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 }