github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/address.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package description 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/schema" 9 ) 10 11 // AddressArgs is an argument struct used to create a new internal address 12 // type that supports the Address interface. 13 type AddressArgs struct { 14 Value string 15 Type string 16 Scope string 17 Origin string 18 } 19 20 func newAddress(args AddressArgs) *address { 21 return &address{ 22 Version: 1, 23 Value_: args.Value, 24 Type_: args.Type, 25 Scope_: args.Scope, 26 Origin_: args.Origin, 27 } 28 } 29 30 // address represents an IP Address of some form. 31 type address struct { 32 Version int `yaml:"version"` 33 34 Value_ string `yaml:"value"` 35 Type_ string `yaml:"type"` 36 Scope_ string `yaml:"scope,omitempty"` 37 Origin_ string `yaml:"origin,omitempty"` 38 } 39 40 // Value implements Address. 41 func (a *address) Value() string { 42 return a.Value_ 43 } 44 45 // Type implements Address. 46 func (a *address) Type() string { 47 return a.Type_ 48 } 49 50 // Scope implements Address. 51 func (a *address) Scope() string { 52 return a.Scope_ 53 } 54 55 // Origin implements Address. 56 func (a *address) Origin() string { 57 return a.Origin_ 58 } 59 60 func importAddresses(sourceList []interface{}) ([]*address, error) { 61 var result []*address 62 for i, value := range sourceList { 63 source, ok := value.(map[string]interface{}) 64 if !ok { 65 return nil, errors.Errorf("unexpected value for address %d, %T", i, value) 66 } 67 addr, err := importAddress(source) 68 if err != nil { 69 return nil, errors.Trace(err) 70 } 71 result = append(result, addr) 72 } 73 return result, nil 74 } 75 76 // importAddress constructs a new Address from a map representing a serialised 77 // Address instance. 78 func importAddress(source map[string]interface{}) (*address, error) { 79 version, err := getVersion(source) 80 if err != nil { 81 return nil, errors.Annotate(err, "address version schema check failed") 82 } 83 84 importFunc, ok := addressDeserializationFuncs[version] 85 if !ok { 86 return nil, errors.NotValidf("version %d", version) 87 } 88 89 return importFunc(source) 90 } 91 92 type addressDeserializationFunc func(map[string]interface{}) (*address, error) 93 94 var addressDeserializationFuncs = map[int]addressDeserializationFunc{ 95 1: importAddressV1, 96 } 97 98 func importAddressV1(source map[string]interface{}) (*address, error) { 99 fields := schema.Fields{ 100 "value": schema.String(), 101 "type": schema.String(), 102 "scope": schema.String(), 103 "origin": schema.String(), 104 } 105 // Some values don't have to be there. 106 defaults := schema.Defaults{ 107 "scope": "", 108 "origin": "", 109 } 110 checker := schema.FieldMap(fields, defaults) 111 112 coerced, err := checker.Coerce(source, nil) 113 if err != nil { 114 return nil, errors.Annotatef(err, "address v1 schema check failed") 115 } 116 valid := coerced.(map[string]interface{}) 117 // From here we know that the map returned from the schema coercion 118 // contains fields of the right type. 119 120 return &address{ 121 Version: 1, 122 Value_: valid["value"].(string), 123 Type_: valid["type"].(string), 124 Scope_: valid["scope"].(string), 125 Origin_: valid["origin"].(string), 126 }, nil 127 }