github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/subnet.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 type subnets struct { 12 Version int `yaml:"version"` 13 Subnets_ []*subnet `yaml:"subnets"` 14 } 15 16 type subnet struct { 17 ProviderId_ string `yaml:"provider-id,omitempty"` 18 CIDR_ string `yaml:"cidr"` 19 VLANTag_ int `yaml:"vlan-tag"` 20 21 AvailabilityZone_ string `yaml:"availability-zone"` 22 SpaceName_ string `yaml:"space-name"` 23 24 // These will be deprecated once the address allocation strategy for 25 // EC2 is changed. They are unused already on MAAS. 26 AllocatableIPHigh_ string `yaml:"allocatable-ip-high,omitempty"` 27 AllocatableIPLow_ string `yaml:"allocatable-ip-low,omitempty"` 28 } 29 30 // SubnetArgs is an argument struct used to create a 31 // new internal subnet type that supports the Subnet interface. 32 type SubnetArgs struct { 33 ProviderId string 34 CIDR string 35 VLANTag int 36 AvailabilityZone string 37 SpaceName string 38 39 // These will be deprecated once the address allocation strategy for 40 // EC2 is changed. They are unused already on MAAS. 41 AllocatableIPHigh string 42 AllocatableIPLow string 43 } 44 45 func newSubnet(args SubnetArgs) *subnet { 46 return &subnet{ 47 ProviderId_: string(args.ProviderId), 48 SpaceName_: args.SpaceName, 49 CIDR_: args.CIDR, 50 VLANTag_: args.VLANTag, 51 AvailabilityZone_: args.AvailabilityZone, 52 AllocatableIPHigh_: args.AllocatableIPHigh, 53 AllocatableIPLow_: args.AllocatableIPLow, 54 } 55 } 56 57 // ProviderId implements Subnet. 58 func (s *subnet) ProviderId() string { 59 return s.ProviderId_ 60 } 61 62 // SpaceName implements Subnet. 63 func (s *subnet) SpaceName() string { 64 return s.SpaceName_ 65 } 66 67 // CIDR implements Subnet. 68 func (s *subnet) CIDR() string { 69 return s.CIDR_ 70 } 71 72 // VLANTag implements Subnet. 73 func (s *subnet) VLANTag() int { 74 return s.VLANTag_ 75 } 76 77 // AvailabilityZone implements Subnet. 78 func (s *subnet) AvailabilityZone() string { 79 return s.AvailabilityZone_ 80 } 81 82 // AllocatableIPHigh implements Subnet. 83 func (s *subnet) AllocatableIPHigh() string { 84 return s.AllocatableIPHigh_ 85 } 86 87 // AllocatableIPLow implements Subnet. 88 func (s *subnet) AllocatableIPLow() string { 89 return s.AllocatableIPLow_ 90 } 91 92 func importSubnets(source map[string]interface{}) ([]*subnet, error) { 93 checker := versionedChecker("subnets") 94 coerced, err := checker.Coerce(source, nil) 95 if err != nil { 96 return nil, errors.Annotatef(err, "subnets version schema check failed") 97 } 98 valid := coerced.(map[string]interface{}) 99 100 version := int(valid["version"].(int64)) 101 importFunc, ok := subnetDeserializationFuncs[version] 102 if !ok { 103 return nil, errors.NotValidf("version %d", version) 104 } 105 sourceList := valid["subnets"].([]interface{}) 106 return importSubnetList(sourceList, importFunc) 107 } 108 109 func importSubnetList(sourceList []interface{}, importFunc subnetDeserializationFunc) ([]*subnet, error) { 110 result := make([]*subnet, 0, len(sourceList)) 111 for i, value := range sourceList { 112 source, ok := value.(map[string]interface{}) 113 if !ok { 114 return nil, errors.Errorf("unexpected value for subnet %d, %T", i, value) 115 } 116 subnet, err := importFunc(source) 117 if err != nil { 118 return nil, errors.Annotatef(err, "subnet %d", i) 119 } 120 result = append(result, subnet) 121 } 122 return result, nil 123 } 124 125 type subnetDeserializationFunc func(map[string]interface{}) (*subnet, error) 126 127 var subnetDeserializationFuncs = map[int]subnetDeserializationFunc{ 128 1: importSubnetV1, 129 } 130 131 func importSubnetV1(source map[string]interface{}) (*subnet, error) { 132 fields := schema.Fields{ 133 "cidr": schema.String(), 134 "provider-id": schema.String(), 135 "vlan-tag": schema.Int(), 136 "space-name": schema.String(), 137 "availability-zone": schema.String(), 138 "allocatable-ip-high": schema.String(), 139 "allocatable-ip-low": schema.String(), 140 } 141 142 defaults := schema.Defaults{ 143 "provider-id": "", 144 "allocatable-ip-high": "", 145 "allocatable-ip-low": "", 146 } 147 checker := schema.FieldMap(fields, defaults) 148 149 coerced, err := checker.Coerce(source, nil) 150 if err != nil { 151 return nil, errors.Annotatef(err, "subnet v1 schema check failed") 152 } 153 valid := coerced.(map[string]interface{}) 154 155 // From here we know that the map returned from the schema coercion 156 // contains fields of the right type. 157 return &subnet{ 158 CIDR_: valid["cidr"].(string), 159 ProviderId_: valid["provider-id"].(string), 160 VLANTag_: int(valid["vlan-tag"].(int64)), 161 SpaceName_: valid["space-name"].(string), 162 AvailabilityZone_: valid["availability-zone"].(string), 163 AllocatableIPHigh_: valid["allocatable-ip-high"].(string), 164 AllocatableIPLow_: valid["allocatable-ip-low"].(string), 165 }, nil 166 }