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>
This commit is contained in:
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", "ImportPath": "github.com/gophercloud/gophercloud",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack", "ImportPath": "github.com/gophercloud/gophercloud/openstack",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions", "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes", "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes", "ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions", "ImportPath": "github.com/gophercloud/gophercloud/openstack/common/extensions",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach", "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors", "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images", "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/images",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers", "ImportPath": "github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts", "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions", "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports", "ImportPath": "github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gophercloud/gophercloud/pagination", "ImportPath": "github.com/gophercloud/gophercloud/pagination",
"Rev": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11" "Rev": "ed590d9afe113c6107cd60717b196155e6579e78"
}, },
{ {
"ImportPath": "github.com/gorilla/context", "ImportPath": "github.com/gorilla/context",

View File

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

View File

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

View File

@ -57,7 +57,7 @@
### Naming ### 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`. variable into which it will be unmarshalled `s`.
- Functions in `requests.go`, with the exception of functions that return a - 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 // control panel to discover your account's username. In Identity V3, either
// UserID or a combination of Username and DomainID or DomainName are needed. // UserID or a combination of Username and DomainID or DomainName are needed.
Username string `json:"username,omitempty"` Username string `json:"username,omitempty"`
UserID string `json:"id,omitempty"` UserID string `json:"-"`
Password string `json:"password,omitempty"` Password string `json:"password,omitempty"`
// At most one of DomainID and DomainName must be provided if using Username // At most one of DomainID and DomainName must be provided if using Username
// with Identity V3. Otherwise, either are optional. // with Identity V3. Otherwise, either are optional.
DomainID string `json:"id,omitempty"` DomainID string `json:"-"`
DomainName string `json:"name,omitempty"` DomainName string `json:"name,omitempty"`
// The TenantID and TenantName fields are optional for the Identity V2 API. // The TenantID and TenantName fields are optional for the Identity V2 API.

View File

@ -1,6 +1,9 @@
package volumes package volumes
import ( import (
"encoding/json"
"time"
"github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination" "github.com/gophercloud/gophercloud/pagination"
) )
@ -18,7 +21,7 @@ type Volume struct {
// Indicates whether this is a bootable volume. // Indicates whether this is a bootable volume.
Bootable string `json:"bootable"` Bootable string `json:"bootable"`
// The date when this volume was created. // The date when this volume was created.
CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"` CreatedAt time.Time `json:"-"`
// Human-readable description for the volume. // Human-readable description for the volume.
Description string `json:"display_description"` Description string `json:"display_description"`
// The type of volume to create, either SATA or SSD. // The type of volume to create, either SATA or SSD.
@ -35,6 +38,23 @@ type Volume struct {
Size int `json:"size"` 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. // CreateResult contains the response body and error from a Create request.
type CreateResult struct { type CreateResult struct {
commonResult 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. // 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) { func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
endpoint := client.IdentityBase + "v2.0/" endpoint := client.IdentityBase + "v2.0/"
clientType := "identity"
var err error var err error
if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) { if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
eo.ApplyDefaults("identity") eo.ApplyDefaults(clientType)
endpoint, err = client.EndpointLocator(eo) endpoint, err = client.EndpointLocator(eo)
if err != nil { if err != nil {
return nil, err return nil, err
@ -194,15 +195,17 @@ func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
return &gophercloud.ServiceClient{ return &gophercloud.ServiceClient{
ProviderClient: client, ProviderClient: client,
Endpoint: endpoint, Endpoint: endpoint,
Type: clientType,
}, nil }, nil
} }
// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service. // 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) { func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
endpoint := client.IdentityBase + "v3/" endpoint := client.IdentityBase + "v3/"
clientType := "identity"
var err error var err error
if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) { if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) {
eo.ApplyDefaults("identity") eo.ApplyDefaults(clientType)
endpoint, err = client.EndpointLocator(eo) endpoint, err = client.EndpointLocator(eo)
if err != nil { if err != nil {
return nil, err return nil, err
@ -212,125 +215,81 @@ func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
return &gophercloud.ServiceClient{ return &gophercloud.ServiceClient{
ProviderClient: client, ProviderClient: client,
Endpoint: endpoint, Endpoint: endpoint,
Type: clientType,
}, nil }, 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. // 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) { func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("object-store") return initClientOpts(client, eo, "object-store")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewComputeV2 creates a ServiceClient that may be used with the v2 compute package. // NewComputeV2 creates a ServiceClient that may be used with the v2 compute package.
func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("compute") return initClientOpts(client, eo, "compute")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewNetworkV2 creates a ServiceClient that may be used with the v2 network package. // NewNetworkV2 creates a ServiceClient that may be used with the v2 network package.
func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("network") sc, err := initClientOpts(client, eo, "network")
url, err := client.EndpointLocator(eo) sc.ResourceBase = sc.Endpoint + "v2.0/"
if err != nil { return sc, err
return nil, err
}
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: url,
ResourceBase: url + "v2.0/",
}, nil
} }
// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1 block storage service. // 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) { func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("volume") return initClientOpts(client, eo, "volume")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 block storage service. // 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) { func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("volumev2") return initClientOpts(client, eo, "volumev2")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewSharedFileSystemV2 creates a ServiceClient that may be used to access the v2 shared file system service. // 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) { func NewSharedFileSystemV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("sharev2") return initClientOpts(client, eo, "sharev2")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1 // NewCDNV1 creates a ServiceClient that may be used to access the OpenStack v1
// CDN service. // CDN service.
func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("cdn") return initClientOpts(client, eo, "cdn")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1 orchestration service. // 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) { func NewOrchestrationV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("orchestration") return initClientOpts(client, eo, "orchestration")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service. // 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) { func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("database") return initClientOpts(client, eo, "database")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
} }
// NewDNSV2 creates a ServiceClient that may be used to access the v2 DNS service. // 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) { func NewDNSV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("dns") sc, err := initClientOpts(client, eo, "dns")
url, err := client.EndpointLocator(eo) sc.ResourceBase = sc.Endpoint + "v2/"
if err != nil { return sc, err
return nil, err
}
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: url,
ResourceBase: url + "v2/"}, nil
} }
// NewImageServiceV2 creates a ServiceClient that may be used to access the v2 image service. // 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) { func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("image") sc, err := initClientOpts(client, eo, "image")
url, err := client.EndpointLocator(eo) sc.ResourceBase = sc.Endpoint + "v2/"
if err != nil { return sc, err
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client,
Endpoint: url,
ResourceBase: url + "v2/"}, nil
} }

View File

@ -11,6 +11,24 @@ type ListOptsBuilder interface {
ToFlavorListQuery() (string, error) 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. // 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. // 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. // 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 instructs List to refrain from sending excessively large lists of flavors.
Limit int `q:"limit"` 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. // ToFlavorListQuery formats a ListOpts into a query string.

View File

@ -46,6 +46,8 @@ type Flavor struct {
Swap int `json:"swap"` Swap int `json:"swap"`
// VCPUs indicates how many (virtual) CPUs are available for this flavor. // VCPUs indicates how many (virtual) CPUs are available for this flavor.
VCPUs int `json:"vcpus"` VCPUs int `json:"vcpus"`
// IsPublic indicates whether the flavor is public.
IsPublic bool `json:"is_public"`
} }
func (r *Flavor) UnmarshalJSON(b []byte) error { 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. // Scope allows a created token to be limited to a specific domain or project.
type Scope struct { type Scope struct {
ProjectID string `json:"scope.project.id,omitempty" not:"ProjectName,DomainID,DomainName"` ProjectID string
ProjectName string `json:"scope.project.name,omitempty"` ProjectName string
DomainID string `json:"scope.project.id,omitempty" not:"ProjectName,ProjectID,DomainName"` DomainID string
DomainName string `json:"scope.project.id,omitempty"` DomainName string
} }
// AuthOptionsBuilder describes any argument that may be passed to the Create call. // 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 // At most one of DomainID and DomainName must be provided if using Username
// with Identity V3. Otherwise, either are optional. // with Identity V3. Otherwise, either are optional.
DomainID string `json:"id,omitempty"` DomainID string `json:"-"`
DomainName string `json:"name,omitempty"` DomainName string `json:"name,omitempty"`
// AllowReauth should be set to true if you grant permission for Gophercloud to // 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) { func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
resp, err := c.Request("HEAD", tokenURL(c), &gophercloud.RequestOpts{ resp, err := c.Request("HEAD", tokenURL(c), &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token), MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{204, 404}, OkCodes: []int{200, 204, 400, 401, 403, 404},
}) })
if err != nil { if err != nil {
return false, err return false, err
} }
return resp.StatusCode == 204, nil return resp.StatusCode == 200 || resp.StatusCode == 204, nil
} }
// Revoke immediately makes specified token invalid. // 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. // CreateOpts contains all the values needed to create a new security group.
type CreateOpts struct { 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"` 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"` TenantID string `json:"tenant_id,omitempty"`
// Optional. Describes the security group. // Optional. Describes the security group.
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
@ -64,6 +64,36 @@ func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResul
return 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. // Get retrieves a particular security group based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) { func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil) _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)

View File

@ -83,6 +83,11 @@ type CreateResult struct {
commonResult commonResult
} }
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// GetResult represents the result of a get operation. // GetResult represents the result of a get operation.
type GetResult struct { type GetResult struct {
commonResult 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) { func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) {
return client.Get(url, nil, &gophercloud.RequestOpts{ return client.Get(url, nil, &gophercloud.RequestOpts{
MoreHeaders: headers, MoreHeaders: headers,
OkCodes: []int{200, 204}, OkCodes: []int{200, 204, 300},
}) })
} }

View File

@ -21,6 +21,12 @@ type ServiceClient struct {
// as-is, instead. // as-is, instead.
ResourceBase string 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 Microversion string
} }
@ -37,11 +43,13 @@ func (client *ServiceClient) ServiceURL(parts ...string) string {
return client.ResourceBaseURL() + strings.Join(parts, "/") return client.ResourceBaseURL() + strings.Join(parts, "/")
} }
// Get calls `Request` with the "GET" HTTP verb. func (client *ServiceClient) initReqOpts(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) {
func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { if v, ok := (JSONBody).(io.Reader); ok {
if opts == nil { opts.RawBody = v
opts = &RequestOpts{} } else if JSONBody != nil {
opts.JSONBody = JSONBody
} }
if JSONResponse != nil { if JSONResponse != nil {
opts.JSONResponse = JSONResponse opts.JSONResponse = JSONResponse
} }
@ -49,93 +57,66 @@ func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *Req
if opts.MoreHeaders == nil { if opts.MoreHeaders == nil {
opts.MoreHeaders = make(map[string]string) 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) return client.Request("GET", url, opts)
} }
// Post calls `Request` with the "POST" HTTP verb. // Post calls `Request` with the "POST" HTTP verb.
func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil { if opts == nil {
opts = &RequestOpts{} opts = new(RequestOpts)
} }
client.initReqOpts(url, JSONBody, JSONResponse, opts)
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
return client.Request("POST", url, opts) return client.Request("POST", url, opts)
} }
// Put calls `Request` with the "PUT" HTTP verb. // Put calls `Request` with the "PUT" HTTP verb.
func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil { if opts == nil {
opts = &RequestOpts{} opts = new(RequestOpts)
} }
client.initReqOpts(url, JSONBody, JSONResponse, opts)
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
return client.Request("PUT", url, opts) return client.Request("PUT", url, opts)
} }
// Patch calls `Request` with the "PATCH" HTTP verb. // Patch calls `Request` with the "PATCH" HTTP verb.
func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
if opts == nil { if opts == nil {
opts = &RequestOpts{} opts = new(RequestOpts)
} }
client.initReqOpts(url, JSONBody, JSONResponse, opts)
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
return client.Request("PATCH", url, opts) return client.Request("PATCH", url, opts)
} }
// Delete calls `Request` with the "DELETE" HTTP verb. // Delete calls `Request` with the "DELETE" HTTP verb.
func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) { func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
if opts == nil { if opts == nil {
opts = &RequestOpts{} opts = new(RequestOpts)
} }
client.initReqOpts(url, nil, nil, opts)
if opts.MoreHeaders == nil {
opts.MoreHeaders = make(map[string]string)
}
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
return client.Request("DELETE", url, 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
}
}