Commit ca65a6d1 authored by Huamin Chen's avatar Huamin Chen

rebase gophercloud to support HTTP status 300 in pagination, so listing Cinder…

rebase gophercloud to support HTTP status 300 in pagination, so listing Cinder v1/v2 API versions won't break Signed-off-by: 's avatarHuamin Chen <hchen@redhat.com>
parent 562e721e
...@@ -1482,123 +1482,123 @@ ...@@ -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",
......
...@@ -416,31 +416,31 @@ ...@@ -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",
......
...@@ -5,13 +5,15 @@ install: ...@@ -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
...@@ -57,7 +57,7 @@ ...@@ -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
......
...@@ -21,13 +21,13 @@ type AuthOptions struct { ...@@ -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.
......
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 { ...@@ -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 { ...@@ -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
......
...@@ -182,9 +182,10 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au ...@@ -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 ...@@ -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 ...@@ -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
} }
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package. func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, clientType string) (*gophercloud.ServiceClient, error) {
func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { sc := new(gophercloud.ServiceClient)
eo.ApplyDefaults("object-store") eo.ApplyDefaults(clientType)
url, err := client.EndpointLocator(eo) url, err := client.EndpointLocator(eo)
if err != nil { if err != nil {
return nil, err return sc, err
} }
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil 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) {
return initClientOpts(client, eo, "object-store")
} }
// 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
} }
...@@ -11,6 +11,24 @@ type ListOptsBuilder interface { ...@@ -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 { ...@@ -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.
......
...@@ -46,6 +46,8 @@ type Flavor struct { ...@@ -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 {
......
...@@ -4,10 +4,10 @@ import "github.com/gophercloud/gophercloud" ...@@ -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 { ...@@ -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) { ...@@ -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.
......
...@@ -40,9 +40,9 @@ type CreateOptsBuilder interface { ...@@ -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 ...@@ -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)
......
...@@ -83,6 +83,11 @@ type CreateResult struct { ...@@ -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
......
...@@ -55,6 +55,6 @@ func PageResultFromParsed(resp *http.Response, body interface{}) PageResult { ...@@ -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},
}) })
} }
...@@ -21,6 +21,12 @@ type ServiceClient struct { ...@@ -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 { ...@@ -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 ...@@ -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)
}
if v, ok := (JSONBody).(io.Reader); ok {
opts.RawBody = v
} else if JSONBody != nil {
opts.JSONBody = JSONBody
}
if JSONResponse != nil {
opts.JSONResponse = JSONResponse
} }
client.initReqOpts(url, JSONBody, JSONResponse, opts)
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)
return client.Request("DELETE", url, opts)
}
if opts.MoreHeaders == nil { func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) {
opts.MoreHeaders = make(map[string]string) 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
} }
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
return client.Request("DELETE", url, opts) if client.Type != "" {
opts.MoreHeaders["OpenStack-API-Version"] = client.Type + " " + client.Microversion
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment