Add update and delete subnet operations :cool:
diff --git a/openstack/networking/v2/subnets/errors.go b/openstack/networking/v2/subnets/errors.go
index 9299927..ca2df72 100644
--- a/openstack/networking/v2/subnets/errors.go
+++ b/openstack/networking/v2/subnets/errors.go
@@ -7,7 +7,9 @@
}
var (
- ErrNetworkIDRequired = err("A network ID is required")
- ErrCIDRRequired = err("A valid CIDR is required")
- ErrInvalidIPType = err("An IP type must either be 4 or 6")
+ ErrNetworkIDRequired = err("A network ID is required")
+ ErrCIDRRequired = err("A valid CIDR is required")
+ ErrInvalidIPType = err("An IP type must either be 4 or 6")
+ ErrCIDRNotUpdatable = err("CIDR attributes cannot be updated")
+ ErrIPVersionNotUpdatable = err("IP Version attributes cannot be updated")
)
diff --git a/openstack/networking/v2/subnets/requests.go b/openstack/networking/v2/subnets/requests.go
index 93641d9..f10bf18 100644
--- a/openstack/networking/v2/subnets/requests.go
+++ b/openstack/networking/v2/subnets/requests.go
@@ -124,16 +124,15 @@
}
reqBody := request{Subnet: subnet{
- NetworkID: opts.NetworkID,
- CIDR: opts.CIDR,
+ NetworkID: opts.NetworkID,
+ CIDR: opts.CIDR,
+ Name: maybeString(opts.Name),
+ TenantID: maybeString(opts.TenantID),
+ GatewayIP: maybeString(opts.GatewayIP),
+ ID: maybeString(opts.ID),
+ EnableDHCP: opts.EnableDHCP,
}}
- reqBody.Subnet.Name = maybeString(opts.Name)
- reqBody.Subnet.TenantID = maybeString(opts.TenantID)
- reqBody.Subnet.GatewayIP = maybeString(opts.GatewayIP)
- reqBody.Subnet.ID = maybeString(opts.ID)
- reqBody.Subnet.EnableDHCP = opts.EnableDHCP
-
if opts.IPVersion != 0 {
reqBody.Subnet.IPVersion = opts.IPVersion
}
@@ -159,3 +158,63 @@
return res.Subnet, nil
}
+
+func Update(c *gophercloud.ServiceClient, id string, opts SubnetOpts) (*Subnet, error) {
+ if opts.CIDR != "" {
+ return nil, ErrCIDRNotUpdatable
+ }
+ if opts.IPVersion != 0 {
+ return nil, ErrIPVersionNotUpdatable
+ }
+
+ type subnet struct {
+ NetworkID string `json:"network_id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ TenantID *string `json:"tenant_id,omitempty"`
+ AllocationPools []AllocationPool `json:"allocation_pools,omitempty"`
+ GatewayIP *string `json:"gateway_ip,omitempty"`
+ ID *string `json:"id,omitempty"`
+ EnableDHCP *bool `json:"enable_dhcp,omitempty"`
+ }
+ type request struct {
+ Subnet subnet `json:"subnet"`
+ }
+
+ reqBody := request{Subnet: subnet{
+ NetworkID: opts.NetworkID,
+ Name: maybeString(opts.Name),
+ TenantID: maybeString(opts.TenantID),
+ GatewayIP: maybeString(opts.GatewayIP),
+ ID: maybeString(opts.ID),
+ EnableDHCP: opts.EnableDHCP,
+ }}
+
+ if len(opts.AllocationPools) != 0 {
+ reqBody.Subnet.AllocationPools = opts.AllocationPools
+ }
+
+ type response struct {
+ Subnet *Subnet `json:"subnet"`
+ }
+
+ var res response
+ _, err := perigee.Request("PUT", UpdateURL(c, id), perigee.Options{
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
+ ReqBody: &reqBody,
+ Results: &res,
+ OkCodes: []int{201},
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return res.Subnet, nil
+}
+
+func Delete(c *gophercloud.ServiceClient, id string) error {
+ _, err := perigee.Request("DELETE", DeleteURL(c, id), perigee.Options{
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
+ OkCodes: []int{204},
+ })
+ return err
+}
diff --git a/openstack/networking/v2/subnets/requests_test.go b/openstack/networking/v2/subnets/requests_test.go
index f5716cf..edf59e7 100644
--- a/openstack/networking/v2/subnets/requests_test.go
+++ b/openstack/networking/v2/subnets/requests_test.go
@@ -258,3 +258,78 @@
th.AssertEquals(t, s.CIDR, "192.168.199.0/24")
th.AssertEquals(t, s.ID, "3b80198d-4f7b-4f77-9ef5-774d54e17126")
}
+
+func TestUpdate(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ th.Mux.HandleFunc("/v2.0/subnets/08eae331-0402-425a-923c-34f7cfe39c1b", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "PUT")
+ th.TestHeader(t, r, "X-Auth-Token", TokenID)
+ th.TestHeader(t, r, "Content-Type", "application/json")
+ th.TestHeader(t, r, "Accept", "application/json")
+ th.TestJSONRequest(t, r, `
+{
+ "subnet": {
+ "name": "my_new_subnet"
+ }
+}
+ `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusCreated)
+
+ fmt.Fprintf(w, `
+{
+ "subnet": {
+ "name": "my_new_subnet",
+ "enable_dhcp": true,
+ "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
+ "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e",
+ "dns_nameservers": [],
+ "allocation_pools": [
+ {
+ "start": "10.0.0.2",
+ "end": "10.0.0.254"
+ }
+ ],
+ "host_routes": [],
+ "ip_version": 4,
+ "gateway_ip": "10.0.0.1",
+ "cidr": "10.0.0.0/24",
+ "id": "08eae331-0402-425a-923c-34f7cfe39c1b"
+ }
+}
+ `)
+ })
+
+ opts := SubnetOpts{Name: "my_new_subnet"}
+ s, err := Update(ServiceClient(), "08eae331-0402-425a-923c-34f7cfe39c1b", opts)
+ th.AssertNoErr(t, err)
+
+ th.AssertEquals(t, s.Name, "my_new_subnet")
+ th.AssertEquals(t, s.ID, "08eae331-0402-425a-923c-34f7cfe39c1b")
+}
+
+func TestCertainAttrsCannotBeUpdated(t *testing.T) {
+ opts := SubnetOpts{IPVersion: 6, CIDR: "192.0.0.1/24"}
+ _, err := Update(ServiceClient(), "08eae331-0402-425a-923c-34f7cfe39c1b", opts)
+
+ if err == nil {
+ t.Errorf("An error was expected when updating IPVersion and CIDR, none was raised")
+ }
+}
+
+func TestDelete(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ th.Mux.HandleFunc("/v2.0/subnets/08eae331-0402-425a-923c-34f7cfe39c1b", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "DELETE")
+ th.TestHeader(t, r, "X-Auth-Token", TokenID)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ err := Delete(ServiceClient(), "08eae331-0402-425a-923c-34f7cfe39c1b")
+ th.AssertNoErr(t, err)
+}
diff --git a/openstack/networking/v2/subnets/urls.go b/openstack/networking/v2/subnets/urls.go
index 485f97a..fe20c53 100644
--- a/openstack/networking/v2/subnets/urls.go
+++ b/openstack/networking/v2/subnets/urls.go
@@ -23,3 +23,11 @@
func CreateURL(c *gophercloud.ServiceClient) string {
return RootURL(c)
}
+
+func UpdateURL(c *gophercloud.ServiceClient, id string) string {
+ return ResourceURL(c, id)
+}
+
+func DeleteURL(c *gophercloud.ServiceClient, id string) string {
+ return ResourceURL(c, id)
+}
diff --git a/openstack/networking/v2/subnets/urls_tests.go b/openstack/networking/v2/subnets/urls_tests.go
index 336e2fe..eec5275 100644
--- a/openstack/networking/v2/subnets/urls_tests.go
+++ b/openstack/networking/v2/subnets/urls_tests.go
@@ -30,3 +30,15 @@
expected := Endpoint + "v2.0/subnets"
th.AssertEquals(t, expected, actual)
}
+
+func TestUpdateURL(t *testing.T) {
+ actual := UpdateURL(EndpointClient(), "foo")
+ expected := Endpoint + "v2.0/subnets/foo"
+ th.AssertEquals(t, expected, actual)
+}
+
+func TestDeleteURL(t *testing.T) {
+ actual := DeleteURL(EndpointClient(), "foo")
+ expected := Endpoint + "v2.0/subnets/foo"
+ th.AssertEquals(t, expected, actual)
+}