Introducing new opts interface idea :smirk:
diff --git a/openstack/networking/v2/extensions/external/requests.go b/openstack/networking/v2/extensions/external/requests.go
new file mode 100644
index 0000000..0d20bb1
--- /dev/null
+++ b/openstack/networking/v2/extensions/external/requests.go
@@ -0,0 +1,33 @@
+package external
+
+import "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
+
+type CreateOpts struct {
+ Parent networks.CreateOpts
+ External bool
+}
+
+func (o CreateOpts) ToMap() map[string]map[string]interface{} {
+ outer := o.Parent.ToMap()
+
+ outer["network"]["router:external"] = o.External
+
+ return outer
+}
+
+func (o CreateOpts) IsCreateOpts() bool { return true }
+
+type UpdateOpts struct {
+ Parent networks.UpdateOpts
+ External bool
+}
+
+func (o UpdateOpts) ToMap() map[string]map[string]interface{} {
+ outer := o.Parent.ToMap()
+
+ outer["network"]["router:external"] = o.External
+
+ return outer
+}
+
+func (o UpdateOpts) IsUpdateOpts() bool { return true }
diff --git a/openstack/networking/v2/extensions/external/results_test.go b/openstack/networking/v2/extensions/external/results_test.go
index 6c7e69a..9831d8b 100644
--- a/openstack/networking/v2/extensions/external/results_test.go
+++ b/openstack/networking/v2/extensions/external/results_test.go
@@ -182,8 +182,10 @@
`)
})
- options := networks.CreateOpts{External: true}
+ iTrue := true
+ options := CreateOpts{networks.CreateOpts{Name: "ext_net", AdminStateUp: &iTrue}, true}
res := networks.Create(serviceClient(), options)
+
n, err := ExtractCreate(res)
th.AssertNoErr(t, err)
@@ -202,7 +204,8 @@
th.TestJSONRequest(t, r, `
{
"network": {
- "router:external": true
+ "router:external": true,
+ "name": "new_name"
}
}
`)
@@ -215,7 +218,7 @@
"network": {
"admin_state_up": true,
"id": "8d05a1b1-297a-46ca-8974-17debf51ca3c",
- "name": "ext_net",
+ "name": "new_name",
"router:external": true,
"shared": false,
"status": "ACTIVE",
@@ -228,8 +231,7 @@
`)
})
- shared := true
- options := networks.UpdateOpts{External: true}
+ options := UpdateOpts{networks.UpdateOpts{Name: "new_name"}, true}
res := networks.Update(serviceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options)
n, err := ExtractUpdate(res)
diff --git a/openstack/networking/v2/networks/requests.go b/openstack/networking/v2/networks/requests.go
index 3a1613e..180914f 100644
--- a/openstack/networking/v2/networks/requests.go
+++ b/openstack/networking/v2/networks/requests.go
@@ -1,6 +1,7 @@
package networks
import (
+ "fmt"
"strconv"
"github.com/racker/perigee"
@@ -10,7 +11,7 @@
)
type networkOpts struct {
- AdminStateUp bool
+ AdminStateUp *bool
Name string
Shared *bool
TenantID string
@@ -89,13 +90,37 @@
return res
}
-type CreateOpts interface {
- ToMap() map[string]interface{}
+type CreateOptsInt interface {
+ ToMap() map[string]map[string]interface{}
+ IsCreateOpts() bool
}
-// CreateOpts represents the attributes used when creating a new network.
type CreateOpts networkOpts
+func (o CreateOpts) ToMap() map[string]map[string]interface{} {
+ inner := make(map[string]interface{})
+
+ if o.AdminStateUp != nil {
+ inner["admin_state_up"] = &o.AdminStateUp
+ }
+ if o.Name != "" {
+ inner["name"] = o.Name
+ }
+ if o.Shared != nil {
+ inner["shared"] = &o.Shared
+ }
+ if o.TenantID != "" {
+ inner["tenant_id"] = o.TenantID
+ }
+
+ outer := make(map[string]map[string]interface{})
+ outer["network"] = inner
+
+ return outer
+}
+
+func (o CreateOpts) IsCreateOpts() bool { return true }
+
// Create accepts a CreateOpts struct and creates a new network using the values
// provided. This operation does not actually require a request body, i.e. the
// CreateOpts struct argument can be empty.
@@ -103,31 +128,17 @@
// The tenant ID that is contained in the URI is the tenant that creates the
// network. An admin user, however, has the option of specifying another tenant
// ID in the CreateOpts struct.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- // Define structures
- type network struct {
- AdminStateUp bool `json:"admin_state_up,omitempty"`
- Name string `json:"name,omitempty"`
- Shared *bool `json:"shared,omitempty"`
- TenantID *string `json:"tenant_id,omitempty"`
- }
- type request struct {
- Network network `json:"network"`
+func Create(c *gophercloud.ServiceClient, opts CreateOptsInt) CreateResult {
+ var res CreateResult
+
+ if opts.IsCreateOpts() != true {
+ res.Err = fmt.Errorf("Must provide valid create opts")
+ return res
}
- // Populate request body
- reqBody := request{Network: network{
- AdminStateUp: opts.AdminStateUp,
- Name: opts.Name,
- Shared: opts.Shared,
- }}
-
- if opts.TenantID != "" {
- reqBody.Network.TenantID = &opts.TenantID
- }
+ reqBody := opts.ToMap()
// Send request to API
- var res CreateResult
_, err := perigee.Request("POST", createURL(c), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
ReqBody: &reqBody,
@@ -138,32 +149,47 @@
return res
}
-// UpdateOpts represents the attributes used when updating an existing network.
+type UpdateOptsInt interface {
+ ToMap() map[string]map[string]interface{}
+ IsUpdateOpts() bool
+}
+
type UpdateOpts networkOpts
+func (o UpdateOpts) ToMap() map[string]map[string]interface{} {
+ inner := make(map[string]interface{})
+
+ if o.AdminStateUp != nil {
+ inner["admin_state_up"] = &o.AdminStateUp
+ }
+ if o.Name != "" {
+ inner["name"] = o.Name
+ }
+ if o.Shared != nil {
+ inner["shared"] = &o.Shared
+ }
+
+ outer := make(map[string]map[string]interface{})
+ outer["network"] = inner
+
+ return outer
+}
+
+func (o UpdateOpts) IsUpdateOpts() bool { return true }
+
// Update accepts a UpdateOpts struct and updates an existing network using the
// values provided. For more information, see the Create function.
-func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOpts) UpdateResult {
- // Define structures
- type network struct {
- AdminStateUp bool `json:"admin_state_up"`
- Name string `json:"name"`
- Shared *bool `json:"shared,omitempty"`
+func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOptsInt) UpdateResult {
+ var res UpdateResult
+
+ if opts.IsUpdateOpts() != true {
+ res.Err = fmt.Errorf("Must provide valid update opts")
+ return res
}
- type request struct {
- Network network `json:"network"`
- }
-
- // Populate request body
- reqBody := request{Network: network{
- AdminStateUp: opts.AdminStateUp,
- Name: opts.Name,
- Shared: opts.Shared,
- }}
+ reqBody := opts.ToMap()
// Send request to API
- var res UpdateResult
_, err := perigee.Request("PUT", getURL(c, networkID), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
ReqBody: &reqBody,
diff --git a/openstack/networking/v2/networks/requests_test.go b/openstack/networking/v2/networks/requests_test.go
index 4c50b87..cc70354 100644
--- a/openstack/networking/v2/networks/requests_test.go
+++ b/openstack/networking/v2/networks/requests_test.go
@@ -180,7 +180,8 @@
`)
})
- options := CreateOpts{Name: "sample_network", AdminStateUp: true}
+ iTrue := true
+ options := CreateOpts{Name: "sample_network", AdminStateUp: &iTrue}
n, err := Create(ServiceClient(), options).Extract()
th.AssertNoErr(t, err)
@@ -216,8 +217,8 @@
w.WriteHeader(http.StatusCreated)
})
- shared := true
- options := CreateOpts{Name: "sample_network", AdminStateUp: true, Shared: &shared, TenantID: "12345"}
+ iTrue := true
+ options := CreateOpts{Name: "sample_network", AdminStateUp: &iTrue, Shared: &iTrue, TenantID: "12345"}
_, err := Create(ServiceClient(), options).Extract()
th.AssertNoErr(t, err)
}
@@ -259,8 +260,8 @@
`)
})
- shared := true
- options := UpdateOpts{Name: "new_network_name", AdminStateUp: false, Shared: &shared}
+ iTrue, iFalse := true, false
+ options := UpdateOpts{Name: "new_network_name", AdminStateUp: &iFalse, Shared: &iTrue}
n, err := Update(ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options).Extract()
th.AssertNoErr(t, err)