rebase gophercloud to support HTTP status 300 in pagination, so listing Cinder v1/v2 API versions won't break

Signed-off-by: Huamin Chen <hchen@redhat.com>
pull/6/head
Huamin Chen 2017-06-15 16:55:10 +00:00
parent 562e721ece
commit ca65a6d151
14 changed files with 213 additions and 192 deletions

60
Godeps/Godeps.json generated
View File

@ -1482,123 +1482,123 @@
},
{
"ImportPath": "github.com/gophercloud/gophercloud",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gorilla/context",

View File

@ -416,31 +416,31 @@
},
{
"ImportPath": "github.com/gophercloud/gophercloud",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11"
"Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
},
{
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",

View File

@ -5,13 +5,15 @@ install:
- go get -v -tags 'fixtures acceptance' ./...
- go get github.com/wadey/gocovmerge
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/goimports
go:
- 1.7
- 1.8
- tip
env:
global:
- secure: "xSQsAG5wlL9emjbCdxzz/hYQsSpJ/bABO1kkbwMSISVcJ3Nk0u4ywF+LS4bgeOnwPfmFvNTOqVDu3RwEvMeWXSI76t1piCPcObutb2faKLVD/hLoAS76gYX+Z8yGWGHrSB7Do5vTPj1ERe2UljdrnsSeOXzoDwFxYRaZLX4bBOB4AyoGvRniil5QXPATiA1tsWX1VMicj8a4F8X+xeESzjt1Q5Iy31e7vkptu71bhvXCaoo5QhYwT+pLR9dN0S1b7Ro0KVvkRefmr1lUOSYd2e74h6Lc34tC1h3uYZCS4h47t7v5cOXvMNxinEj2C51RvbjvZI1RLVdkuAEJD1Iz4+Ote46nXbZ//6XRZMZz/YxQ13l7ux1PFjgEB6HAapmF5Xd8PRsgeTU9LRJxpiTJ3P5QJ3leS1va8qnziM5kYipj/Rn+V8g2ad/rgkRox9LSiR9VYZD2Pe45YCb1mTKSl2aIJnV7nkOqsShY5LNB4JZSg7xIffA+9YVDktw8dJlATjZqt7WvJJ49g6A61mIUV4C15q2JPGKTkZzDiG81NtmS7hFa7k0yaE2ELgYocbcuyUcAahhxntYTC0i23nJmEHVNiZmBO3u7EgpWe4KGVfumU+lt12tIn5b3dZRBBUk3QakKKozSK1QPHGpk/AZGrhu7H6l8to6IICKWtDcyMPQ="
script:
- ./script/coverage
- ./script/format
after_success:
- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out

View File

@ -57,7 +57,7 @@
### Naming
- For methods on a type in `response.go`, the receiver should be named `r` and the
- For methods on a type in `results.go`, the receiver should be named `r` and the
variable into which it will be unmarshalled `s`.
- Functions in `requests.go`, with the exception of functions that return a

View File

@ -21,13 +21,13 @@ type AuthOptions struct {
// control panel to discover your account's username. In Identity V3, either
// UserID or a combination of Username and DomainID or DomainName are needed.
Username string `json:"username,omitempty"`
UserID string `json:"id,omitempty"`
UserID string `json:"-"`
Password string `json:"password,omitempty"`
// At most one of DomainID and DomainName must be provided if using Username
// with Identity V3. Otherwise, either are optional.
DomainID string `json:"id,omitempty"`
DomainID string `json:"-"`
DomainName string `json:"name,omitempty"`
// The TenantID and TenantName fields are optional for the Identity V2 API.

View File

@ -1,6 +1,9 @@
package volumes
import (
"encoding/json"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)
@ -18,7 +21,7 @@ type Volume struct {
// Indicates whether this is a bootable volume.
Bootable string `json:"bootable"`
// The date when this volume was created.
CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
CreatedAt time.Time `json:"-"`
// Human-readable description for the volume.
Description string `json:"display_description"`
// The type of volume to create, either SATA or SSD.
@ -35,6 +38,23 @@ type Volume struct {
Size int `json:"size"`
}
func (r *Volume) UnmarshalJSON(b []byte) error {
type tmp Volume
var s struct {
tmp
CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = Volume(s.tmp)
r.CreatedAt = time.Time(s.CreatedAt)
return err
}
// CreateResult contains the response body and error from a Create request.
type CreateResult struct {
commonResult

View File

@ -182,9 +182,10 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
// NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
endpoint := client.IdentityBase + "v2.0/"
clientType := "identity"
var err error
if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
eo.ApplyDefaults("identity")
eo.ApplyDefaults(clientType)
endpoint, err = client.EndpointLocator(eo)
if err != nil {
return nil, err
@ -194,15 +195,17 @@ func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: endpoint,
Type: clientType,
}, nil
}
// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
endpoint := client.IdentityBase + "v3/"
clientType := "identity"
var err error
if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
eo.ApplyDefaults("identity")
eo.ApplyDefaults(clientType)
endpoint, err = client.EndpointLocator(eo)
if err != nil {
return nil, err
@ -212,125 +215,81 @@ func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: endpoint,
Type: clientType,
}, nil
}
func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, clientType string) (*gophercloud.ServiceClient, error) {
sc := new(gophercloud.ServiceClient)
eo.ApplyDefaults(clientType)
url, err := client.EndpointLocator(eo)
if err != nil {
return sc, err
}
sc.ProviderClient = client
sc.Endpoint = url
sc.Type = clientType
return sc, nil
}
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("object-store")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "object-store")
}
// NewComputeV2 creates a ServiceClient that may be used with the v2 compute package.
func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("compute")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "compute")
}
// NewNetworkV2 creates a ServiceClient that may be used with the v2 network package.
func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("network")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: url,
ResourceBase: url + "v2.0/",
}, nil
sc, err := initClientOpts(client, eo, "network")
sc.ResourceBase = sc.Endpoint + "v2.0/"
return sc, err
}
// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1 block storage service.
func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("volume")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "volume")
}
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 block storage service.
func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("volumev2")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "volumev2")
}
// NewSharedFileSystemV2 creates a ServiceClient that may be used to access the v2 shared file system service.
func NewSharedFileSystemV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("sharev2")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "sharev2")
}
// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1
// CDN service.
func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("cdn")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "cdn")
}
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service.
func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("orchestration")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "orchestration")
}
// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service.
func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("database")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
return initClientOpts(client, eo, "database")
}
// NewDNSV2 creates a ServiceClient that may be used to access the v2 DNS service.
func NewDNSV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("dns")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: url,
ResourceBase: url + "v2/"}, nil
sc, err := initClientOpts(client, eo, "dns")
sc.ResourceBase = sc.Endpoint + "v2/"
return sc, err
}
// NewImageServiceV2 creates a ServiceClient that may be used to access the v2 image service.
func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("image")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client,
Endpoint: url,
ResourceBase: url + "v2/"}, nil
sc, err := initClientOpts(client, eo, "image")
sc.ResourceBase = sc.Endpoint + "v2/"
return sc, err
}

View File

@ -11,6 +11,24 @@ type ListOptsBuilder interface {
ToFlavorListQuery() (string, error)
}
// AccessType maps to OpenStack's Flavor.is_public field. Although the is_public field is boolean, the
// request options are ternary, which is why AccessType is a string. The following values are
// allowed:
//
// PublicAccess (the default): Returns public flavors and private flavors associated with that project.
// PrivateAccess (admin only): Returns private flavors, across all projects.
// AllAccess (admin only): Returns public and private flavors across all projects.
//
// The AccessType arguement is optional, and if it is not supplied, OpenStack returns the PublicAccess
// flavors.
type AccessType string
const (
PublicAccess AccessType = "true"
PrivateAccess AccessType = "false"
AllAccess AccessType = "None"
)
// 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.
@ -29,6 +47,10 @@ type ListOpts struct {
// Limit instructs List to refrain from sending excessively large lists of flavors.
Limit int `q:"limit"`
// AccessType, if provided, instructs List which set of flavors to return. If IsPublic not provided,
// flavors for the current project are returned.
AccessType AccessType `q:"is_public"`
}
// ToFlavorListQuery formats a ListOpts into a query string.

View File

@ -46,6 +46,8 @@ type Flavor struct {
Swap int `json:"swap"`
// VCPUs indicates how many (virtual) CPUs are available for this flavor.
VCPUs int `json:"vcpus"`
// IsPublic indicates whether the flavor is public.
IsPublic bool `json:"is_public"`
}
func (r *Flavor) UnmarshalJSON(b []byte) error {

View File

@ -4,10 +4,10 @@ import "github.com/gophercloud/gophercloud"
// Scope allows a created token to be limited to a specific domain or project.
type Scope struct {
ProjectID string `json:"scope.project.id,omitempty" not:"ProjectName,DomainID,DomainName"`
ProjectName string `json:"scope.project.name,omitempty"`
DomainID string `json:"scope.project.id,omitempty" not:"ProjectName,ProjectID,DomainName"`
DomainName string `json:"scope.project.id,omitempty"`
ProjectID string
ProjectName string
DomainID string
DomainName string
}
// AuthOptionsBuilder describes any argument that may be passed to the Create call.
@ -36,7 +36,7 @@ type AuthOptions struct {
// At most one of DomainID and DomainName must be provided if using Username
// with Identity V3. Otherwise, either are optional.
DomainID string `json:"id,omitempty"`
DomainID string `json:"-"`
DomainName string `json:"name,omitempty"`
// AllowReauth should be set to true if you grant permission for Gophercloud to
@ -182,13 +182,13 @@ func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
resp, err := c.Request("HEAD", tokenURL(c), &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{204, 404},
OkCodes: []int{200, 204, 400, 401, 403, 404},
})
if err != nil {
return false, err
}
return resp.StatusCode == 204, nil
return resp.StatusCode == 200 || resp.StatusCode == 204, nil
}
// Revoke immediately makes specified token invalid.

View File

@ -40,9 +40,9 @@ type CreateOptsBuilder interface {
// CreateOpts contains all the values needed to create a new security group.
type CreateOpts struct {
// Required. Human-readable name for the VIP. Does not have to be unique.
// Required. Human-readable name for the Security Group. Does not have to be unique.
Name string `json:"name" required:"true"`
// Required for admins. Indicates the owner of the VIP.
// Required for admins. Indicates the owner of the Security Group.
TenantID string `json:"tenant_id,omitempty"`
// Optional. Describes the security group.
Description string `json:"description,omitempty"`
@ -64,6 +64,36 @@ func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResul
return
}
type UpdateOptsBuilder interface {
ToSecGroupUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains all the values needed to update an existing security group.
type UpdateOpts struct {
// Human-readable name for the Security Group. Does not have to be unique.
Name string `json:"name,omitempty"`
// Optional. Describes the security group.
Description string `json:"description,omitempty"`
}
func (opts UpdateOpts) ToSecGroupUpdateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "security_group")
}
// Update is an operation which updates an existing security group.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
b, err := opts.ToSecGroupUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return
}
// Get retrieves a particular security group based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)

View File

@ -83,6 +83,11 @@ type CreateResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult

View File

@ -55,6 +55,6 @@ func PageResultFromParsed(resp *http.Response, body interface{}) PageResult {
func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) {
return client.Get(url, nil, &gophercloud.RequestOpts{
MoreHeaders: headers,
OkCodes: []int{200, 204},
OkCodes: []int{200, 204, 300},
})
}

View File

@ -21,6 +21,12 @@ type ServiceClient struct {
// as-is, instead.
ResourceBase string
// This is the service client type (e.g. compute, sharev2).
// NOTE: FOR INTERNAL USE ONLY. DO NOT SET. GOPHERCLOUD WILL SET THIS.
// It is only exported because it gets set in a different package.
Type string
// The microversion of the service to use. Set this to use a particular microversion.
Microversion string
}
@ -37,11 +43,13 @@ func (client *ServiceClient) ServiceURL(parts ...string) string {
return client.ResourceBaseURL() + strings.Join(parts, "/")
}
// Get calls `Request` with the "GET" HTTP verb.
func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil {
opts = &RequestOpts{}
func (client *ServiceClient) initReqOpts(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) {
if v, ok := (JSONBody).(io.Reader); ok {
opts.RawBody = v
} else if JSONBody != nil {
opts.JSONBody = JSONBody
}
if JSONResponse != nil {
opts.JSONResponse = JSONResponse
}
@ -49,93 +57,66 @@ func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *Req
if opts.MoreHeaders == nil {
opts.MoreHeaders = make(map[string]string)
}
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
if client.Microversion != "" {
client.setMicroversionHeader(opts)
}
}
// Get calls `Request` with the "GET" HTTP verb.
func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil {
opts = new(RequestOpts)
}
client.initReqOpts(url, nil, JSONResponse, opts)
return client.Request("GET", url, opts)
}
// Post calls `Request` with the "POST" HTTP verb.
func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil {
opts = &RequestOpts{}
opts = new(RequestOpts)
}
if v, ok := (JSONBody).(io.Reader); ok {
opts.RawBody = v
} else if JSONBody != nil {
opts.JSONBody = JSONBody
}
if JSONResponse != nil {
opts.JSONResponse = JSONResponse
}
if opts.MoreHeaders == nil {
opts.MoreHeaders = make(map[string]string)
}
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
client.initReqOpts(url, JSONBody, JSONResponse, opts)
return client.Request("POST", url, opts)
}
// Put calls `Request` with the "PUT" HTTP verb.
func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil {
opts = &RequestOpts{}
opts = new(RequestOpts)
}
if v, ok := (JSONBody).(io.Reader); ok {
opts.RawBody = v
} else if JSONBody != nil {
opts.JSONBody = JSONBody
}
if JSONResponse != nil {
opts.JSONResponse = JSONResponse
}
if opts.MoreHeaders == nil {
opts.MoreHeaders = make(map[string]string)
}
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
client.initReqOpts(url, JSONBody, JSONResponse, opts)
return client.Request("PUT", url, opts)
}
// Patch calls `Request` with the "PATCH" HTTP verb.
func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil {
opts = &RequestOpts{}
opts = new(RequestOpts)
}
if v, ok := (JSONBody).(io.Reader); ok {
opts.RawBody = v
} else if JSONBody != nil {
opts.JSONBody = JSONBody
}
if JSONResponse != nil {
opts.JSONResponse = JSONResponse
}
if opts.MoreHeaders == nil {
opts.MoreHeaders = make(map[string]string)
}
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
client.initReqOpts(url, JSONBody, JSONResponse, opts)
return client.Request("PATCH", url, opts)
}
// Delete calls `Request` with the "DELETE" HTTP verb.
func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
if opts == nil {
opts = &RequestOpts{}
opts = new(RequestOpts)
}
if opts.MoreHeaders == nil {
opts.MoreHeaders = make(map[string]string)
}
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
client.initReqOpts(url, nil, nil, opts)
return client.Request("DELETE", url, opts)
}
func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) {
switch client.Type {
case "compute":
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
case "sharev2":
opts.MoreHeaders["X-OpenStack-Manila-API-Version"] = client.Microversion
}
if client.Type != "" {
opts.MoreHeaders["OpenStack-API-Version"] = client.Type + " " + client.Microversion
}
}