github.com/juju/charm/v11@v11.2.0/extra_bindings.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the LGPLv3, see LICENCE file for details.
     3  
     4  package charm
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/juju/collections/set"
    11  	"github.com/juju/schema"
    12  )
    13  
    14  // ExtraBinding represents an extra bindable endpoint that is not a relation.
    15  type ExtraBinding struct {
    16  	Name string `bson:"name" json:"Name"`
    17  }
    18  
    19  // When specified, the "extra-bindings" section in the metadata.yaml
    20  // should have the following format:
    21  //
    22  // extra-bindings:
    23  //     "<endpoint-name>":
    24  //     ...
    25  // Endpoint names are strings and must not match existing relation names from
    26  // the Provides, Requires, or Peers metadata sections. The values beside each
    27  // endpoint name must be left out (i.e. "foo": <anything> is invalid).
    28  var extraBindingsSchema = schema.Map(schema.NonEmptyString("binding name"), schema.Nil(""))
    29  
    30  func parseMetaExtraBindings(data interface{}) (map[string]ExtraBinding, error) {
    31  	if data == nil {
    32  		return nil, nil
    33  	}
    34  
    35  	bindingsMap := data.(map[interface{}]interface{})
    36  	result := make(map[string]ExtraBinding)
    37  	for name, _ := range bindingsMap {
    38  		stringName := name.(string)
    39  		result[stringName] = ExtraBinding{Name: stringName}
    40  	}
    41  
    42  	return result, nil
    43  }
    44  
    45  func validateMetaExtraBindings(meta Meta) error {
    46  	extraBindings := meta.ExtraBindings
    47  	if extraBindings == nil {
    48  		return nil
    49  	} else if len(extraBindings) == 0 {
    50  		return fmt.Errorf("extra bindings cannot be empty when specified")
    51  	}
    52  
    53  	usedExtraNames := set.NewStrings()
    54  	for name, binding := range extraBindings {
    55  		if binding.Name == "" || name == "" {
    56  			return fmt.Errorf("missing binding name")
    57  		}
    58  		if binding.Name != name {
    59  			return fmt.Errorf("mismatched extra binding name: got %q, expected %q", binding.Name, name)
    60  		}
    61  		usedExtraNames.Add(name)
    62  	}
    63  
    64  	usedRelationNames := set.NewStrings()
    65  	for relationName, _ := range meta.CombinedRelations() {
    66  		usedRelationNames.Add(relationName)
    67  	}
    68  	notAllowedNames := usedExtraNames.Intersection(usedRelationNames)
    69  	if !notAllowedNames.IsEmpty() {
    70  		notAllowedList := strings.Join(notAllowedNames.SortedValues(), ", ")
    71  		return fmt.Errorf("relation names (%s) cannot be used in extra bindings", notAllowedList)
    72  	}
    73  	return nil
    74  }