@@ -114,10 +114,91 @@ func resourceNetworkingSubnetV2() *schema.Resource {
114114 },
115115 },
116116 },
117+ "value_specs" : & schema.Schema {
118+ Type : schema .TypeMap ,
119+ Optional : true ,
120+ ForceNew : true ,
121+ },
117122 },
118123 }
119124}
120125
126+ // SubnetCreateOpts represents the attributes used when creating a new subnet.
127+ type SubnetCreateOpts struct {
128+ // Required
129+ NetworkID string
130+ CIDR string
131+ // Optional
132+ Name string
133+ TenantID string
134+ AllocationPools []subnets.AllocationPool
135+ GatewayIP string
136+ NoGateway bool
137+ IPVersion int
138+ EnableDHCP * bool
139+ DNSNameservers []string
140+ HostRoutes []subnets.HostRoute
141+ ValueSpecs map [string ]string
142+ }
143+
144+ // ToSubnetCreateMap casts a CreateOpts struct to a map.
145+ func (opts SubnetCreateOpts ) ToSubnetCreateMap () (map [string ]interface {}, error ) {
146+ s := make (map [string ]interface {})
147+
148+ if opts .NetworkID == "" {
149+ return nil , fmt .Errorf ("A network ID is required" )
150+ }
151+ if opts .CIDR == "" {
152+ return nil , fmt .Errorf ("A valid CIDR is required" )
153+ }
154+ if opts .IPVersion != 0 && opts .IPVersion != subnets .IPv4 && opts .IPVersion != subnets .IPv6 {
155+ return nil , fmt .Errorf ("An IP type must either be 4 or 6" )
156+ }
157+
158+ // Both GatewayIP and NoGateway should not be set
159+ if opts .GatewayIP != "" && opts .NoGateway {
160+ return nil , fmt .Errorf ("Both disabling the gateway and specifying a gateway is not allowed" )
161+ }
162+
163+ s ["network_id" ] = opts .NetworkID
164+ s ["cidr" ] = opts .CIDR
165+
166+ if opts .EnableDHCP != nil {
167+ s ["enable_dhcp" ] = & opts .EnableDHCP
168+ }
169+ if opts .Name != "" {
170+ s ["name" ] = opts .Name
171+ }
172+ if opts .GatewayIP != "" {
173+ s ["gateway_ip" ] = opts .GatewayIP
174+ } else if opts .NoGateway {
175+ s ["gateway_ip" ] = nil
176+ }
177+ if opts .TenantID != "" {
178+ s ["tenant_id" ] = opts .TenantID
179+ }
180+ if opts .IPVersion != 0 {
181+ s ["ip_version" ] = opts .IPVersion
182+ }
183+ if len (opts .AllocationPools ) != 0 {
184+ s ["allocation_pools" ] = opts .AllocationPools
185+ }
186+ if len (opts .DNSNameservers ) != 0 {
187+ s ["dns_nameservers" ] = opts .DNSNameservers
188+ }
189+ if len (opts .HostRoutes ) != 0 {
190+ s ["host_routes" ] = opts .HostRoutes
191+ }
192+
193+ if opts .ValueSpecs != nil {
194+ for k , v := range opts .ValueSpecs {
195+ s [k ] = v
196+ }
197+ }
198+
199+ return map [string ]interface {}{"subnet" : s }, nil
200+ }
201+
121202func resourceNetworkingSubnetV2Create (d * schema.ResourceData , meta interface {}) error {
122203 config := meta .(* Config )
123204 networkingClient , err := config .networkingV2Client (d .Get ("region" ).(string ))
@@ -133,7 +214,7 @@ func resourceNetworkingSubnetV2Create(d *schema.ResourceData, meta interface{})
133214
134215 enableDHCP := d .Get ("enable_dhcp" ).(bool )
135216
136- createOpts := subnets. CreateOpts {
217+ createOpts := SubnetCreateOpts {
137218 NetworkID : d .Get ("network_id" ).(string ),
138219 CIDR : d .Get ("cidr" ).(string ),
139220 Name : d .Get ("name" ).(string ),
@@ -145,6 +226,7 @@ func resourceNetworkingSubnetV2Create(d *schema.ResourceData, meta interface{})
145226 DNSNameservers : resourceSubnetDNSNameserversV2 (d ),
146227 HostRoutes : resourceSubnetHostRoutesV2 (d ),
147228 EnableDHCP : & enableDHCP ,
229+ ValueSpecs : subnetValueSpecs (d ),
148230 }
149231
150232 log .Printf ("[DEBUG] Create Options: %#v" , createOpts )
@@ -354,3 +436,11 @@ func waitForSubnetDelete(networkingClient *gophercloud.ServiceClient, subnetId s
354436 return s , "ACTIVE" , nil
355437 }
356438}
439+
440+ func subnetValueSpecs (d * schema.ResourceData ) map [string ]string {
441+ m := make (map [string ]string )
442+ for key , val := range d .Get ("value_specs" ).(map [string ]interface {}) {
443+ m [key ] = val .(string )
444+ }
445+ return m
446+ }
0 commit comments