consistency updates; struct opts -> interface opts (networking, compute)
diff --git a/openstack/blockstorage/v1/snapshots/requests.go b/openstack/blockstorage/v1/snapshots/requests.go
index f54432f..1bc0a14 100644
--- a/openstack/blockstorage/v1/snapshots/requests.go
+++ b/openstack/blockstorage/v1/snapshots/requests.go
@@ -72,7 +72,7 @@
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
MoreHeaders: client.Provider.AuthenticatedHeaders(),
OkCodes: []int{200, 201},
- ReqBody: reqBody,
+ ReqBody: &reqBody,
Results: &res.Resp,
})
return res
@@ -102,7 +102,7 @@
// ListOptsBuilder allows extensions to add additional parameters to the List
// request.
type ListOptsBuilder interface {
- ToVolumeListParams() (string, error)
+ ToSnapshotListString() (string, error)
}
// ListOpts hold options for listing Snapshots. It is passed to the
@@ -113,8 +113,8 @@
VolumeID string `q:"volume_id"`
}
-// ToVolumeListParams formats a ListOpts into a query string.
-func (opts ListOpts) ToVolumeListParams() (string, error) {
+// ToSnapshotListString formats a ListOpts into a query string.
+func (opts ListOpts) ToSnapshotListString() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
@@ -127,7 +127,7 @@
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listURL(client)
if opts != nil {
- query, err := opts.ToVolumeListParams()
+ query, err := opts.ToSnapshotListString()
if err != nil {
return pagination.Pager{Err: err}
}
@@ -180,7 +180,7 @@
_, res.Err = perigee.Request("PUT", updateMetadataURL(client, id), perigee.Options{
MoreHeaders: client.Provider.AuthenticatedHeaders(),
OkCodes: []int{200},
- ReqBody: reqBody,
+ ReqBody: &reqBody,
Results: &res.Resp,
})
return res
diff --git a/openstack/blockstorage/v1/volumes/requests.go b/openstack/blockstorage/v1/volumes/requests.go
index dc04732..f46b2b6 100644
--- a/openstack/blockstorage/v1/volumes/requests.go
+++ b/openstack/blockstorage/v1/volumes/requests.go
@@ -87,7 +87,7 @@
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
MoreHeaders: client.Provider.AuthenticatedHeaders(),
- ReqBody: reqBody,
+ ReqBody: &reqBody,
Results: &res.Resp,
OkCodes: []int{200, 201},
})
@@ -118,7 +118,7 @@
// ListOptsBuilder allows extensions to add additional parameters to the List
// request.
type ListOptsBuilder interface {
- ToVolumeListParams() (string, error)
+ ToVolumeListString() (string, error)
}
// ListOpts holds options for listing Volumes. It is passed to the volumes.List
@@ -134,8 +134,8 @@
Status string `q:"status"`
}
-// ToVolumeListParams formats a ListOpts into a query string.
-func (opts ListOpts) ToVolumeListParams() (string, error) {
+// ToVolumeListString formats a ListOpts into a query string.
+func (opts ListOpts) ToVolumeListString() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
@@ -147,7 +147,7 @@
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listURL(client)
if opts != nil {
- query, err := opts.ToVolumeListParams()
+ query, err := opts.ToVolumeListString()
if err != nil {
return pagination.Pager{Err: err}
}
@@ -197,7 +197,7 @@
// Update will update the Volume with provided information. To extract the updated
// Volume from the response, call the Extract method on the UpdateResult.
-func Update(client *gophercloud.ServiceClient, id string, opts *UpdateOpts) UpdateResult {
+func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
reqBody, err := opts.ToVolumeUpdateMap()
@@ -209,7 +209,7 @@
_, res.Err = perigee.Request("PUT", updateURL(client, id), perigee.Options{
MoreHeaders: client.Provider.AuthenticatedHeaders(),
OkCodes: []int{200},
- ReqBody: reqBody,
+ ReqBody: &reqBody,
Results: &res.Resp,
})
return res
diff --git a/openstack/blockstorage/v1/volumetypes/requests.go b/openstack/blockstorage/v1/volumetypes/requests.go
index ff71de1..d4f880f 100644
--- a/openstack/blockstorage/v1/volumetypes/requests.go
+++ b/openstack/blockstorage/v1/volumetypes/requests.go
@@ -9,7 +9,7 @@
// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
- ToVolumeTypeCreateMap() map[string]interface{}
+ ToVolumeTypeCreateMap() (map[string]interface{}, error)
}
// CreateOpts are options for creating a volume type.
@@ -21,7 +21,7 @@
}
// ToVolumeTypeCreateMap casts a CreateOpts struct to a map.
-func (opts CreateOpts) ToVolumeTypeCreateMap() map[string]interface{} {
+func (opts CreateOpts) ToVolumeTypeCreateMap() (map[string]interface{}, error) {
vt := make(map[string]interface{})
if opts.ExtraSpecs != nil {
@@ -31,17 +31,24 @@
vt["name"] = opts.Name
}
- return map[string]interface{}{"volume_type": vt}
+ return map[string]interface{}{"volume_type": vt}, nil
}
// Create will create a new volume. To extract the created volume type object,
// call the Extract method on the CreateResult.
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
+
+ reqBody, err := opts.ToVolumeTypeCreateMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
+
_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
MoreHeaders: client.Provider.AuthenticatedHeaders(),
OkCodes: []int{200, 201},
- ReqBody: opts.ToVolumeTypeCreateMap(),
+ ReqBody: &reqBody,
Results: &res.Resp,
})
return res
diff --git a/openstack/compute/v2/flavors/requests.go b/openstack/compute/v2/flavors/requests.go
index 4b89b1a..469c69d 100644
--- a/openstack/compute/v2/flavors/requests.go
+++ b/openstack/compute/v2/flavors/requests.go
@@ -6,6 +6,12 @@
"github.com/rackspace/gophercloud/pagination"
)
+// ListOptsBuilder allows extensions to add additional parameters to the
+// List request.
+type ListOptsBuilder interface {
+ ToFlavorListParams() (string, error)
+}
+
// ListOpts helps control the results returned by the List() function.
// For example, a flavor with a minDisk field of 10 will not be returned if you specify MinDisk set to 20.
// Typically, software will use the last ID of the previous call to List to set the Marker for the current call.
@@ -26,17 +32,26 @@
Limit int `q:"limit"`
}
+// ToFlavorListParams formats a ListOpts into a query string.
+func (opts ListOpts) ToFlavorListParams() (string, error) {
+ q, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return "", err
+ }
+ return q.String(), nil
+}
+
// List instructs OpenStack to provide a list of flavors.
// You may provide criteria by which List curtails its results for easier processing.
// See ListOpts for more details.
-func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
+func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listURL(client)
if opts != nil {
- query, err := gophercloud.BuildQueryString(opts)
+ query, err := opts.ToFlavorListParams()
if err != nil {
return pagination.Pager{Err: err}
}
- url += query.String()
+ url += query
}
createPage := func(r pagination.LastHTTPResponse) pagination.Page {
return FlavorPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
diff --git a/openstack/compute/v2/images/requests.go b/openstack/compute/v2/images/requests.go
index 6ccffc4..d901f6e 100644
--- a/openstack/compute/v2/images/requests.go
+++ b/openstack/compute/v2/images/requests.go
@@ -1,11 +1,18 @@
package images
import (
- "github.com/racker/perigee"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
+
+ "github.com/racker/perigee"
)
+// ListOptsBuilder allows extensions to add additional parameters to the
+// List request.
+type ListOptsBuilder interface {
+ ToImageListParams() (string, error)
+}
+
// ListOpts contain options for limiting the number of Images returned from a call to ListDetail.
type ListOpts struct {
// When the image last changed status (in date-time format).
@@ -24,15 +31,24 @@
Type string `q:"type"`
}
+// ToImageListParams formats a ListOpts into a query string.
+func (opts ListOpts) ToImageListParams() (string, error) {
+ q, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return "", err
+ }
+ return q.String(), nil
+}
+
// ListDetail enumerates the available images.
-func ListDetail(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
+func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listDetailURL(client)
if opts != nil {
- query, err := gophercloud.BuildQueryString(opts)
+ query, err := opts.ToImageListParams()
if err != nil {
return pagination.Pager{Err: err}
}
- url += query.String()
+ url += query
}
createPage := func(r pagination.LastHTTPResponse) pagination.Page {
diff --git a/openstack/networking/v2/extensions/external/requests.go b/openstack/networking/v2/extensions/external/requests.go
index afdd428..2f04593 100644
--- a/openstack/networking/v2/extensions/external/requests.go
+++ b/openstack/networking/v2/extensions/external/requests.go
@@ -24,12 +24,15 @@
}
// ToNetworkCreateMap casts a CreateOpts struct to a map.
-func (o CreateOpts) ToNetworkCreateMap() map[string]map[string]interface{} {
- outer := o.Parent.ToNetworkCreateMap()
+func (o CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
+ outer, err := o.Parent.ToNetworkCreateMap()
+ if err != nil {
+ return nil, err
+ }
- outer["network"]["router:external"] = o.External
+ outer["network"].(map[string]interface{})["router:external"] = o.External
- return outer
+ return outer, nil
}
// UpdateOpts is the structure used when updating existing external network
@@ -41,10 +44,13 @@
}
// ToNetworkUpdateMap casts an UpdateOpts struct to a map.
-func (o UpdateOpts) ToNetworkUpdateMap() map[string]map[string]interface{} {
- outer := o.Parent.ToNetworkUpdateMap()
+func (o UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
+ outer, err := o.Parent.ToNetworkUpdateMap()
+ if err != nil {
+ return nil, err
+ }
- outer["network"]["router:external"] = o.External
+ outer["network"].(map[string]interface{})["router:external"] = o.External
- return outer
+ return outer, nil
}
diff --git a/openstack/networking/v2/networks/requests.go b/openstack/networking/v2/networks/requests.go
index 39a151a..de34989 100644
--- a/openstack/networking/v2/networks/requests.go
+++ b/openstack/networking/v2/networks/requests.go
@@ -1,9 +1,10 @@
package networks
import (
- "github.com/racker/perigee"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
+
+ "github.com/racker/perigee"
)
// AdminState gives users a solid type to work with for create and update
@@ -26,6 +27,12 @@
TenantID string
}
+// ListOptsBuilder allows extensions to add additional parameters to the
+// List request.
+type ListOptsBuilder interface {
+ ToNetworkListString() (string, error)
+}
+
// ListOpts allows the filtering and sorting of paginated collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the network attributes you want to see returned. SortKey allows you to sort
@@ -44,17 +51,29 @@
SortDir string `q:"sort_dir"`
}
+// ToNetworkListString formats a ListOpts into a query string.
+func (opts ListOpts) ToNetworkListString() (string, error) {
+ q, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return "", err
+ }
+ return q.String(), nil
+}
+
// List returns a Pager which allows you to iterate over a collection of
// networks. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
-func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
- // Build query parameters
- q, err := gophercloud.BuildQueryString(&opts)
- if err != nil {
- return pagination.Pager{Err: err}
+func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
+ url := listURL(c)
+ if opts != nil {
+ query, err := opts.ToNetworkListString()
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ url += query
}
- u := listURL(c) + q.String()
- return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
+
+ return pagination.NewPager(c, url, func(r pagination.LastHTTPResponse) pagination.Page {
return NetworkPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
})
}
@@ -75,7 +94,7 @@
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type CreateOptsBuilder interface {
- ToNetworkCreateMap() map[string]map[string]interface{}
+ ToNetworkCreateMap() (map[string]interface{}, error)
}
// CreateOpts is the common options struct used in this package's Create
@@ -83,26 +102,23 @@
type CreateOpts networkOpts
// ToNetworkCreateMap casts a CreateOpts struct to a map.
-func (o CreateOpts) ToNetworkCreateMap() map[string]map[string]interface{} {
- inner := make(map[string]interface{})
+func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
+ n := make(map[string]interface{})
- if o.AdminStateUp != nil {
- inner["admin_state_up"] = &o.AdminStateUp
+ if opts.AdminStateUp != nil {
+ n["admin_state_up"] = &opts.AdminStateUp
}
- if o.Name != "" {
- inner["name"] = o.Name
+ if opts.Name != "" {
+ n["name"] = opts.Name
}
- if o.Shared != nil {
- inner["shared"] = &o.Shared
+ if opts.Shared != nil {
+ n["shared"] = &opts.Shared
}
- if o.TenantID != "" {
- inner["tenant_id"] = o.TenantID
+ if opts.TenantID != "" {
+ n["tenant_id"] = opts.TenantID
}
- outer := make(map[string]map[string]interface{})
- outer["network"] = inner
-
- return outer
+ return map[string]interface{}{"network": n}, nil
}
// Create accepts a CreateOpts struct and creates a new network using the values
@@ -115,7 +131,11 @@
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
- reqBody := opts.ToNetworkCreateMap()
+ reqBody, err := opts.ToNetworkCreateMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
// Send request to API
_, res.Err = perigee.Request("POST", createURL(c), perigee.Options{
@@ -132,7 +152,7 @@
// extensions decorate or modify the common logic, it is useful for them to
// satisfy a basic interface in order for them to be used.
type UpdateOptsBuilder interface {
- ToNetworkUpdateMap() map[string]map[string]interface{}
+ ToNetworkUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts is the common options struct used in this package's Update
@@ -140,23 +160,20 @@
type UpdateOpts networkOpts
// ToNetworkUpdateMap casts a UpdateOpts struct to a map.
-func (o UpdateOpts) ToNetworkUpdateMap() map[string]map[string]interface{} {
- inner := make(map[string]interface{})
+func (opts UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
+ n := make(map[string]interface{})
- if o.AdminStateUp != nil {
- inner["admin_state_up"] = &o.AdminStateUp
+ if opts.AdminStateUp != nil {
+ n["admin_state_up"] = &opts.AdminStateUp
}
- if o.Name != "" {
- inner["name"] = o.Name
+ if opts.Name != "" {
+ n["name"] = opts.Name
}
- if o.Shared != nil {
- inner["shared"] = &o.Shared
+ if opts.Shared != nil {
+ n["shared"] = &opts.Shared
}
- outer := make(map[string]map[string]interface{})
- outer["network"] = inner
-
- return outer
+ return map[string]interface{}{"network": n}, nil
}
// Update accepts a UpdateOpts struct and updates an existing network using the
@@ -164,7 +181,11 @@
func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
- reqBody := opts.ToNetworkUpdateMap()
+ reqBody, err := opts.ToNetworkUpdateMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
// Send request to API
_, res.Err = perigee.Request("PUT", getURL(c, networkID), perigee.Options{
diff --git a/openstack/networking/v2/ports/requests.go b/openstack/networking/v2/ports/requests.go
index 0fbb9f2..afa37f5 100644
--- a/openstack/networking/v2/ports/requests.go
+++ b/openstack/networking/v2/ports/requests.go
@@ -1,9 +1,10 @@
package ports
import (
- "github.com/racker/perigee"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
+
+ "github.com/racker/perigee"
)
// AdminState gives users a solid type to work with for create and update
@@ -19,6 +20,12 @@
Down AdminState = &iFalse
)
+// ListOptsBuilder allows extensions to add additional parameters to the
+// List request.
+type ListOptsBuilder interface {
+ ToPortListString() (string, error)
+}
+
// ListOpts allows the filtering and sorting of paginated collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the port attributes you want to see returned. SortKey allows you to sort
@@ -40,6 +47,15 @@
SortDir string `q:"sort_dir"`
}
+// ToPortListString formats a ListOpts into a query string.
+func (opts ListOpts) ToPortListString() (string, error) {
+ q, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return "", err
+ }
+ return q.String(), nil
+}
+
// List returns a Pager which allows you to iterate over a collection of
// ports. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
@@ -47,15 +63,17 @@
// Default policy settings return only those ports that are owned by the tenant
// who submits the request, unless the request is submitted by an user with
// administrative rights.
-func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
- // Build query parameters
- q, err := gophercloud.BuildQueryString(&opts)
- if err != nil {
- return pagination.Pager{Err: err}
+func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
+ url := listURL(c)
+ if opts != nil {
+ query, err := opts.ToPortListString()
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ url += query
}
- u := listURL(c) + q.String()
- return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
+ return pagination.NewPager(c, url, func(r pagination.LastHTTPResponse) pagination.Page {
return PortPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
})
}
@@ -71,6 +89,14 @@
return res
}
+// CreateOptsBuilder is the interface options structs have to satisfy in order
+// to be used in the main Create operation in this package. Since many
+// extensions decorate or modify the common logic, it is useful for them to
+// satisfy a basic interface in order for them to be used.
+type CreateOptsBuilder interface {
+ ToPortCreateMap() (map[string]interface{}, error)
+}
+
// CreateOpts represents the attributes used when creating a new port.
type CreateOpts struct {
NetworkID string
@@ -84,51 +110,54 @@
SecurityGroups []string
}
+// ToPortCreateMap casts a CreateOpts struct to a map.
+func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
+ p := make(map[string]interface{})
+
+ if opts.NetworkID == "" {
+ return nil, errNetworkIDRequired
+ }
+ p["network_id"] = opts.NetworkID
+
+ if opts.DeviceID != "" {
+ p["device_id"] = opts.DeviceID
+ }
+ if opts.DeviceOwner != "" {
+ p["device_owner"] = opts.DeviceOwner
+ }
+ if opts.FixedIPs != nil {
+ p["fixed_ips"] = opts.FixedIPs
+ }
+ if opts.SecurityGroups != nil {
+ p["security_groups"] = opts.SecurityGroups
+ }
+ if opts.TenantID != "" {
+ p["tenant_id"] = opts.TenantID
+ }
+ if opts.AdminStateUp != nil {
+ p["admin_state_up"] = &opts.AdminStateUp
+ }
+ if opts.Name != "" {
+ p["name"] = opts.Name
+ }
+ if opts.MACAddress != "" {
+ p["mac_address"] = opts.MACAddress
+ }
+
+ return map[string]interface{}{"port": p}, nil
+}
+
// Create accepts a CreateOpts struct and creates a new network using the values
// provided. You must remember to provide a NetworkID value.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
- type port struct {
- NetworkID string `json:"network_id"`
- Name *string `json:"name,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- MACAddress *string `json:"mac_address,omitempty"`
- FixedIPs interface{} `json:"fixed_ips,omitempty"`
- DeviceID *string `json:"device_id,omitempty"`
- DeviceOwner *string `json:"device_owner,omitempty"`
- TenantID *string `json:"tenant_id,omitempty"`
- SecurityGroups []string `json:"security_groups,omitempty"`
- }
- type request struct {
- Port port `json:"port"`
- }
-
- // Validate
- if opts.NetworkID == "" {
- res.Err = errNetworkIDRequired
+ reqBody, err := opts.ToPortCreateMap()
+ if err != nil {
+ res.Err = err
return res
}
- // Populate request body
- reqBody := request{Port: port{
- NetworkID: opts.NetworkID,
- Name: gophercloud.MaybeString(opts.Name),
- AdminStateUp: opts.AdminStateUp,
- TenantID: gophercloud.MaybeString(opts.TenantID),
- MACAddress: gophercloud.MaybeString(opts.MACAddress),
- DeviceID: gophercloud.MaybeString(opts.DeviceID),
- DeviceOwner: gophercloud.MaybeString(opts.DeviceOwner),
- }}
-
- if opts.FixedIPs != nil {
- reqBody.Port.FixedIPs = opts.FixedIPs
- }
-
- if opts.SecurityGroups != nil {
- reqBody.Port.SecurityGroups = opts.SecurityGroups
- }
-
// Response
_, res.Err = perigee.Request("POST", createURL(c), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
@@ -141,6 +170,14 @@
return res
}
+// UpdateOptsBuilder is the interface options structs have to satisfy in order
+// to be used in the main Update operation in this package. Since many
+// extensions decorate or modify the common logic, it is useful for them to
+// satisfy a basic interface in order for them to be used.
+type UpdateOptsBuilder interface {
+ ToPortUpdateMap() (map[string]interface{}, error)
+}
+
// UpdateOpts represents the attributes used when updating an existing port.
type UpdateOpts struct {
Name string
@@ -151,39 +188,43 @@
SecurityGroups []string
}
+// ToPortUpdateMap casts an UpdateOpts struct to a map.
+func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
+ p := make(map[string]interface{})
+
+ if opts.DeviceID != "" {
+ p["device_id"] = opts.DeviceID
+ }
+ if opts.DeviceOwner != "" {
+ p["device_owner"] = opts.DeviceOwner
+ }
+ if opts.FixedIPs != nil {
+ p["fixed_ips"] = opts.FixedIPs
+ }
+ if opts.SecurityGroups != nil {
+ p["security_groups"] = opts.SecurityGroups
+ }
+ if opts.AdminStateUp != nil {
+ p["admin_state_up"] = &opts.AdminStateUp
+ }
+ if opts.Name != "" {
+ p["name"] = opts.Name
+ }
+
+ return map[string]interface{}{"port": p}, nil
+}
+
// Update accepts a UpdateOpts struct and updates an existing port using the
// values provided.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- type port struct {
- Name *string `json:"name,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- FixedIPs interface{} `json:"fixed_ips,omitempty"`
- DeviceID *string `json:"device_id,omitempty"`
- DeviceOwner *string `json:"device_owner,omitempty"`
- SecurityGroups []string `json:"security_groups,omitempty"`
- }
- type request struct {
- Port port `json:"port"`
- }
-
- // Populate request body
- reqBody := request{Port: port{
- Name: gophercloud.MaybeString(opts.Name),
- AdminStateUp: opts.AdminStateUp,
- DeviceID: gophercloud.MaybeString(opts.DeviceID),
- DeviceOwner: gophercloud.MaybeString(opts.DeviceOwner),
- }}
-
- if opts.FixedIPs != nil {
- reqBody.Port.FixedIPs = opts.FixedIPs
- }
-
- if opts.SecurityGroups != nil {
- reqBody.Port.SecurityGroups = opts.SecurityGroups
- }
-
- // Response
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
+
+ reqBody, err := opts.ToPortUpdateMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
+
_, res.Err = perigee.Request("PUT", updateURL(c, id), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
ReqBody: &reqBody,
diff --git a/openstack/networking/v2/subnets/requests.go b/openstack/networking/v2/subnets/requests.go
index a7e6b53..e164583 100644
--- a/openstack/networking/v2/subnets/requests.go
+++ b/openstack/networking/v2/subnets/requests.go
@@ -1,9 +1,10 @@
package subnets
import (
- "github.com/racker/perigee"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
+
+ "github.com/racker/perigee"
)
// AdminState gives users a solid type to work with for create and update
@@ -19,6 +20,12 @@
Down AdminState = &iFalse
)
+// ListOptsBuilder allows extensions to add additional parameters to the
+// List request.
+type ListOptsBuilder interface {
+ ToSubnetListString() (string, error)
+}
+
// ListOpts allows the filtering and sorting of paginated collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the subnet attributes you want to see returned. SortKey allows you to sort
@@ -39,6 +46,15 @@
SortDir string `q:"sort_dir"`
}
+// ToSubnetListString formats a ListOpts into a query string.
+func (opts ListOpts) ToSubnetListString() (string, error) {
+ q, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return "", err
+ }
+ return q.String(), nil
+}
+
// List returns a Pager which allows you to iterate over a collection of
// subnets. It accepts a ListOpts struct, which allows you to filter and sort
// the returned collection for greater efficiency.
@@ -46,13 +62,15 @@
// Default policy settings return only those subnets that are owned by the tenant
// who submits the request, unless the request is submitted by an user with
// administrative rights.
-func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
- // Build query parameters
- query, err := gophercloud.BuildQueryString(&opts)
- if err != nil {
- return pagination.Pager{Err: err}
+func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
+ url := listURL(c)
+ if opts != nil {
+ query, err := opts.ToSubnetListString()
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ url += query
}
- url := listURL(c) + query.String()
return pagination.NewPager(c, url, func(r pagination.LastHTTPResponse) pagination.Page {
return SubnetPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
@@ -76,6 +94,14 @@
IPv6 = 6
)
+// CreateOptsBuilder is the interface options structs have to satisfy in order
+// to be used in the main Create operation in this package. Since many
+// extensions decorate or modify the common logic, it is useful for them to
+// satisfy a basic interface in order for them to be used.
+type CreateOptsBuilder interface {
+ ToSubnetCreateMap() (map[string]interface{}, error)
+}
+
// CreateOpts represents the attributes used when creating a new subnet.
type CreateOpts struct {
// Required
@@ -92,61 +118,60 @@
HostRoutes []HostRoute
}
-// Create accepts a CreateOpts struct and creates a new subnet using the values
-// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- var res CreateResult
+// ToSubnetCreateMap casts a CreateOpts struct to a map.
+func (opts CreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) {
+ s := make(map[string]interface{})
- // Validate required options
if opts.NetworkID == "" {
- res.Err = errNetworkIDRequired
- return res
+ return nil, errNetworkIDRequired
}
if opts.CIDR == "" {
- res.Err = errCIDRRequired
- return res
+ return nil, errCIDRRequired
}
if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
- res.Err = errInvalidIPType
- return res
+ return nil, errInvalidIPType
}
- type subnet struct {
- NetworkID string `json:"network_id"`
- CIDR string `json:"cidr"`
- Name *string `json:"name,omitempty"`
- TenantID *string `json:"tenant_id,omitempty"`
- AllocationPools []AllocationPool `json:"allocation_pools,omitempty"`
- GatewayIP *string `json:"gateway_ip,omitempty"`
- IPVersion int `json:"ip_version,omitempty"`
- EnableDHCP *bool `json:"enable_dhcp,omitempty"`
- DNSNameservers []string `json:"dns_nameservers,omitempty"`
- HostRoutes []HostRoute `json:"host_routes,omitempty"`
- }
- type request struct {
- Subnet subnet `json:"subnet"`
- }
+ s["network_id"] = opts.NetworkID
+ s["cidr"] = opts.CIDR
- reqBody := request{Subnet: subnet{
- NetworkID: opts.NetworkID,
- CIDR: opts.CIDR,
- Name: gophercloud.MaybeString(opts.Name),
- TenantID: gophercloud.MaybeString(opts.TenantID),
- GatewayIP: gophercloud.MaybeString(opts.GatewayIP),
- EnableDHCP: opts.EnableDHCP,
- }}
-
+ if opts.EnableDHCP != nil {
+ s["enable_dhcp"] = &opts.EnableDHCP
+ }
+ if opts.Name != "" {
+ s["name"] = opts.Name
+ }
+ if opts.GatewayIP != "" {
+ s["gateway_ip"] = opts.GatewayIP
+ }
+ if opts.TenantID != "" {
+ s["tenant_id"] = opts.TenantID
+ }
if opts.IPVersion != 0 {
- reqBody.Subnet.IPVersion = opts.IPVersion
+ s["ip_version"] = opts.IPVersion
}
if len(opts.AllocationPools) != 0 {
- reqBody.Subnet.AllocationPools = opts.AllocationPools
+ s["allocation_pools"] = opts.AllocationPools
}
if len(opts.DNSNameservers) != 0 {
- reqBody.Subnet.DNSNameservers = opts.DNSNameservers
+ s["dns_nameservers"] = opts.DNSNameservers
}
if len(opts.HostRoutes) != 0 {
- reqBody.Subnet.HostRoutes = opts.HostRoutes
+ s["host_routes"] = opts.HostRoutes
+ }
+
+ return map[string]interface{}{"subnet": s}, nil
+}
+
+// Create accepts a CreateOpts struct and creates a new subnet using the values
+// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
+ var res CreateResult
+
+ reqBody, err := opts.ToSubnetCreateMap()
+ if err != nil {
+ res.Err = err
+ return res
}
_, res.Err = perigee.Request("POST", createURL(c), perigee.Options{
@@ -159,6 +184,12 @@
return res
}
+// UpdateOptsBuilder allows extensions to add additional parameters to the
+// Update request.
+type UpdateOptsBuilder interface {
+ ToSubnetUpdateMap() (map[string]interface{}, error)
+}
+
// UpdateOpts represents the attributes used when updating an existing subnet.
type UpdateOpts struct {
Name string
@@ -168,35 +199,40 @@
EnableDHCP *bool
}
+// ToSubnetUpdateMap casts an UpdateOpts struct to a map.
+func (opts UpdateOpts) ToSubnetUpdateMap() (map[string]interface{}, error) {
+ s := make(map[string]interface{})
+
+ if opts.EnableDHCP != nil {
+ s["enable_dhcp"] = &opts.EnableDHCP
+ }
+ if opts.Name != "" {
+ s["name"] = opts.Name
+ }
+ if opts.GatewayIP != "" {
+ s["gateway_ip"] = opts.GatewayIP
+ }
+ if len(opts.DNSNameservers) != 0 {
+ s["dns_nameservers"] = opts.DNSNameservers
+ }
+ if len(opts.HostRoutes) != 0 {
+ s["host_routes"] = opts.HostRoutes
+ }
+
+ return map[string]interface{}{"subnet": s}, nil
+}
+
// Update accepts a UpdateOpts struct and updates an existing subnet using the
// values provided.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- type subnet struct {
- Name *string `json:"name,omitempty"`
- GatewayIP *string `json:"gateway_ip,omitempty"`
- DNSNameservers []string `json:"dns_nameservers,omitempty"`
- HostRoutes []HostRoute `json:"host_routes,omitempty"`
- EnableDHCP *bool `json:"enable_dhcp,omitempty"`
- }
- type request struct {
- Subnet subnet `json:"subnet"`
- }
-
- reqBody := request{Subnet: subnet{
- Name: gophercloud.MaybeString(opts.Name),
- GatewayIP: gophercloud.MaybeString(opts.GatewayIP),
- EnableDHCP: opts.EnableDHCP,
- }}
-
- if len(opts.DNSNameservers) != 0 {
- reqBody.Subnet.DNSNameservers = opts.DNSNameservers
- }
-
- if len(opts.HostRoutes) != 0 {
- reqBody.Subnet.HostRoutes = opts.HostRoutes
- }
-
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
var res UpdateResult
+
+ reqBody, err := opts.ToSubnetUpdateMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
+
_, res.Err = perigee.Request("PUT", updateURL(c, id), perigee.Options{
MoreHeaders: c.Provider.AuthenticatedHeaders(),
ReqBody: &reqBody,
diff --git a/openstack/objectstorage/v1/containers/requests.go b/openstack/objectstorage/v1/containers/requests.go
index afe7c7f..ce3f540 100644
--- a/openstack/objectstorage/v1/containers/requests.go
+++ b/openstack/objectstorage/v1/containers/requests.go
@@ -15,12 +15,12 @@
// ListOpts is a structure that holds options for listing containers.
type ListOpts struct {
Full bool
- Limit int `q:"limit"`
- Marker string `q:"marker"`
- EndMarker string `q:"end_marker"`
- Format string `q:"format"`
- Prefix string `q:"prefix"`
- Delimiter [1]byte `q:"delimiter"`
+ Limit int `q:"limit"`
+ Marker string `q:"marker"`
+ EndMarker string `q:"end_marker"`
+ Format string `q:"format"`
+ Prefix string `q:"prefix"`
+ Delimiter string `q:"delimiter"`
}
// ToContainerListParams formats a ListOpts into a query string and boolean
@@ -66,7 +66,7 @@
// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
- ToContainerCreateParams() (map[string]string, error)
+ ToContainerCreateMap() (map[string]string, error)
}
// CreateOpts is a structure that holds parameters for creating a container.
@@ -82,8 +82,8 @@
VersionsLocation string `h:"X-Versions-Location"`
}
-// ToContainerCreateParams formats a CreateOpts into a map of headers.
-func (opts CreateOpts) ToContainerCreateParams() (map[string]string, error) {
+// ToContainerCreateMap formats a CreateOpts into a map of headers.
+func (opts CreateOpts) ToContainerCreateMap() (map[string]string, error) {
h, err := gophercloud.BuildHeaders(opts)
if err != nil {
return nil, err
@@ -100,7 +100,7 @@
h := c.Provider.AuthenticatedHeaders()
if opts != nil {
- headers, err := opts.ToContainerCreateParams()
+ headers, err := opts.ToContainerCreateMap()
if err != nil {
res.Err = err
return res
@@ -135,7 +135,7 @@
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
- ToContainerUpdateParams() (map[string]string, error)
+ ToContainerUpdateMap() (map[string]string, error)
}
// UpdateOpts is a structure that holds parameters for updating, creating, or
@@ -152,8 +152,8 @@
VersionsLocation string `h:"X-Versions-Location"`
}
-// ToContainerUpdateParams formats a CreateOpts into a map of headers.
-func (opts UpdateOpts) ToContainerUpdateParams() (map[string]string, error) {
+// ToContainerUpdateMap formats a CreateOpts into a map of headers.
+func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) {
h, err := gophercloud.BuildHeaders(opts)
if err != nil {
return nil, err
@@ -171,7 +171,7 @@
h := c.Provider.AuthenticatedHeaders()
if opts != nil {
- headers, err := opts.ToContainerUpdateParams()
+ headers, err := opts.ToContainerUpdateMap()
if err != nil {
res.Err = err
return res
diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go
index 77b8380..f6e355d 100644
--- a/openstack/objectstorage/v1/objects/requests.go
+++ b/openstack/objectstorage/v1/objects/requests.go
@@ -19,13 +19,13 @@
// ListOpts is a structure that holds parameters for listing objects.
type ListOpts struct {
Full bool
- Limit int `q:"limit"`
- Marker string `q:"marker"`
- EndMarker string `q:"end_marker"`
- Format string `q:"format"`
- Prefix string `q:"prefix"`
- Delimiter [1]byte `q:"delimiter"`
- Path string `q:"path"`
+ Limit int `q:"limit"`
+ Marker string `q:"marker"`
+ EndMarker string `q:"end_marker"`
+ Format string `q:"format"`
+ Prefix string `q:"prefix"`
+ Delimiter string `q:"delimiter"`
+ Path string `q:"path"`
}
// ToObjectListParams formats a ListOpts into a query string and boolean
@@ -222,7 +222,7 @@
// CopyOptsBuilder allows extensions to add additional parameters to the
// Copy request.
type CopyOptsBuilder interface {
- ToObjectCopyParams() (map[string]string, error)
+ ToObjectCopyMap() (map[string]string, error)
}
// CopyOpts is a structure that holds parameters for copying one object to
@@ -235,8 +235,8 @@
Destination string `h:"Destination,required"`
}
-// ToObjectCopyParams formats a CopyOpts into a map of headers.
-func (opts CopyOpts) ToObjectCopyParams() (map[string]string, error) {
+// ToObjectCopyMap formats a CopyOpts into a map of headers.
+func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
if opts.Destination == "" {
return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.")
}
@@ -255,7 +255,7 @@
var res CopyResult
h := c.Provider.AuthenticatedHeaders()
- headers, err := opts.ToObjectCopyParams()
+ headers, err := opts.ToObjectCopyMap()
if err != nil {
res.Err = err
return res
@@ -277,7 +277,7 @@
// DeleteOptsBuilder allows extensions to add additional parameters to the
// Delete request.
type DeleteOptsBuilder interface {
- ToObjectDeleteParams() (string, error)
+ ToObjectDeleteString() (string, error)
}
// DeleteOpts is a structure that holds parameters for deleting an object.
@@ -285,8 +285,8 @@
MultipartManifest string `q:"multipart-manifest"`
}
-// ToObjectDeleteParams formats a DeleteOpts into a query string.
-func (opts DeleteOpts) ToObjectDeleteParams() (string, error) {
+// ToObjectDeleteString formats a DeleteOpts into a query string.
+func (opts DeleteOpts) ToObjectDeleteString() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
@@ -300,7 +300,7 @@
url := deleteURL(c, containerName, objectName)
if opts != nil {
- query, err := opts.ToObjectDeleteParams()
+ query, err := opts.ToObjectDeleteString()
if err != nil {
res.Err = err
return res
@@ -320,7 +320,7 @@
// GetOptsBuilder allows extensions to add additional parameters to the
// Get request.
type GetOptsBuilder interface {
- ToObjectGetParams() (string, error)
+ ToObjectGetString() (string, error)
}
// GetOpts is a structure that holds parameters for getting an object's metadata.
@@ -329,8 +329,8 @@
Signature string `q:"signature"`
}
-// ToObjectGetParams formats a GetOpts into a query string.
-func (opts GetOpts) ToObjectGetParams() (string, error) {
+// ToObjectGetString formats a GetOpts into a query string.
+func (opts GetOpts) ToObjectGetString() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
@@ -345,7 +345,7 @@
url := getURL(c, containerName, objectName)
if opts != nil {
- query, err := opts.ToObjectGetParams()
+ query, err := opts.ToObjectGetString()
if err != nil {
res.Err = err
return res
@@ -365,7 +365,7 @@
// UpdateOptsBuilder allows extensions to add additional parameters to the
// Update request.
type UpdateOptsBuilder interface {
- ToObjectUpdateParams() (map[string]string, error)
+ ToObjectUpdateMap() (map[string]string, error)
}
// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an
@@ -380,8 +380,8 @@
DetectContentType bool `h:"X-Detect-Content-Type"`
}
-// ToObjectUpdateParams formats a UpdateOpts into a map of headers.
-func (opts UpdateOpts) ToObjectUpdateParams() (map[string]string, error) {
+// ToObjectUpdateMap formats a UpdateOpts into a map of headers.
+func (opts UpdateOpts) ToObjectUpdateMap() (map[string]string, error) {
h, err := gophercloud.BuildHeaders(opts)
if err != nil {
return nil, err
@@ -398,7 +398,7 @@
h := c.Provider.AuthenticatedHeaders()
if opts != nil {
- headers, err := opts.ToObjectUpdateParams()
+ headers, err := opts.ToObjectUpdateMap()
if err != nil {
res.Err = err
return res