From 278e6606534eef97e9086563f030f6de25fb36ff Mon Sep 17 00:00:00 2001 From: Jesse Haka Date: Fri, 22 Feb 2019 15:59:32 +0200 Subject: [PATCH] update gophercloud dependencies --- Gopkg.lock | 5 +- Gopkg.toml | 2 +- .../gophercloud/gophercloud/.travis.yml | 13 +- .../gophercloud/gophercloud/.zuul.yaml | 12 + .../gophercloud/gophercloud/BUILD.bazel | 1 + .../gophercloud/gophercloud/auth_options.go | 84 +++- .../gophercloud/gophercloud/auth_result.go | 52 +++ .../github.com/gophercloud/gophercloud/doc.go | 2 +- .../gophercloud/gophercloud/errors.go | 7 + .../github.com/gophercloud/gophercloud/go.mod | 7 + .../github.com/gophercloud/gophercloud/go.sum | 8 + .../gophercloud/openstack/auth_env.go | 55 ++- .../blockstorage/v2/volumes/requests.go | 36 +- .../gophercloud/openstack/client.go | 28 +- .../openstack/compute/v2/servers/BUILD.bazel | 1 + .../compute/v2/servers/microversions.go | 11 + .../openstack/compute/v2/servers/requests.go | 4 + .../openstack/dns/v2/recordsets/requests.go | 2 +- .../openstack/dns/v2/zones/requests.go | 2 +- .../openstack/identity/v2/tenants/requests.go | 2 +- .../openstack/identity/v2/tokens/results.go | 15 + .../openstack/identity/v3/tokens/requests.go | 23 +- .../openstack/identity/v3/tokens/results.go | 7 + .../loadbalancer/v2/l7policies/BUILD.bazel | 18 + .../loadbalancer/v2/l7policies/doc.go | 123 ++++++ .../loadbalancer/v2/l7policies/requests.go | 376 ++++++++++++++++++ .../loadbalancer/v2/l7policies/results.go | 237 +++++++++++ .../loadbalancer/v2/l7policies/urls.go | 25 ++ .../loadbalancer/v2/listeners/BUILD.bazel | 1 + .../loadbalancer/v2/listeners/doc.go | 3 + .../loadbalancer/v2/listeners/requests.go | 60 ++- .../loadbalancer/v2/listeners/results.go | 10 + .../loadbalancer/v2/loadbalancers/BUILD.bazel | 1 + .../loadbalancer/v2/loadbalancers/doc.go | 16 +- .../loadbalancer/v2/loadbalancers/requests.go | 62 ++- .../loadbalancer/v2/loadbalancers/results.go | 18 + .../loadbalancer/v2/loadbalancers/urls.go | 5 + .../loadbalancer/v2/monitors/requests.go | 2 +- .../loadbalancer/v2/monitors/results.go | 3 + .../openstack/loadbalancer/v2/pools/doc.go | 34 +- .../loadbalancer/v2/pools/requests.go | 48 ++- .../loadbalancer/v2/pools/results.go | 47 +++ .../v2/extensions/layer3/floatingips/doc.go | 2 +- .../extensions/layer3/floatingips/requests.go | 21 +- .../extensions/layer3/floatingips/results.go | 6 + .../v2/extensions/layer3/routers/requests.go | 7 + .../v2/extensions/layer3/routers/results.go | 8 +- .../v2/extensions/security/groups/requests.go | 23 +- .../v2/extensions/security/groups/results.go | 3 + .../v2/extensions/security/rules/requests.go | 4 + .../v2/extensions/security/rules/results.go | 3 + .../networking/v2/networks/requests.go | 13 +- .../networking/v2/networks/results.go | 6 + .../openstack/networking/v2/ports/requests.go | 13 +- .../openstack/networking/v2/ports/results.go | 6 + .../networking/v2/subnets/requests.go | 15 + .../networking/v2/subnets/results.go | 6 + .../objectstorage/v1/containers/requests.go | 3 + .../objectstorage/v1/containers/results.go | 1 + .../gophercloud/gophercloud/params.go | 16 + .../gophercloud/provider_client.go | 138 ++++++- .../gophercloud/gophercloud/results.go | 56 +-- .../gophercloud/gophercloud/service_client.go | 2 + 63 files changed, 1653 insertions(+), 167 deletions(-) create mode 100644 vendor/github.com/gophercloud/gophercloud/auth_result.go create mode 100644 vendor/github.com/gophercloud/gophercloud/go.mod create mode 100644 vendor/github.com/gophercloud/gophercloud/go.sum create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/microversions.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/BUILD.bazel create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/doc.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/requests.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/results.go create mode 100644 vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/urls.go diff --git a/Gopkg.lock b/Gopkg.lock index b1ca5ccb6b..bb2663864a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -616,7 +616,7 @@ revision = "0c5108395e2debce0d731cf0287ddf7242066aba" [[projects]] - digest = "1:a59e42230741fb00ffd95d61a731b6ee13500ad18400c5e0dd651acd3d30e4ba" + digest = "1:33cfd57691761d62c8f84c2748e3ea2690234b4d8b622856539a5175b7fc3bfd" name = "github.com/gophercloud/gophercloud" packages = [ ".", @@ -636,6 +636,7 @@ "openstack/identity/v2/tenants", "openstack/identity/v2/tokens", "openstack/identity/v3/tokens", + "openstack/loadbalancer/v2/l7policies", "openstack/loadbalancer/v2/listeners", "openstack/loadbalancer/v2/loadbalancers", "openstack/loadbalancer/v2/monitors", @@ -655,7 +656,7 @@ "pagination", ] pruneopts = "UT" - revision = "f29afc2cceca860199ee88cd355a4d0a37b3fad2" + revision = "dcc6e84aef1b6713accea7d7d7252ad2bc0e7034" [[projects]] digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1" diff --git a/Gopkg.toml b/Gopkg.toml index 423f93c601..f39c919ef5 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -455,4 +455,4 @@ required = [ revision = "bf70f2a70fb1b1f36d90d671a72795984eab0fcb" [[override]] name = "github.com/gophercloud/gophercloud" - revision = "f29afc2cceca860199ee88cd355a4d0a37b3fad2" + revision = "dcc6e84aef1b6713accea7d7d7252ad2bc0e7034" diff --git a/vendor/github.com/gophercloud/gophercloud/.travis.yml b/vendor/github.com/gophercloud/gophercloud/.travis.yml index 02728f4968..0955f170ea 100644 --- a/vendor/github.com/gophercloud/gophercloud/.travis.yml +++ b/vendor/github.com/gophercloud/gophercloud/.travis.yml @@ -1,21 +1,24 @@ language: go sudo: false install: -- go get golang.org/x/crypto/ssh -- 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 +- GO111MODULE=off go get golang.org/x/crypto/ssh +- GO111MODULE=off go get -v -tags 'fixtures acceptance' ./... +- GO111MODULE=off go get github.com/wadey/gocovmerge +- GO111MODULE=off go get github.com/mattn/goveralls +- GO111MODULE=off go get golang.org/x/tools/cmd/goimports go: - "1.10" +- "1.11" - "tip" env: global: - secure: "xSQsAG5wlL9emjbCdxzz/hYQsSpJ/bABO1kkbwMSISVcJ3Nk0u4ywF+LS4bgeOnwPfmFvNTOqVDu3RwEvMeWXSI76t1piCPcObutb2faKLVD/hLoAS76gYX+Z8yGWGHrSB7Do5vTPj1ERe2UljdrnsSeOXzoDwFxYRaZLX4bBOB4AyoGvRniil5QXPATiA1tsWX1VMicj8a4F8X+xeESzjt1Q5Iy31e7vkptu71bhvXCaoo5QhYwT+pLR9dN0S1b7Ro0KVvkRefmr1lUOSYd2e74h6Lc34tC1h3uYZCS4h47t7v5cOXvMNxinEj2C51RvbjvZI1RLVdkuAEJD1Iz4+Ote46nXbZ//6XRZMZz/YxQ13l7ux1PFjgEB6HAapmF5Xd8PRsgeTU9LRJxpiTJ3P5QJ3leS1va8qnziM5kYipj/Rn+V8g2ad/rgkRox9LSiR9VYZD2Pe45YCb1mTKSl2aIJnV7nkOqsShY5LNB4JZSg7xIffA+9YVDktw8dJlATjZqt7WvJJ49g6A61mIUV4C15q2JPGKTkZzDiG81NtmS7hFa7k0yaE2ELgYocbcuyUcAahhxntYTC0i23nJmEHVNiZmBO3u7EgpWe4KGVfumU+lt12tIn5b3dZRBBUk3QakKKozSK1QPHGpk/AZGrhu7H6l8to6IICKWtDcyMPQ=" + - GO111MODULE=on before_script: - go vet ./... script: - ./script/coverage +- ./script/unittest - ./script/format after_success: - $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out diff --git a/vendor/github.com/gophercloud/gophercloud/.zuul.yaml b/vendor/github.com/gophercloud/gophercloud/.zuul.yaml index 92fd9d4826..8c31ea160e 100644 --- a/vendor/github.com/gophercloud/gophercloud/.zuul.yaml +++ b/vendor/github.com/gophercloud/gophercloud/.zuul.yaml @@ -22,6 +22,15 @@ global_env: OS_BRANCH: stable/queens +- job: + name: gophercloud-acceptance-test-rocky + parent: gophercloud-acceptance-test + description: | + Run gophercloud acceptance test on rocky branch + vars: + global_env: + OS_BRANCH: stable/rocky + - job: name: gophercloud-acceptance-test-pike parent: gophercloud-acceptance-test @@ -80,6 +89,9 @@ recheck-queens: jobs: - gophercloud-acceptance-test-queens + recheck-rocky: + jobs: + - gophercloud-acceptance-test-rocky periodic: jobs: - gophercloud-unittest diff --git a/vendor/github.com/gophercloud/gophercloud/BUILD.bazel b/vendor/github.com/gophercloud/gophercloud/BUILD.bazel index d62541cb8b..27a3591e57 100644 --- a/vendor/github.com/gophercloud/gophercloud/BUILD.bazel +++ b/vendor/github.com/gophercloud/gophercloud/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "auth_options.go", + "auth_result.go", "doc.go", "endpoint_search.go", "errors.go", diff --git a/vendor/github.com/gophercloud/gophercloud/auth_options.go b/vendor/github.com/gophercloud/gophercloud/auth_options.go index 5e693585c2..5ffa8d1e0a 100644 --- a/vendor/github.com/gophercloud/gophercloud/auth_options.go +++ b/vendor/github.com/gophercloud/gophercloud/auth_options.go @@ -84,6 +84,12 @@ type AuthOptions struct { // Scope determines the scoping of the authentication request. Scope *AuthScope `json:"-"` + + // Authentication through Application Credentials requires supplying name, project and secret + // For project we can use TenantID + ApplicationCredentialID string `json:"-"` + ApplicationCredentialName string `json:"-"` + ApplicationCredentialSecret string `json:"-"` } // AuthScope allows a created token to be limited to a specific domain or project. @@ -142,7 +148,7 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s type userReq struct { ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` - Password string `json:"password"` + Password string `json:"password,omitempty"` Domain *domainReq `json:"domain,omitempty"` } @@ -154,10 +160,18 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s ID string `json:"id"` } + type applicationCredentialReq struct { + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + User *userReq `json:"user,omitempty"` + Secret *string `json:"secret,omitempty"` + } + type identityReq struct { - Methods []string `json:"methods"` - Password *passwordReq `json:"password,omitempty"` - Token *tokenReq `json:"token,omitempty"` + Methods []string `json:"methods"` + Password *passwordReq `json:"password,omitempty"` + Token *tokenReq `json:"token,omitempty"` + ApplicationCredential *applicationCredentialReq `json:"application_credential,omitempty"` } type authReq struct { @@ -194,8 +208,68 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s req.Auth.Identity.Token = &tokenReq{ ID: opts.TokenID, } + + } else if opts.ApplicationCredentialID != "" { + // Configure the request for ApplicationCredentialID authentication. + // https://github.com/openstack/keystoneauth/blob/stable/rocky/keystoneauth1/identity/v3/application_credential.py#L48-L67 + // There are three kinds of possible application_credential requests + // 1. application_credential id + secret + // 2. application_credential name + secret + user_id + // 3. application_credential name + secret + username + domain_id / domain_name + if opts.ApplicationCredentialSecret == "" { + return nil, ErrAppCredMissingSecret{} + } + req.Auth.Identity.Methods = []string{"application_credential"} + req.Auth.Identity.ApplicationCredential = &applicationCredentialReq{ + ID: &opts.ApplicationCredentialID, + Secret: &opts.ApplicationCredentialSecret, + } + } else if opts.ApplicationCredentialName != "" { + if opts.ApplicationCredentialSecret == "" { + return nil, ErrAppCredMissingSecret{} + } + + var userRequest *userReq + + if opts.UserID != "" { + // UserID could be used without the domain information + userRequest = &userReq{ + ID: &opts.UserID, + } + } + + if userRequest == nil && opts.Username == "" { + // Make sure that Username or UserID are provided + return nil, ErrUsernameOrUserID{} + } + + if userRequest == nil && opts.DomainID != "" { + userRequest = &userReq{ + Name: &opts.Username, + Domain: &domainReq{ID: &opts.DomainID}, + } + } + + if userRequest == nil && opts.DomainName != "" { + userRequest = &userReq{ + Name: &opts.Username, + Domain: &domainReq{Name: &opts.DomainName}, + } + } + + // Make sure that DomainID or DomainName are provided among Username + if userRequest == nil { + return nil, ErrDomainIDOrDomainName{} + } + + req.Auth.Identity.Methods = []string{"application_credential"} + req.Auth.Identity.ApplicationCredential = &applicationCredentialReq{ + Name: &opts.ApplicationCredentialName, + User: userRequest, + Secret: &opts.ApplicationCredentialSecret, + } } else { - // If no password or token ID are available, authentication can't continue. + // If no password or token ID or ApplicationCredential are available, authentication can't continue. return nil, ErrMissingPassword{} } } else { diff --git a/vendor/github.com/gophercloud/gophercloud/auth_result.go b/vendor/github.com/gophercloud/gophercloud/auth_result.go new file mode 100644 index 0000000000..2e4699b978 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/auth_result.go @@ -0,0 +1,52 @@ +package gophercloud + +/* +AuthResult is the result from the request that was used to obtain a provider +client's Keystone token. It is returned from ProviderClient.GetAuthResult(). + +The following types satisfy this interface: + + github.com/gophercloud/gophercloud/openstack/identity/v2/tokens.CreateResult + github.com/gophercloud/gophercloud/openstack/identity/v3/tokens.CreateResult + +Usage example: + + import ( + "github.com/gophercloud/gophercloud" + tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens" + tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" + ) + + func GetAuthenticatedUserID(providerClient *gophercloud.ProviderClient) (string, error) { + r := providerClient.GetAuthResult() + if r == nil { + //ProviderClient did not use openstack.Authenticate(), e.g. because token + //was set manually with ProviderClient.SetToken() + return "", errors.New("no AuthResult available") + } + switch r := r.(type) { + case tokens2.CreateResult: + u, err := r.ExtractUser() + if err != nil { + return "", err + } + return u.ID, nil + case tokens3.CreateResult: + u, err := r.ExtractUser() + if err != nil { + return "", err + } + return u.ID, nil + default: + panic(fmt.Sprintf("got unexpected AuthResult type %t", r)) + } + } + +Both implementing types share a lot of methods by name, like ExtractUser() in +this example. But those methods cannot be part of the AuthResult interface +because the return types are different (in this case, type tokens2.User vs. +type tokens3.User). +*/ +type AuthResult interface { + ExtractTokenID() (string, error) +} diff --git a/vendor/github.com/gophercloud/gophercloud/doc.go b/vendor/github.com/gophercloud/gophercloud/doc.go index 30067aa352..131cc8e303 100644 --- a/vendor/github.com/gophercloud/gophercloud/doc.go +++ b/vendor/github.com/gophercloud/gophercloud/doc.go @@ -41,7 +41,7 @@ pass in the parent provider, like so: opts := gophercloud.EndpointOpts{Region: "RegionOne"} - client := openstack.NewComputeV2(provider, opts) + client, err := openstack.NewComputeV2(provider, opts) Resources diff --git a/vendor/github.com/gophercloud/gophercloud/errors.go b/vendor/github.com/gophercloud/gophercloud/errors.go index a5fa68d6d5..4bf1024684 100644 --- a/vendor/github.com/gophercloud/gophercloud/errors.go +++ b/vendor/github.com/gophercloud/gophercloud/errors.go @@ -451,3 +451,10 @@ type ErrScopeEmpty struct{ BaseError } func (e ErrScopeEmpty) Error() string { return "You must provide either a Project or Domain in a Scope" } + +// ErrAppCredMissingSecret indicates that no Application Credential Secret was provided with Application Credential ID or Name +type ErrAppCredMissingSecret struct{ BaseError } + +func (e ErrAppCredMissingSecret) Error() string { + return "You must provide an Application Credential Secret" +} diff --git a/vendor/github.com/gophercloud/gophercloud/go.mod b/vendor/github.com/gophercloud/gophercloud/go.mod new file mode 100644 index 0000000000..d1ee3b472e --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/go.mod @@ -0,0 +1,7 @@ +module github.com/gophercloud/gophercloud + +require ( + golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 + golang.org/x/sys v0.0.0-20190209173611-3b5209105503 // indirect + gopkg.in/yaml.v2 v2.2.2 +) diff --git a/vendor/github.com/gophercloud/gophercloud/go.sum b/vendor/github.com/gophercloud/gophercloud/go.sum new file mode 100644 index 0000000000..33cb0be8aa --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/go.sum @@ -0,0 +1,8 @@ +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go b/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go index 994b5550c9..0bb1f48375 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/auth_env.go @@ -38,6 +38,9 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) { tenantName := os.Getenv("OS_TENANT_NAME") domainID := os.Getenv("OS_DOMAIN_ID") domainName := os.Getenv("OS_DOMAIN_NAME") + applicationCredentialID := os.Getenv("OS_APPLICATION_CREDENTIAL_ID") + applicationCredentialName := os.Getenv("OS_APPLICATION_CREDENTIAL_NAME") + applicationCredentialSecret := os.Getenv("OS_APPLICATION_CREDENTIAL_SECRET") // If OS_PROJECT_ID is set, overwrite tenantID with the value. if v := os.Getenv("OS_PROJECT_ID"); v != "" { @@ -56,29 +59,55 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) { return nilOptions, err } - if username == "" && userID == "" { - err := gophercloud.ErrMissingAnyoneOfEnvironmentVariables{ - EnvironmentVariables: []string{"OS_USERNAME", "OS_USERID"}, + if userID == "" && username == "" { + // Empty username and userID could be ignored, when applicationCredentialID and applicationCredentialSecret are set + if applicationCredentialID == "" && applicationCredentialSecret == "" { + err := gophercloud.ErrMissingAnyoneOfEnvironmentVariables{ + EnvironmentVariables: []string{"OS_USERID", "OS_USERNAME"}, + } + return nilOptions, err } - return nilOptions, err } - if password == "" { + if password == "" && applicationCredentialID == "" && applicationCredentialName == "" { err := gophercloud.ErrMissingEnvironmentVariable{ EnvironmentVariable: "OS_PASSWORD", } return nilOptions, err } + if (applicationCredentialID != "" || applicationCredentialName != "") && applicationCredentialSecret == "" { + err := gophercloud.ErrMissingEnvironmentVariable{ + EnvironmentVariable: "OS_APPLICATION_CREDENTIAL_SECRET", + } + return nilOptions, err + } + + if applicationCredentialID == "" && applicationCredentialName != "" && applicationCredentialSecret != "" { + if userID == "" && username == "" { + return nilOptions, gophercloud.ErrMissingAnyoneOfEnvironmentVariables{ + EnvironmentVariables: []string{"OS_USERID", "OS_USERNAME"}, + } + } + if username != "" && domainID == "" && domainName == "" { + return nilOptions, gophercloud.ErrMissingAnyoneOfEnvironmentVariables{ + EnvironmentVariables: []string{"OS_DOMAIN_ID", "OS_DOMAIN_NAME"}, + } + } + } + ao := gophercloud.AuthOptions{ - IdentityEndpoint: authURL, - UserID: userID, - Username: username, - Password: password, - TenantID: tenantID, - TenantName: tenantName, - DomainID: domainID, - DomainName: domainName, + IdentityEndpoint: authURL, + UserID: userID, + Username: username, + Password: password, + TenantID: tenantID, + TenantName: tenantName, + DomainID: domainID, + DomainName: domainName, + ApplicationCredentialID: applicationCredentialID, + ApplicationCredentialName: applicationCredentialName, + ApplicationCredentialSecret: applicationCredentialSecret, } return ao, nil diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go index b7977cbc8f..c27ddbf67c 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes/requests.go @@ -61,9 +61,37 @@ func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r Create return } +// DeleteOptsBuilder allows extensions to add additional parameters to the +// Delete request. +type DeleteOptsBuilder interface { + ToVolumeDeleteQuery() (string, error) +} + +// DeleteOpts contains options for deleting a Volume. This object is passed to +// the volumes.Delete function. +type DeleteOpts struct { + // Delete all snapshots of this volume as well. + Cascade bool `q:"cascade"` +} + +// ToLoadBalancerDeleteQuery formats a DeleteOpts into a query string. +func (opts DeleteOpts) ToVolumeDeleteQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + // Delete will delete the existing Volume with the provided ID. -func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) { - _, r.Err = client.Delete(deleteURL(client, id), nil) +func Delete(client *gophercloud.ServiceClient, id string, opts DeleteOptsBuilder) (r DeleteResult) { + url := deleteURL(client, id) + if opts != nil { + query, err := opts.ToVolumeDeleteQuery() + if err != nil { + r.Err = err + return + } + url += query + } + _, r.Err = client.Delete(url, nil) return } @@ -145,8 +173,8 @@ type UpdateOptsBuilder interface { // to the volumes.Update function. For more information about the parameters, see // the Volume object. type UpdateOpts struct { - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` Metadata map[string]string `json:"metadata,omitempty"` } diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/client.go b/vendor/github.com/gophercloud/gophercloud/openstack/client.go index 0859d9cb75..064a70dbed 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/client.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/client.go @@ -135,7 +135,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc result := tokens2.Create(v2Client, v2Opts) - token, err := result.ExtractToken() + err = client.SetTokenAndAuthResult(result) if err != nil { return err } @@ -150,8 +150,9 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc // with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`, // this should retry authentication only once tac := *client + tac.SetThrowaway(true) tac.ReauthFunc = nil - tac.TokenID = "" + tac.SetTokenAndAuthResult(nil) tao := options tao.AllowReauth = false client.ReauthFunc = func() error { @@ -159,11 +160,10 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc if err != nil { return err } - client.TokenID = tac.TokenID + client.CopyTokenFrom(&tac) return nil } } - client.TokenID = token.ID client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { return V2EndpointURL(catalog, opts) } @@ -189,7 +189,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au result := tokens3.Create(v3Client, opts) - token, err := result.ExtractToken() + err = client.SetTokenAndAuthResult(result) if err != nil { return err } @@ -199,15 +199,14 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au return err } - client.TokenID = token.ID - if opts.CanReauth() { // here we're creating a throw-away client (tac). it's a copy of the user's provider client, but // with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`, // this should retry authentication only once tac := *client + tac.SetThrowaway(true) tac.ReauthFunc = nil - tac.TokenID = "" + tac.SetTokenAndAuthResult(nil) var tao tokens3.AuthOptionsBuilder switch ot := opts.(type) { case *gophercloud.AuthOptions: @@ -226,7 +225,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au if err != nil { return err } - client.TokenID = tac.TokenID + client.CopyTokenFrom(&tac) return nil } } @@ -305,6 +304,12 @@ func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointO return sc, nil } +// NewBareMetalV1 creates a ServiceClient that may be used with the v1 +// bare metal package. +func NewBareMetalV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + return initClientOpts(client, eo, "baremetal") +} + // 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) { @@ -420,3 +425,8 @@ func NewKeyManagerV1(client *gophercloud.ProviderClient, eo gophercloud.Endpoint func NewContainerInfraV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { return initClientOpts(client, eo, "container-infra") } + +// NewWorkflowV2 creates a ServiceClient that may be used with the v2 workflow management package. +func NewWorkflowV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + return initClientOpts(client, eo, "workflowv2") +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/BUILD.bazel b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/BUILD.bazel index 27d600316d..c780a81be7 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/BUILD.bazel +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "doc.go", "errors.go", + "microversions.go", "requests.go", "results.go", "urls.go", diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/microversions.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/microversions.go new file mode 100644 index 0000000000..84ec9f31d3 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/microversions.go @@ -0,0 +1,11 @@ +package servers + +// ExtractTags will extract the tags of a server. +// This requires the client to be set to microversion 2.26 or later. +func (r serverResult) ExtractTags() ([]string, error) { + var s struct { + Tags []string `json:"tags"` + } + err := r.ExtractInto(&s) + return s.Tags, err +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go index a6530f8d65..646bd4ccf1 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers/requests.go @@ -189,6 +189,10 @@ type CreateOpts struct { // ServiceClient will allow calls to be made to retrieve an image or // flavor ID by name. ServiceClient *gophercloud.ServiceClient `json:"-"` + + // Tags allows a server to be tagged with single-word metadata. + // Requires microversion 2.52 or later. + Tags []string `json:"tags,omitempty"` } // ToServerCreateMap assembles a request body based on the contents of a diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/requests.go index 2d6ecdc3dc..2bc4579727 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/requests.go @@ -119,7 +119,7 @@ type UpdateOptsBuilder interface { // RecordSet. type UpdateOpts struct { // Description is a description of the RecordSet. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` // TTL is the time to live of the RecordSet. TTL int `json:"ttl,omitempty"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones/requests.go index f87deadce7..78b08ae4f8 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones/requests.go @@ -134,7 +134,7 @@ type UpdateOpts struct { Masters []string `json:"masters,omitempty"` // Description of the zone. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` } // ToZoneUpdateMap formats an UpdateOpts structure into a request body. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go index 60f58c8ce3..f21a58f10c 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tenants/requests.go @@ -85,7 +85,7 @@ type UpdateOpts struct { Name string `json:"name,omitempty"` // Description is the description of the tenant. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` // Enabled sets the tenant status to enabled or disabled. Enabled *bool `json:"enabled,omitempty"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go index b11326772b..ee5da37f46 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/results.go @@ -135,6 +135,21 @@ func (r CreateResult) ExtractToken() (*Token, error) { }, nil } +// ExtractTokenID implements the gophercloud.AuthResult interface. The returned +// string is the same as the ID field of the Token struct returned from +// ExtractToken(). +func (r CreateResult) ExtractTokenID() (string, error) { + var s struct { + Access struct { + Token struct { + ID string `json:"id"` + } `json:"token"` + } `json:"access"` + } + err := r.ExtractInto(&s) + return s.Access.Token.ID, err +} + // ExtractServiceCatalog returns the ServiceCatalog that was generated along // with the user's Token. func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go index 6e99a793c5..2d20fa6f4b 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/requests.go @@ -52,19 +52,28 @@ type AuthOptions struct { // authentication token ID. TokenID string `json:"-"` + // Authentication through Application Credentials requires supplying name, project and secret + // For project we can use TenantID + ApplicationCredentialID string `json:"-"` + ApplicationCredentialName string `json:"-"` + ApplicationCredentialSecret string `json:"-"` + Scope Scope `json:"-"` } // ToTokenV3CreateMap builds a request body from AuthOptions. func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) { gophercloudAuthOpts := gophercloud.AuthOptions{ - Username: opts.Username, - UserID: opts.UserID, - Password: opts.Password, - DomainID: opts.DomainID, - DomainName: opts.DomainName, - AllowReauth: opts.AllowReauth, - TokenID: opts.TokenID, + Username: opts.Username, + UserID: opts.UserID, + Password: opts.Password, + DomainID: opts.DomainID, + DomainName: opts.DomainName, + AllowReauth: opts.AllowReauth, + TokenID: opts.TokenID, + ApplicationCredentialID: opts.ApplicationCredentialID, + ApplicationCredentialName: opts.ApplicationCredentialName, + ApplicationCredentialSecret: opts.ApplicationCredentialSecret, } return gophercloudAuthOpts.ToTokenV3CreateMap(scope) diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go index ebdca58f65..6f26c96bcd 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/tokens/results.go @@ -102,6 +102,13 @@ func (r commonResult) ExtractToken() (*Token, error) { return &s, err } +// ExtractTokenID implements the gophercloud.AuthResult interface. The returned +// string is the same as the ID field of the Token struct returned from +// ExtractToken(). +func (r CreateResult) ExtractTokenID() (string, error) { + return r.Header.Get("X-Subject-Token"), r.Err +} + // ExtractServiceCatalog returns the ServiceCatalog that was generated along // with the user's Token. func (r commonResult) ExtractServiceCatalog() (*ServiceCatalog, error) { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/BUILD.bazel b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/BUILD.bazel new file mode 100644 index 0000000000..57349a67a0 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/BUILD.bazel @@ -0,0 +1,18 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "requests.go", + "results.go", + "urls.go", + ], + importmap = "k8s.io/kops/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies", + importpath = "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/gophercloud/gophercloud:go_default_library", + "//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library", + ], +) diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/doc.go new file mode 100644 index 0000000000..813579905c --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/doc.go @@ -0,0 +1,123 @@ +/* +Package l7policies provides information and interaction with L7Policies and +Rules of the LBaaS v2 extension for the OpenStack Networking service. + +Example to Create a L7Policy + + createOpts := l7policies.CreateOpts{ + Name: "redirect-example.com", + ListenerID: "023f2e34-7806-443b-bfae-16c324569a3d", + Action: l7policies.ActionRedirectToURL, + RedirectURL: "http://www.example.com", + } + l7policy, err := l7policies.Create(lbClient, createOpts).Extract() + if err != nil { + panic(err) + } + +Example to List L7Policies + + listOpts := l7policies.ListOpts{ + ListenerID: "c79a4468-d788-410c-bf79-9a8ef6354852", + } + allPages, err := l7policies.List(lbClient, listOpts).AllPages() + if err != nil { + panic(err) + } + allL7Policies, err := l7policies.ExtractL7Policies(allPages) + if err != nil { + panic(err) + } + for _, l7policy := range allL7Policies { + fmt.Printf("%+v\n", l7policy) + } + +Example to Get a L7Policy + + l7policy, err := l7policies.Get(lbClient, "023f2e34-7806-443b-bfae-16c324569a3d").Extract() + if err != nil { + panic(err) + } + +Example to Delete a L7Policy + + l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64" + err := l7policies.Delete(lbClient, l7policyID).ExtractErr() + if err != nil { + panic(err) + } + +Example to Update a L7Policy + + l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64" + name := "new-name" + updateOpts := l7policies.UpdateOpts{ + Name: &name, + } + l7policy, err := l7policies.Update(lbClient, l7policyID, updateOpts).Extract() + if err != nil { + panic(err) + } + +Example to Create a Rule + + l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64" + createOpts := l7policies.CreateRuleOpts{ + RuleType: l7policies.TypePath, + CompareType: l7policies.CompareTypeRegex, + Value: "/images*", + } + rule, err := l7policies.CreateRule(lbClient, l7policyID, createOpts).Extract() + if err != nil { + panic(err) + } + +Example to List L7 Rules + + l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64" + listOpts := l7policies.ListRulesOpts{ + RuleType: l7policies.TypePath, + } + allPages, err := l7policies.ListRules(lbClient, l7policyID, listOpts).AllPages() + if err != nil { + panic(err) + } + allRules, err := l7policies.ExtractRules(allPages) + if err != nil { + panic(err) + } + for _, rule := allRules { + fmt.Printf("%+v\n", rule) + } + +Example to Get a l7 rule + + l7rule, err := l7policies.GetRule(lbClient, "023f2e34-7806-443b-bfae-16c324569a3d", "53ad8ab8-40fa-11e8-a508-00224d6b7bc1").Extract() + if err != nil { + panic(err) + } + +Example to Delete a l7 rule + + l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64" + ruleID := "64dba99f-8af8-4200-8882-e32a0660f23e" + err := l7policies.DeleteRule(lbClient, l7policyID, ruleID).ExtractErr() + if err != nil { + panic(err) + } + +Example to Update a Rule + + l7policyID := "d67d56a6-4a86-4688-a282-f46444705c64" + ruleID := "64dba99f-8af8-4200-8882-e32a0660f23e" + updateOpts := l7policies.UpdateRuleOpts{ + RuleType: l7policies.TypePath, + CompareType: l7policies.CompareTypeRegex, + Value: "/images/special*", + } + rule, err := l7policies.UpdateRule(lbClient, l7policyID, ruleID, updateOpts).Extract() + if err != nil { + panic(err) + } +*/ +package l7policies diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/requests.go new file mode 100644 index 0000000000..fc1c809afa --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/requests.go @@ -0,0 +1,376 @@ +package l7policies + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToL7PolicyCreateMap() (map[string]interface{}, error) +} + +type Action string +type RuleType string +type CompareType string + +const ( + ActionRedirectToPool Action = "REDIRECT_TO_POOL" + ActionRedirectToURL Action = "REDIRECT_TO_URL" + ActionReject Action = "REJECT" + + TypeCookie RuleType = "COOKIE" + TypeFileType RuleType = "FILE_TYPE" + TypeHeader RuleType = "HEADER" + TypeHostName RuleType = "HOST_NAME" + TypePath RuleType = "PATH" + + CompareTypeContains CompareType = "CONTAINS" + CompareTypeEndWith CompareType = "ENDS_WITH" + CompareTypeEqual CompareType = "EQUAL_TO" + CompareTypeRegex CompareType = "REGEX" + CompareTypeStartWith CompareType = "STARTS_WITH" +) + +// CreateOpts is the common options struct used in this package's Create +// operation. +type CreateOpts struct { + // Name of the L7 policy. + Name string `json:"name,omitempty"` + + // The ID of the listener. + ListenerID string `json:"listener_id" required:"true"` + + // The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT. + Action Action `json:"action" required:"true"` + + // The position of this policy on the listener. + Position int32 `json:"position,omitempty"` + + // A human-readable description for the resource. + Description string `json:"description,omitempty"` + + // ProjectID is the UUID of the project who owns the L7 policy in octavia. + // Only administrative users can specify a project UUID other than their own. + ProjectID string `json:"project_id,omitempty"` + + // Requests matching this policy will be redirected to the pool with this ID. + // Only valid if action is REDIRECT_TO_POOL. + RedirectPoolID string `json:"redirect_pool_id,omitempty"` + + // Requests matching this policy will be redirected to this URL. + // Only valid if action is REDIRECT_TO_URL. + RedirectURL string `json:"redirect_url,omitempty"` + + // The administrative state of the Loadbalancer. A valid value is true (UP) + // or false (DOWN). + AdminStateUp *bool `json:"admin_state_up,omitempty"` +} + +// ToL7PolicyCreateMap builds a request body from CreateOpts. +func (opts CreateOpts) ToL7PolicyCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "l7policy") +} + +// Create accepts a CreateOpts struct and uses the values to create a new l7policy. +func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + b, err := opts.ToL7PolicyCreateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = c.Post(rootURL(c), b, &r.Body, nil) + return +} + +// ListOptsBuilder allows extensions to add additional parameters to the +// List request. +type ListOptsBuilder interface { + ToL7PolicyListQuery() (string, error) +} + +// ListOpts allows the filtering and sorting of paginated collections through +// the API. +type ListOpts struct { + Name string `q:"name"` + Description string `q:"description"` + ListenerID string `q:"listener_id"` + Action string `q:"action"` + ProjectID string `q:"project_id"` + RedirectPoolID string `q:"redirect_pool_id"` + RedirectURL string `q:"redirect_url"` + Position int32 `q:"position"` + AdminStateUp bool `q:"admin_state_up"` + ID string `q:"id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToL7PolicyListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToL7PolicyListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// List returns a Pager which allows you to iterate over a collection of +// l7policies. It accepts a ListOpts struct, which allows you to filter and sort +// the returned collection for greater efficiency. +// +// Default policy settings return only those l7policies that are owned by the +// project who submits the request, unless an admin user submits the request. +func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(c) + if opts != nil { + query, err := opts.ToL7PolicyListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return L7PolicyPage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// Get retrieves a particular l7policy based on its unique ID. +func Get(c *gophercloud.ServiceClient, id string) (r GetResult) { + _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil) + return +} + +// Delete will permanently delete a particular l7policy based on its unique ID. +func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) { + _, r.Err = c.Delete(resourceURL(c, id), nil) + return +} + +// UpdateOptsBuilder allows extensions to add additional parameters to the +// Update request. +type UpdateOptsBuilder interface { + ToL7PolicyUpdateMap() (map[string]interface{}, error) +} + +// UpdateOpts is the common options struct used in this package's Update +// operation. +type UpdateOpts struct { + // Name of the L7 policy, empty string is allowed. + Name *string `json:"name,omitempty"` + + // The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT. + Action Action `json:"action,omitempty"` + + // The position of this policy on the listener. + Position int32 `json:"position,omitempty"` + + // A human-readable description for the resource, empty string is allowed. + Description *string `json:"description,omitempty"` + + // Requests matching this policy will be redirected to the pool with this ID. + // Only valid if action is REDIRECT_TO_POOL. + RedirectPoolID *string `json:"redirect_pool_id,omitempty"` + + // Requests matching this policy will be redirected to this URL. + // Only valid if action is REDIRECT_TO_URL. + RedirectURL *string `json:"redirect_url,omitempty"` + + // The administrative state of the Loadbalancer. A valid value is true (UP) + // or false (DOWN). + AdminStateUp *bool `json:"admin_state_up,omitempty"` +} + +// ToL7PolicyUpdateMap builds a request body from UpdateOpts. +func (opts UpdateOpts) ToL7PolicyUpdateMap() (map[string]interface{}, error) { + b, err := gophercloud.BuildRequestBody(opts, "l7policy") + if err != nil { + return nil, err + } + + m := b["l7policy"].(map[string]interface{}) + + if m["redirect_pool_id"] == "" { + m["redirect_pool_id"] = nil + } + + if m["redirect_url"] == "" { + m["redirect_url"] = nil + } + + return b, nil +} + +// Update allows l7policy to be updated. +func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) { + b, err := opts.ToL7PolicyUpdateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200}, + }) + return +} + +// CreateRuleOpts is the common options struct used in this package's CreateRule +// operation. +type CreateRuleOpts struct { + // The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH. + RuleType RuleType `json:"type" required:"true"` + + // The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH. + CompareType CompareType `json:"compare_type" required:"true"` + + // The value to use for the comparison. For example, the file type to compare. + Value string `json:"value" required:"true"` + + // ProjectID is the UUID of the project who owns the rule in octavia. + // Only administrative users can specify a project UUID other than their own. + ProjectID string `json:"project_id,omitempty"` + + // The key to use for the comparison. For example, the name of the cookie to evaluate. + Key string `json:"key,omitempty"` + + // When true the logic of the rule is inverted. For example, with invert true, + // equal to would become not equal to. Default is false. + Invert bool `json:"invert,omitempty"` + + // The administrative state of the Loadbalancer. A valid value is true (UP) + // or false (DOWN). + AdminStateUp *bool `json:"admin_state_up,omitempty"` +} + +// ToRuleCreateMap builds a request body from CreateRuleOpts. +func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "rule") +} + +// CreateRule will create and associate a Rule with a particular L7Policy. +func CreateRule(c *gophercloud.ServiceClient, policyID string, opts CreateRuleOpts) (r CreateRuleResult) { + b, err := opts.ToRuleCreateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = c.Post(ruleRootURL(c, policyID), b, &r.Body, nil) + return +} + +// ListRulesOptsBuilder allows extensions to add additional parameters to the +// ListRules request. +type ListRulesOptsBuilder interface { + ToRulesListQuery() (string, error) +} + +// ListRulesOpts allows the filtering and sorting of paginated collections +// through the API. +type ListRulesOpts struct { + RuleType RuleType `q:"type"` + ProjectID string `q:"project_id"` + CompareType CompareType `q:"compare_type"` + Value string `q:"value"` + Key string `q:"key"` + Invert bool `q:"invert"` + AdminStateUp bool `q:"admin_state_up"` + ID string `q:"id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` +} + +// ToRulesListQuery formats a ListOpts into a query string. +func (opts ListRulesOpts) ToRulesListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// ListRules returns a Pager which allows you to iterate over a collection of +// rules. It accepts a ListRulesOptsBuilder, which allows you to filter and +// sort the returned collection for greater efficiency. +// +// Default policy settings return only those rules that are owned by the +// project who submits the request, unless an admin user submits the request. +func ListRules(c *gophercloud.ServiceClient, policyID string, opts ListRulesOptsBuilder) pagination.Pager { + url := ruleRootURL(c, policyID) + if opts != nil { + query, err := opts.ToRulesListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page { + return RulePage{pagination.LinkedPageBase{PageResult: r}} + }) +} + +// GetRule retrieves a particular L7Policy Rule based on its unique ID. +func GetRule(c *gophercloud.ServiceClient, policyID string, ruleID string) (r GetRuleResult) { + _, r.Err = c.Get(ruleResourceURL(c, policyID, ruleID), &r.Body, nil) + return +} + +// DeleteRule will remove a Rule from a particular L7Policy. +func DeleteRule(c *gophercloud.ServiceClient, policyID string, ruleID string) (r DeleteRuleResult) { + _, r.Err = c.Delete(ruleResourceURL(c, policyID, ruleID), nil) + return +} + +// UpdateRuleOptsBuilder allows to add additional parameters to the PUT request. +type UpdateRuleOptsBuilder interface { + ToRuleUpdateMap() (map[string]interface{}, error) +} + +// UpdateRuleOpts is the common options struct used in this package's Update +// operation. +type UpdateRuleOpts struct { + // The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH. + RuleType RuleType `json:"type,omitempty"` + + // The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH. + CompareType CompareType `json:"compare_type,omitempty"` + + // The value to use for the comparison. For example, the file type to compare. + Value string `json:"value,omitempty"` + + // The key to use for the comparison. For example, the name of the cookie to evaluate. + Key *string `json:"key,omitempty"` + + // When true the logic of the rule is inverted. For example, with invert true, + // equal to would become not equal to. Default is false. + Invert *bool `json:"invert,omitempty"` + + // The administrative state of the Loadbalancer. A valid value is true (UP) + // or false (DOWN). + AdminStateUp *bool `json:"admin_state_up,omitempty"` +} + +// ToRuleUpdateMap builds a request body from UpdateRuleOpts. +func (opts UpdateRuleOpts) ToRuleUpdateMap() (map[string]interface{}, error) { + b, err := gophercloud.BuildRequestBody(opts, "rule") + if err != nil { + return nil, err + } + + if m := b["rule"].(map[string]interface{}); m["key"] == "" { + m["key"] = nil + } + + return b, nil +} + +// UpdateRule allows Rule to be updated. +func UpdateRule(c *gophercloud.ServiceClient, policyID string, ruleID string, opts UpdateRuleOptsBuilder) (r UpdateRuleResult) { + b, err := opts.ToRuleUpdateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = c.Put(ruleResourceURL(c, policyID, ruleID), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 201, 202}, + }) + return +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/results.go new file mode 100644 index 0000000000..dafcceed14 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/results.go @@ -0,0 +1,237 @@ +package l7policies + +import ( + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/pagination" +) + +// L7Policy is a collection of L7 rules associated with a Listener, and which +// may also have an association to a back-end pool. +type L7Policy struct { + // The unique ID for the L7 policy. + ID string `json:"id"` + + // Name of the L7 policy. + Name string `json:"name"` + + // The ID of the listener. + ListenerID string `json:"listener_id"` + + // The L7 policy action. One of REDIRECT_TO_POOL, REDIRECT_TO_URL, or REJECT. + Action string `json:"action"` + + // The position of this policy on the listener. + Position int32 `json:"position"` + + // A human-readable description for the resource. + Description string `json:"description"` + + // ProjectID is the UUID of the project who owns the L7 policy in octavia. + // Only administrative users can specify a project UUID other than their own. + ProjectID string `json:"project_id"` + + // Requests matching this policy will be redirected to the pool with this ID. + // Only valid if action is REDIRECT_TO_POOL. + RedirectPoolID string `json:"redirect_pool_id"` + + // Requests matching this policy will be redirected to this URL. + // Only valid if action is REDIRECT_TO_URL. + RedirectURL string `json:"redirect_url"` + + // The administrative state of the L7 policy, which is up (true) or down (false). + AdminStateUp bool `json:"admin_state_up"` + + // The provisioning status of the L7 policy. + // This value is ACTIVE, PENDING_* or ERROR. + ProvisioningStatus string `json:"provisioning_status"` + + // The operating status of the L7 policy. + OperatingStatus string `json:"operating_status"` + + // Rules are List of associated L7 rule IDs. + Rules []Rule `json:"rules"` +} + +// Rule represents layer 7 load balancing rule. +type Rule struct { + // The unique ID for the L7 rule. + ID string `json:"id"` + + // The L7 rule type. One of COOKIE, FILE_TYPE, HEADER, HOST_NAME, or PATH. + RuleType string `json:"type"` + + // The comparison type for the L7 rule. One of CONTAINS, ENDS_WITH, EQUAL_TO, REGEX, or STARTS_WITH. + CompareType string `json:"compare_type"` + + // The value to use for the comparison. For example, the file type to compare. + Value string `json:"value"` + + // ProjectID is the UUID of the project who owns the rule in octavia. + // Only administrative users can specify a project UUID other than their own. + ProjectID string `json:"project_id"` + + // The key to use for the comparison. For example, the name of the cookie to evaluate. + Key string `json:"key"` + + // When true the logic of the rule is inverted. For example, with invert true, + // equal to would become not equal to. Default is false. + Invert bool `json:"invert"` + + // The administrative state of the L7 rule, which is up (true) or down (false). + AdminStateUp bool `json:"admin_state_up"` + + // The provisioning status of the L7 rule. + // This value is ACTIVE, PENDING_* or ERROR. + ProvisioningStatus string `json:"provisioning_status"` + + // The operating status of the L7 policy. + OperatingStatus string `json:"operating_status"` +} + +type commonResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a l7policy. +func (r commonResult) Extract() (*L7Policy, error) { + var s struct { + L7Policy *L7Policy `json:"l7policy"` + } + err := r.ExtractInto(&s) + return s.L7Policy, err +} + +// CreateResult represents the result of a Create operation. Call its Extract +// method to interpret the result as a L7Policy. +type CreateResult struct { + commonResult +} + +// L7PolicyPage is the page returned by a pager when traversing over a +// collection of l7policies. +type L7PolicyPage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of l7policies has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (r L7PolicyPage) NextPageURL() (string, error) { + var s struct { + Links []gophercloud.Link `json:"l7policies_links"` + } + err := r.ExtractInto(&s) + if err != nil { + return "", err + } + return gophercloud.ExtractNextURL(s.Links) +} + +// IsEmpty checks whether a L7PolicyPage struct is empty. +func (r L7PolicyPage) IsEmpty() (bool, error) { + is, err := ExtractL7Policies(r) + return len(is) == 0, err +} + +// ExtractL7Policies accepts a Page struct, specifically a L7PolicyPage struct, +// and extracts the elements into a slice of L7Policy structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractL7Policies(r pagination.Page) ([]L7Policy, error) { + var s struct { + L7Policies []L7Policy `json:"l7policies"` + } + err := (r.(L7PolicyPage)).ExtractInto(&s) + return s.L7Policies, err +} + +// GetResult represents the result of a Get operation. Call its Extract +// method to interpret the result as a L7Policy. +type GetResult struct { + commonResult +} + +// DeleteResult represents the result of a Delete operation. Call its +// ExtractErr method to determine if the request succeeded or failed. +type DeleteResult struct { + gophercloud.ErrResult +} + +// UpdateResult represents the result of an Update operation. Call its Extract +// method to interpret the result as a L7Policy. +type UpdateResult struct { + commonResult +} + +type commonRuleResult struct { + gophercloud.Result +} + +// Extract is a function that accepts a result and extracts a rule. +func (r commonRuleResult) Extract() (*Rule, error) { + var s struct { + Rule *Rule `json:"rule"` + } + err := r.ExtractInto(&s) + return s.Rule, err +} + +// CreateRuleResult represents the result of a CreateRule operation. +// Call its Extract method to interpret it as a Rule. +type CreateRuleResult struct { + commonRuleResult +} + +// RulePage is the page returned by a pager when traversing over a +// collection of Rules in a L7Policy. +type RulePage struct { + pagination.LinkedPageBase +} + +// NextPageURL is invoked when a paginated collection of rules has reached +// the end of a page and the pager seeks to traverse over a new one. In order +// to do this, it needs to construct the next page's URL. +func (r RulePage) NextPageURL() (string, error) { + var s struct { + Links []gophercloud.Link `json:"rules_links"` + } + err := r.ExtractInto(&s) + if err != nil { + return "", err + } + return gophercloud.ExtractNextURL(s.Links) +} + +// IsEmpty checks whether a RulePage struct is empty. +func (r RulePage) IsEmpty() (bool, error) { + is, err := ExtractRules(r) + return len(is) == 0, err +} + +// ExtractRules accepts a Page struct, specifically a RulePage struct, +// and extracts the elements into a slice of Rules structs. In other words, +// a generic collection is mapped into a relevant slice. +func ExtractRules(r pagination.Page) ([]Rule, error) { + var s struct { + Rules []Rule `json:"rules"` + } + err := (r.(RulePage)).ExtractInto(&s) + return s.Rules, err +} + +// GetRuleResult represents the result of a GetRule operation. +// Call its Extract method to interpret it as a Rule. +type GetRuleResult struct { + commonRuleResult +} + +// DeleteRuleResult represents the result of a DeleteRule operation. +// Call its ExtractErr method to determine if the request succeeded or failed. +type DeleteRuleResult struct { + gophercloud.ErrResult +} + +// UpdateRuleResult represents the result of an UpdateRule operation. +// Call its Extract method to interpret it as a Rule. +type UpdateRuleResult struct { + commonRuleResult +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/urls.go new file mode 100644 index 0000000000..ecb607a8e8 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies/urls.go @@ -0,0 +1,25 @@ +package l7policies + +import "github.com/gophercloud/gophercloud" + +const ( + rootPath = "lbaas" + resourcePath = "l7policies" + rulePath = "rules" +) + +func rootURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} + +func ruleRootURL(c *gophercloud.ServiceClient, policyID string) string { + return c.ServiceURL(rootPath, resourcePath, policyID, rulePath) +} + +func ruleResourceURL(c *gophercloud.ServiceClient, policyID string, ruleID string) string { + return c.ServiceURL(rootPath, resourcePath, policyID, rulePath, ruleID) +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/BUILD.bazel b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/BUILD.bazel index 61a779f215..2ebaa085c4 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/BUILD.bazel +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/BUILD.bazel @@ -13,6 +13,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//vendor/github.com/gophercloud/gophercloud:go_default_library", + "//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools:go_default_library", "//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library", ], diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/doc.go index 4ccb967755..eeea6eea82 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/doc.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/doc.go @@ -43,8 +43,11 @@ Example to Update a Listener listenerID := "d67d56a6-4a86-4688-a282-f46444705c64" i1001 := 1001 + i181000 := 181000 updateOpts := listeners.UpdateOpts{ ConnLimit: &i1001, + TimeoutClientData: &i181000, + TimeoutMemberData: &i181000, } listener, err := listeners.Update(networkClient, listenerID, updateOpts).Extract() diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/requests.go index ac587e258d..005bd1e79a 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/requests.go @@ -11,6 +11,8 @@ type Protocol string // Supported attributes for create/update operations. const ( ProtocolTCP Protocol = "TCP" + ProtocolUDP Protocol = "UDP" + ProtocolPROXY Protocol = "PROXY" ProtocolHTTP Protocol = "HTTP" ProtocolHTTPS Protocol = "HTTPS" ) @@ -27,19 +29,21 @@ type ListOptsBuilder interface { // sort by a particular listener attribute. SortDir sets the direction, and is // either `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { - ID string `q:"id"` - Name string `q:"name"` - AdminStateUp *bool `q:"admin_state_up"` - ProjectID string `q:"project_id"` - LoadbalancerID string `q:"loadbalancer_id"` - DefaultPoolID string `q:"default_pool_id"` - Protocol string `q:"protocol"` - ProtocolPort int `q:"protocol_port"` - ConnectionLimit int `q:"connection_limit"` - Limit int `q:"limit"` - Marker string `q:"marker"` - SortKey string `q:"sort_key"` - SortDir string `q:"sort_dir"` + ID string `q:"id"` + Name string `q:"name"` + AdminStateUp *bool `q:"admin_state_up"` + ProjectID string `q:"project_id"` + LoadbalancerID string `q:"loadbalancer_id"` + DefaultPoolID string `q:"default_pool_id"` + Protocol string `q:"protocol"` + ProtocolPort int `q:"protocol_port"` + ConnectionLimit int `q:"connection_limit"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` + TimeoutClientData *int `q:"timeout_client_data"` + TimeoutMemberData *int `q:"timeout_member_data"` } // ToListenerListQuery formats a ListOpts into a query string. @@ -110,6 +114,12 @@ type CreateOpts struct { // The administrative state of the Listener. A valid value is true (UP) // or false (DOWN). AdminStateUp *bool `json:"admin_state_up,omitempty"` + + // Frontend client inactivity timeout in milliseconds + TimeoutClientData *int `json:"timeout_client_data,omitempty"` + + // Backend member inactivity timeout in milliseconds + TimeoutMemberData *int `json:"timeout_member_data,omitempty"` } // ToListenerCreateMap builds a request body from CreateOpts. @@ -149,10 +159,13 @@ type UpdateOptsBuilder interface { // UpdateOpts represents options for updating a Listener. type UpdateOpts struct { // Human-readable name for the Listener. Does not have to be unique. - Name string `json:"name,omitempty"` + Name *string `json:"name,omitempty"` + + // The ID of the default pool with which the Listener is associated. + DefaultPoolID *string `json:"default_pool_id,omitempty"` // Human-readable description for the Listener. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` // The maximum number of connections allowed for the Listener. ConnLimit *int `json:"connection_limit,omitempty"` @@ -166,11 +179,26 @@ type UpdateOpts struct { // The administrative state of the Listener. A valid value is true (UP) // or false (DOWN). AdminStateUp *bool `json:"admin_state_up,omitempty"` + + // Frontend client inactivity timeout in milliseconds + TimeoutClientData *int `json:"timeout_client_data,omitempty"` + + // Backend member inactivity timeout in milliseconds + TimeoutMemberData *int `json:"timeout_member_data,omitempty"` } // ToListenerUpdateMap builds a request body from UpdateOpts. func (opts UpdateOpts) ToListenerUpdateMap() (map[string]interface{}, error) { - return gophercloud.BuildRequestBody(opts, "listener") + b, err := gophercloud.BuildRequestBody(opts, "listener") + if err != nil { + return nil, err + } + + if m := b["listener"].(map[string]interface{}); m["default_pool_id"] == "" { + m["default_pool_id"] = nil + } + + return b, nil } // Update is an operation which modifies the attributes of the specified diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/results.go index c3e7129157..45164b3335 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners/results.go @@ -2,6 +2,7 @@ package listeners import ( "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools" "github.com/gophercloud/gophercloud/pagination" ) @@ -55,9 +56,18 @@ type Listener struct { // Pools are the pools which are part of this listener. Pools []pools.Pool `json:"pools"` + // L7policies are the L7 policies which are part of this listener. + L7Policies []l7policies.L7Policy `json:"l7policies"` + // The provisioning status of the Listener. // This value is ACTIVE, PENDING_* or ERROR. ProvisioningStatus string `json:"provisioning_status"` + + // Frontend client inactivity timeout in milliseconds + TimeoutClientData int `json:"timeout_client_data"` + + // Backend member inactivity timeout in milliseconds + TimeoutMemberData int `json:"timeout_member_data"` } type Stats struct { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/BUILD.bazel b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/BUILD.bazel index f76aa538ff..7e890345b9 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/BUILD.bazel +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/BUILD.bazel @@ -14,6 +14,7 @@ go_library( deps = [ "//vendor/github.com/gophercloud/gophercloud:go_default_library", "//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners:go_default_library", + "//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools:go_default_library", "//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library", ], ) diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/doc.go index 244e19882a..83cc6c44f4 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/doc.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/doc.go @@ -31,6 +31,7 @@ Example to Create a Load Balancer VipAddress: "10.30.176.48", Flavor: "medium", Provider: "haproxy", + Tags: []string{"test", "stage"}, } lb, err := loadbalancers.Create(networkClient, createOpts).Extract() @@ -41,12 +42,10 @@ Example to Create a Load Balancer Example to Update a Load Balancer lbID := "d67d56a6-4a86-4688-a282-f46444705c64" - - i1001 := 1001 + name := "new-name" updateOpts := loadbalancers.UpdateOpts{ - Name: "new-name", + Name: &name, } - lb, err := loadbalancers.Update(networkClient, lbID, updateOpts).Extract() if err != nil { panic(err) @@ -80,5 +79,14 @@ Example to Get the Statistics of a Load Balancer if err != nil { panic(err) } + +Example to Failover a Load Balancers + + lbID := "d67d56a6-4a86-4688-a282-f46444705c64" + + err := loadbalancers.Failover(networkClient, lbID).ExtractErr() + if err != nil { + panic(err) + } */ package loadbalancers diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/requests.go index 99b60fb458..05b0367f69 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/requests.go @@ -17,22 +17,27 @@ type ListOptsBuilder interface { // sort by a particular attribute. SortDir sets the direction, and is // either `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { - Description string `q:"description"` - AdminStateUp *bool `q:"admin_state_up"` - ProjectID string `q:"project_id"` - ProvisioningStatus string `q:"provisioning_status"` - VipAddress string `q:"vip_address"` - VipPortID string `q:"vip_port_id"` - VipSubnetID string `q:"vip_subnet_id"` - ID string `q:"id"` - OperatingStatus string `q:"operating_status"` - Name string `q:"name"` - Flavor string `q:"flavor"` - Provider string `q:"provider"` - Limit int `q:"limit"` - Marker string `q:"marker"` - SortKey string `q:"sort_key"` - SortDir string `q:"sort_dir"` + Description string `q:"description"` + AdminStateUp *bool `q:"admin_state_up"` + ProjectID string `q:"project_id"` + ProvisioningStatus string `q:"provisioning_status"` + VipAddress string `q:"vip_address"` + VipPortID string `q:"vip_port_id"` + VipSubnetID string `q:"vip_subnet_id"` + VipNetworkID string `q:"vip_network_id"` + ID string `q:"id"` + OperatingStatus string `q:"operating_status"` + Name string `q:"name"` + Flavor string `q:"flavor"` + Provider string `q:"provider"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` + Tags []string `q:"tags"` + TagsAny []string `q:"tags-any"` + TagsNot []string `q:"not-tags"` + TagsNotAny []string `q:"not-tags-any"` } // ToLoadBalancerListQuery formats a ListOpts into a query string. @@ -76,11 +81,16 @@ type CreateOpts struct { // Human-readable description for the Loadbalancer. Description string `json:"description,omitempty"` - // The network on which to allocate the Loadbalancer's address. A project can + // The subnet on which to allocate the Loadbalancer's address. A project can // only create Loadbalancers on networks authorized by policy (e.g. networks // that belong to them or networks that are shared). VipSubnetID string `json:"vip_subnet_id" required:"true"` + // The network on which to allocate the Loadbalancer's address. A tenant can + // only create Loadbalancers on networks authorized by policy (e.g. networks + // that belong to them or networks that are shared). + VipNetworkID string `json:"vip_network_id,omitempty"` + // ProjectID is the UUID of the project who owns the Loadbalancer. // Only administrative users can specify a project UUID other than their own. ProjectID string `json:"project_id,omitempty"` @@ -97,6 +107,9 @@ type CreateOpts struct { // The name of the provider. Provider string `json:"provider,omitempty"` + + // Tags is a set of resource tags. + Tags []string `json:"tags,omitempty"` } // ToLoadBalancerCreateMap builds a request body from CreateOpts. @@ -134,14 +147,17 @@ type UpdateOptsBuilder interface { // operation. type UpdateOpts struct { // Human-readable name for the Loadbalancer. Does not have to be unique. - Name string `json:"name,omitempty"` + Name *string `json:"name,omitempty"` // Human-readable description for the Loadbalancer. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` // The administrative state of the Loadbalancer. A valid value is true (UP) // or false (DOWN). AdminStateUp *bool `json:"admin_state_up,omitempty"` + + // Tags is a set of resource tags. + Tags *[]string `json:"tags,omitempty"` } // ToLoadBalancerUpdateMap builds a request body from UpdateOpts. @@ -209,3 +225,11 @@ func GetStats(c *gophercloud.ServiceClient, id string) (r StatsResult) { _, r.Err = c.Get(statisticsRootURL(c, id), &r.Body, nil) return } + +// Failover performs a failover of a load balancer. +func Failover(c *gophercloud.ServiceClient, id string) (r FailoverResult) { + _, r.Err = c.Put(failoverRootURL(c, id), nil, nil, &gophercloud.RequestOpts{ + OkCodes: []int{202}, + }) + return +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/results.go index 69e8a8b701..73372938cf 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/results.go @@ -3,6 +3,7 @@ package loadbalancers import ( "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners" + "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools" "github.com/gophercloud/gophercloud/pagination" ) @@ -34,6 +35,10 @@ type LoadBalancer struct { // Loadbalancer address. VipSubnetID string `json:"vip_subnet_id"` + // The UUID of the network on which to allocate the virtual IP for the + // Loadbalancer address. + VipNetworkID string `json:"vip_network_id"` + // The unique ID for the LoadBalancer. ID string `json:"id"` @@ -51,6 +56,13 @@ type LoadBalancer struct { // Listeners are the listeners related to this Loadbalancer. Listeners []listeners.Listener `json:"listeners"` + + // Pools are the pools related to this Loadbalancer. + Pools []pools.Pool `json:"pools"` + + // Tags is a list of resource tags. Tags are arbitrarily defined strings + // attached to the resource. + Tags []string `json:"tags"` } // StatusTree represents the status of a loadbalancer. @@ -180,3 +192,9 @@ type UpdateResult struct { type DeleteResult struct { gophercloud.ErrResult } + +// FailoverResult represents the result of a failover operation. Call its +// ExtractErr method to determine if the request succeeded or failed. +type FailoverResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/urls.go index 70267c358d..7b184e35f6 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/urls.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers/urls.go @@ -7,6 +7,7 @@ const ( resourcePath = "loadbalancers" statusPath = "status" statisticsPath = "stats" + failoverPath = "failover" ) func rootURL(c *gophercloud.ServiceClient) string { @@ -24,3 +25,7 @@ func statusRootURL(c *gophercloud.ServiceClient, id string) string { func statisticsRootURL(c *gophercloud.ServiceClient, id string) string { return c.ServiceURL(rootPath, resourcePath, id, statisticsPath) } + +func failoverRootURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id, failoverPath) +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go index c173e1c64e..f728f5a823 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go @@ -223,7 +223,7 @@ type UpdateOpts struct { ExpectedCodes string `json:"expected_codes,omitempty"` // The Name of the Monitor. - Name string `json:"name,omitempty"` + Name *string `json:"name,omitempty"` // The administrative state of the Monitor. A valid value is true (UP) // or false (DOWN). diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go index ccf7d98509..2c3a815bae 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go @@ -74,6 +74,9 @@ type Monitor struct { // The provisioning status of the Monitor. // This value is ACTIVE, PENDING_* or ERROR. ProvisioningStatus string `json:"provisioning_status"` + + // The operating status of the monitor. + OperatingStatus string `json:"operating_status"` } // MonitorPage is the page returned by a pager when traversing over a diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/doc.go index 2d57ed4393..d26de312cb 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/doc.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/doc.go @@ -83,12 +83,13 @@ Example to Create a Member poolID := "d67d56a6-4a86-4688-a282-f46444705c64" + weight := 10 createOpts := pools.CreateMemberOpts{ Name: "db", SubnetID: "1981f108-3c48-48d2-b908-30f7d28532c9", Address: "10.0.2.11", ProtocolPort: 80, - Weight: 10, + Weight: &weight, } member, err := pools.CreateMember(networkClient, poolID, createOpts).Extract() @@ -101,9 +102,10 @@ Example to Update a Member poolID := "d67d56a6-4a86-4688-a282-f46444705c64" memberID := "64dba99f-8af8-4200-8882-e32a0660f23e" + weight := 4 updateOpts := pools.UpdateMemberOpts{ Name: "new-name", - Weight: 4, + Weight: &weight, } member, err := pools.UpdateMember(networkClient, poolID, memberID, updateOpts).Extract() @@ -120,5 +122,33 @@ Example to Delete a Member if err != nil { panic(err) } + +Example to Update Members: + + poolID := "d67d56a6-4a86-4688-a282-f46444705c64" + + weight_1 := 20 + member1 := pools.BatchUpdateMemberOpts{ + Address: "192.0.2.16", + ProtocolPort: 80, + Name: "web-server-1", + SubnetID: "bbb35f84-35cc-4b2f-84c2-a6a29bba68aa", + Weight: &weight_1, + } + + weight_2 := 10 + member2 := pools.BatchUpdateMemberOpts{ + Address: "192.0.2.17", + ProtocolPort: 80, + Name: "web-server-2", + Weight: &weight_2, + SubnetID: "bbb35f84-35cc-4b2f-84c2-a6a29bba68aa", + } + members := []pools.BatchUpdateMemberOpts{member1, member2} + + err := pools.BatchUpdateMembers(networkClient, poolID, members).ExtractErr() + if err != nil { + panic(err) + } */ package pools diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go index 538b2f1b2a..fbf16dc288 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go @@ -66,6 +66,8 @@ const ( LBMethodSourceIp LBMethod = "SOURCE_IP" ProtocolTCP Protocol = "TCP" + ProtocolUDP Protocol = "UDP" + ProtocolPROXY Protocol = "PROXY" ProtocolHTTP Protocol = "HTTP" ProtocolHTTPS Protocol = "HTTPS" ) @@ -85,7 +87,7 @@ type CreateOpts struct { LBMethod LBMethod `json:"lb_algorithm" required:"true"` // The protocol used by the pool members, you can use either - // ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS. + // ProtocolTCP, ProtocolUDP, ProtocolPROXY, ProtocolHTTP, or ProtocolHTTPS. Protocol Protocol `json:"protocol" required:"true"` // The Loadbalancer on which the members of the pool will be associated with. @@ -148,10 +150,10 @@ type UpdateOptsBuilder interface { // operation. type UpdateOpts struct { // Name of the pool. - Name string `json:"name,omitempty"` + Name *string `json:"name,omitempty"` // Human-readable description for the pool. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` // The algorithm used to distribute load between the members of the pool. The // current specification supports LBMethodRoundRobin, LBMethodLeastConnections @@ -261,10 +263,10 @@ type CreateMemberOpts struct { ProjectID string `json:"project_id,omitempty"` // A positive integer value that indicates the relative portion of traffic - // that this member should receive from the pool. For example, a member with - // a weight of 10 receives five times as much traffic as a member with a + // that this member should receive from the pool. For example, a member with + // a weight of 10 receives five times as much traffic as a member with a // weight of 2. - Weight int `json:"weight,omitempty"` + Weight *int `json:"weight,omitempty"` // If you omit this parameter, LBaaS uses the vip_subnet_id parameter value // for the subnet UUID. @@ -307,13 +309,13 @@ type UpdateMemberOptsBuilder interface { // operation. type UpdateMemberOpts struct { // Name of the Member. - Name string `json:"name,omitempty"` + Name *string `json:"name,omitempty"` // A positive integer value that indicates the relative portion of traffic // that this member should receive from the pool. For example, a member with // a weight of 10 receives five times as much traffic as a member with a // weight of 2. - Weight int `json:"weight,omitempty"` + Weight *int `json:"weight,omitempty"` // The administrative state of the Pool. A valid value is true (UP) // or false (DOWN). @@ -338,6 +340,36 @@ func UpdateMember(c *gophercloud.ServiceClient, poolID string, memberID string, return } +// BatchUpdateMemberOptsBuilder allows extensions to add additional parameters to the BatchUpdateMembers request. +type BatchUpdateMemberOptsBuilder interface { + ToBatchMemberUpdateMap() (map[string]interface{}, error) +} + +type BatchUpdateMemberOpts CreateMemberOpts + +// ToBatchMemberUpdateMap builds a request body from BatchUpdateMemberOpts. +func (opts BatchUpdateMemberOpts) ToBatchMemberUpdateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "") +} + +// BatchUpdateMembers updates the pool members in batch +func BatchUpdateMembers(c *gophercloud.ServiceClient, poolID string, opts []BatchUpdateMemberOpts) (r UpdateMembersResult) { + var members []map[string]interface{} + for _, opt := range opts { + b, err := opt.ToBatchMemberUpdateMap() + if err != nil { + r.Err = err + return + } + members = append(members, b) + } + + b := map[string]interface{}{"members": members} + + _, r.Err = c.Put(memberRootURL(c, poolID), b, nil, &gophercloud.RequestOpts{OkCodes: []int{202}}) + return +} + // DisassociateMember will remove and disassociate a Member from a particular // Pool. func DeleteMember(c *gophercloud.ServiceClient, poolID string, memberID string) (r DeleteMemberResult) { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/results.go index fe0d93325f..1dc0ed90ac 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/results.go @@ -1,6 +1,9 @@ package pools import ( + "encoding/json" + "time" + "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors" "github.com/gophercloud/gophercloud/pagination" @@ -96,6 +99,9 @@ type Pool struct { // The provisioning status of the pool. // This value is ACTIVE, PENDING_* or ERROR. ProvisioningStatus string `json:"provisioning_status"` + + // The operating status of the pool. + OperatingStatus string `json:"operating_status"` } // PoolPage is the page returned by a pager when traversing over a @@ -204,6 +210,24 @@ type Member struct { // The provisioning status of the pool. // This value is ACTIVE, PENDING_* or ERROR. ProvisioningStatus string `json:"provisioning_status"` + + // DateTime when the member was created + CreatedAt time.Time `json:"-"` + + // DateTime when the member was updated + UpdatedAt time.Time `json:"-"` + + // The operating status of the member + OperatingStatus string `json:"operating_status"` + + // Is the member a backup? Backup members only receive traffic when all non-backup members are down. + Backup bool `json:"backup"` + + // An alternate IP address used for health monitoring a backend member. + MonitorAddress string `json:"monitor_address"` + + // An alternate protocol port used for health monitoring a backend member. + MonitorPort int `json:"monitor_port"` } // MemberPage is the page returned by a pager when traversing over a @@ -247,6 +271,23 @@ type commonMemberResult struct { gophercloud.Result } +func (r *Member) UnmarshalJSON(b []byte) error { + type tmp Member + var s struct { + tmp + CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"` + UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"` + } + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + *r = Member(s.tmp) + r.CreatedAt = time.Time(s.CreatedAt) + r.UpdatedAt = time.Time(s.UpdatedAt) + return nil +} + // ExtractMember is a function that accepts a result and extracts a member. func (r commonMemberResult) Extract() (*Member, error) { var s struct { @@ -274,6 +315,12 @@ type UpdateMemberResult struct { commonMemberResult } +// UpdateMembersResult represents the result of an UpdateMembers operation. +// Call its ExtractErr method to determine if the request succeeded or failed. +type UpdateMembersResult struct { + gophercloud.ErrResult +} + // DeleteMemberResult represents the result of a DeleteMember operation. // Call its ExtractErr method to determine if the request succeeded or failed. type DeleteMemberResult struct { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/doc.go index bf5ec6807c..a71a3ec88a 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/doc.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/doc.go @@ -52,7 +52,7 @@ Example to Disassociate a Floating IP with a Port fipID := "2f245a7b-796b-4f26-9cf9-9e82d248fda7" updateOpts := floatingips.UpdateOpts{ - PortID: nil, + PortID: new(string), } fip, err := floatingips.Update(networkingClient, fipID, updateOpts).Extract() diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go index d82a1bc8e2..b7e6e9189d 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/requests.go @@ -12,6 +12,7 @@ import ( // either `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { ID string `q:"id"` + Description string `q:"description"` FloatingNetworkID string `q:"floating_network_id"` PortID string `q:"port_id"` FixedIP string `q:"fixed_ip_address"` @@ -24,6 +25,10 @@ type ListOpts struct { SortDir string `q:"sort_dir"` RouterID string `q:"router_id"` Status string `q:"status"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` } // List returns a Pager which allows you to iterate over a collection of @@ -50,6 +55,7 @@ type CreateOptsBuilder interface { // resource. The only required fields are FloatingNetworkID and PortID which // refer to the external network and internal port respectively. type CreateOpts struct { + Description string `json:"description,omitempty"` FloatingNetworkID string `json:"floating_network_id" required:"true"` FloatingIP string `json:"floating_ip_address,omitempty"` PortID string `json:"port_id,omitempty"` @@ -116,13 +122,24 @@ type UpdateOptsBuilder interface { // linked to. To associate the floating IP with a new internal port, provide its // ID. To disassociate the floating IP from all ports, provide an empty string. type UpdateOpts struct { - PortID *string `json:"port_id"` + Description *string `json:"description,omitempty"` + PortID *string `json:"port_id,omitempty"` + FixedIP string `json:"fixed_ip_address,omitempty"` } // ToFloatingIPUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder // interface func (opts UpdateOpts) ToFloatingIPUpdateMap() (map[string]interface{}, error) { - return gophercloud.BuildRequestBody(opts, "floatingip") + b, err := gophercloud.BuildRequestBody(opts, "floatingip") + if err != nil { + return nil, err + } + + if m := b["floatingip"].(map[string]interface{}); m["port_id"] == "" { + m["port_id"] = nil + } + + return b, nil } // Update allows floating IP resources to be updated. Currently, the only way to diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go index 8b1a517645..b0b25a9d66 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips/results.go @@ -15,6 +15,9 @@ type FloatingIP struct { // ID is the unique identifier for the floating IP instance. ID string `json:"id"` + // Description for the floating IP instance. + Description string `json:"description"` + // FloatingNetworkID is the UUID of the external network where the floating // IP is to be created. FloatingNetworkID string `json:"floating_network_id"` @@ -42,6 +45,9 @@ type FloatingIP struct { // RouterID is the ID of the router used for this floating IP. RouterID string `json:"router_id"` + + // Tags optionally set via extensions/attributestags + Tags []string `json:"tags"` } type commonResult struct { diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go index 8b2bde530e..cf499f9873 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/requests.go @@ -13,6 +13,7 @@ import ( type ListOpts struct { ID string `q:"id"` Name string `q:"name"` + Description string `q:"description"` AdminStateUp *bool `q:"admin_state_up"` Distributed *bool `q:"distributed"` Status string `q:"status"` @@ -22,6 +23,10 @@ type ListOpts struct { Marker string `q:"marker"` SortKey string `q:"sort_key"` SortDir string `q:"sort_dir"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` } // List returns a Pager which allows you to iterate over a collection of @@ -51,6 +56,7 @@ type CreateOptsBuilder interface { // no required values. type CreateOpts struct { Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` AdminStateUp *bool `json:"admin_state_up,omitempty"` Distributed *bool `json:"distributed,omitempty"` TenantID string `json:"tenant_id,omitempty"` @@ -97,6 +103,7 @@ type UpdateOptsBuilder interface { // UpdateOpts contains the values used when updating a router. type UpdateOpts struct { Name string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` AdminStateUp *bool `json:"admin_state_up,omitempty"` Distributed *bool `json:"distributed,omitempty"` GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go index dffdce8f48..a6fa4a35ea 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers/results.go @@ -16,7 +16,7 @@ type GatewayInfo struct { // ExternalFixedIP is the IP address and subnet ID of the external gateway of a // router. type ExternalFixedIP struct { - IPAddress string `json:"ip_address"` + IPAddress string `json:"ip_address,omitempty"` SubnetID string `json:"subnet_id"` } @@ -51,6 +51,9 @@ type Router struct { // unique. Name string `json:"name"` + // Description for the router. + Description string `json:"description"` + // ID is the unique identifier for the router. ID string `json:"id"` @@ -67,6 +70,9 @@ type Router struct { // Availability zone hints groups network nodes that run services like DHCP, L3, FW, and others. // Used to make network resources highly available. AvailabilityZoneHints []string `json:"availability_zone_hints"` + + // Tags optionally set via extensions/attributestags + Tags []string `json:"tags"` } // RouterPage is the page returned by a pager when traversing over a diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go index 2a46ce6aa0..a22cd306e8 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/requests.go @@ -11,14 +11,19 @@ import ( // sort by a particular network attribute. SortDir sets the direction, and is // either `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { - ID string `q:"id"` - Name string `q:"name"` - TenantID string `q:"tenant_id"` - ProjectID string `q:"project_id"` - Limit int `q:"limit"` - Marker string `q:"marker"` - SortKey string `q:"sort_key"` - SortDir string `q:"sort_dir"` + ID string `q:"id"` + Name string `q:"name"` + Description string `q:"description"` + TenantID string `q:"tenant_id"` + ProjectID string `q:"project_id"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` } // List returns a Pager which allows you to iterate over a collection of @@ -88,7 +93,7 @@ type UpdateOpts struct { Name string `json:"name,omitempty"` // Describes the security group. - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` } // ToSecGroupUpdateMap builds a request body from UpdateOpts. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/results.go index 66915e6e55..468952b3e4 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups/results.go @@ -27,6 +27,9 @@ type SecGroup struct { // ProjectID is the project owner of the security group. ProjectID string `json:"project_id"` + + // Tags optionally set via extensions/attributestags + Tags []string `json:"tags"` } // SecGroupPage is the page returned by a pager when traversing over a diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go index 96cce2817d..c7741ffcd2 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/requests.go @@ -14,6 +14,7 @@ type ListOpts struct { Direction string `q:"direction"` EtherType string `q:"ethertype"` ID string `q:"id"` + Description string `q:"description"` PortRangeMax int `q:"port_range_max"` PortRangeMin int `q:"port_range_min"` Protocol string `q:"protocol"` @@ -88,6 +89,9 @@ type CreateOpts struct { // group rule is applied. Direction RuleDirection `json:"direction" required:"true"` + // String description of each rule, optional + Description string `json:"description,omitempty"` + // Must be "IPv4" or "IPv6", and addresses represented in CIDR must match the // ingress or egress rules. EtherType RuleEtherType `json:"ethertype" required:"true"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/results.go index 377e753140..3bf5501d92 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules/results.go @@ -17,6 +17,9 @@ type SecGroupRule struct { // instance. An egress rule is applied to traffic leaving the instance. Direction string + // Descripton of the rule + Description string `json:"description"` + // Must be IPv4 or IPv6, and addresses represented in CIDR must match the // ingress or egress rules. EtherType string `json:"ethertype"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go index 1fbf62092c..d52d099a67 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/requests.go @@ -19,6 +19,7 @@ type ListOptsBuilder interface { type ListOpts struct { Status string `q:"status"` Name string `q:"name"` + Description string `q:"description"` AdminStateUp *bool `q:"admin_state_up"` TenantID string `q:"tenant_id"` ProjectID string `q:"project_id"` @@ -28,6 +29,10 @@ type ListOpts struct { Limit int `q:"limit"` SortKey string `q:"sort_key"` SortDir string `q:"sort_dir"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` } // ToNetworkListQuery formats a ListOpts into a query string. @@ -69,6 +74,7 @@ type CreateOptsBuilder interface { type CreateOpts struct { AdminStateUp *bool `json:"admin_state_up,omitempty"` Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` Shared *bool `json:"shared,omitempty"` TenantID string `json:"tenant_id,omitempty"` ProjectID string `json:"project_id,omitempty"` @@ -105,9 +111,10 @@ type UpdateOptsBuilder interface { // UpdateOpts represents options used to update a network. type UpdateOpts struct { - AdminStateUp *bool `json:"admin_state_up,omitempty"` - Name string `json:"name,omitempty"` - Shared *bool `json:"shared,omitempty"` + AdminStateUp *bool `json:"admin_state_up,omitempty"` + Name string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Shared *bool `json:"shared,omitempty"` } // ToNetworkUpdateMap builds a request body from UpdateOpts. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go index 62f4b3c3a5..f03067415f 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/networks/results.go @@ -52,6 +52,9 @@ type Network struct { // Human-readable name for the network. Might not be unique. Name string `json:"name"` + // Description for the network + Description string `json:"description"` + // The administrative state of network. If false (down), the network does not // forward packets. AdminStateUp bool `json:"admin_state_up"` @@ -76,6 +79,9 @@ type Network struct { // Availability zone hints groups network nodes that run services like DHCP, L3, FW, and others. // Used to make network resources highly available. AvailabilityZoneHints []string `json:"availability_zone_hints"` + + // Tags optionally set via extensions/attributestags + Tags []string `json:"tags"` } // NetworkPage is the page returned by a pager when traversing over a diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go index 2a5902d75d..f5f7d761ce 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/requests.go @@ -19,6 +19,7 @@ type ListOptsBuilder interface { type ListOpts struct { Status string `q:"status"` Name string `q:"name"` + Description string `q:"description"` AdminStateUp *bool `q:"admin_state_up"` NetworkID string `q:"network_id"` TenantID string `q:"tenant_id"` @@ -31,6 +32,10 @@ type ListOpts struct { Marker string `q:"marker"` SortKey string `q:"sort_key"` SortDir string `q:"sort_dir"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` } // ToPortListQuery formats a ListOpts into a query string. @@ -76,6 +81,7 @@ type CreateOptsBuilder interface { type CreateOpts struct { NetworkID string `json:"network_id" required:"true"` Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` AdminStateUp *bool `json:"admin_state_up,omitempty"` MACAddress string `json:"mac_address,omitempty"` FixedIPs interface{} `json:"fixed_ips,omitempty"` @@ -112,11 +118,12 @@ type UpdateOptsBuilder interface { // UpdateOpts represents the attributes used when updating an existing port. type UpdateOpts struct { - Name string `json:"name,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` AdminStateUp *bool `json:"admin_state_up,omitempty"` FixedIPs interface{} `json:"fixed_ips,omitempty"` - DeviceID string `json:"device_id,omitempty"` - DeviceOwner string `json:"device_owner,omitempty"` + DeviceID *string `json:"device_id,omitempty"` + DeviceOwner *string `json:"device_owner,omitempty"` SecurityGroups *[]string `json:"security_groups,omitempty"` AllowedAddressPairs *[]AddressPair `json:"allowed_address_pairs,omitempty"` } diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go index 66937fd989..3941b62300 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports/results.go @@ -68,6 +68,9 @@ type Port struct { // Human-readable name for the port. Might not be unique. Name string `json:"name"` + // Describes the port. + Description string `json:"description"` + // Administrative state of port. If false (down), port does not forward // packets. AdminStateUp bool `json:"admin_state_up"` @@ -101,6 +104,9 @@ type Port struct { // Identifies the list of IP addresses the port will recognize/accept AllowedAddressPairs []AddressPair `json:"allowed_address_pairs"` + + // Tags optionally set via extensions/attributestags + Tags []string `json:"tags"` } // PortPage is the page returned by a pager when traversing over a collection diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/requests.go index 2597947b18..d2c4a29f7c 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/requests.go @@ -18,6 +18,7 @@ type ListOptsBuilder interface { // `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { Name string `q:"name"` + Description string `q:"description"` EnableDHCP *bool `q:"enable_dhcp"` NetworkID string `q:"network_id"` TenantID string `q:"tenant_id"` @@ -33,6 +34,10 @@ type ListOpts struct { Marker string `q:"marker"` SortKey string `q:"sort_key"` SortDir string `q:"sort_dir"` + Tags string `q:"tags"` + TagsAny string `q:"tags-any"` + NotTags string `q:"not-tags"` + NotTagsAny string `q:"not-tags-any"` } // ToSubnetListQuery formats a ListOpts into a query string. @@ -85,6 +90,9 @@ type CreateOpts struct { // Name is a human-readable name of the subnet. Name string `json:"name,omitempty"` + // Description of the subnet. + Description string `json:"description,omitempty"` + // The UUID of the project who owns the Subnet. Only administrative users // can specify a project UUID other than their own. TenantID string `json:"tenant_id,omitempty"` @@ -123,6 +131,10 @@ type CreateOpts struct { // SubnetPoolID is the id of the subnet pool that subnet should be associated to. SubnetPoolID string `json:"subnetpool_id,omitempty"` + + // Prefixlen is used when user creates a subnet from the subnetpool. It will + // overwrite the "default_prefixlen" value of the referenced subnetpool. + Prefixlen int `json:"prefixlen,omitempty"` } // ToSubnetCreateMap builds a request body from CreateOpts. @@ -163,6 +175,9 @@ type UpdateOpts struct { // Name is a human-readable name of the subnet. Name string `json:"name,omitempty"` + // Description of the subnet. + Description *string `json:"description,omitempty"` + // AllocationPools are IP Address pools that will be available for DHCP. AllocationPools []AllocationPool `json:"allocation_pools,omitempty"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/results.go index 493e5c042e..cf0397019a 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets/results.go @@ -68,6 +68,9 @@ type Subnet struct { // Human-readable name for the subnet. Might not be unique. Name string `json:"name"` + // Description for the subnet. + Description string `json:"description"` + // IP version, either `4' or `6'. IPVersion int `json:"ip_version"` @@ -106,6 +109,9 @@ type Subnet struct { // SubnetPoolID is the id of the subnet pool associated with the subnet. SubnetPoolID string `json:"subnetpool_id"` + + // Tags optionally set via extensions/attributestags + Tags []string `json:"tags"` } // SubnetPage is the page returned by a pager when traversing over a collection diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/requests.go index 4799204e70..89aa996839 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/requests.go @@ -74,6 +74,7 @@ type CreateOpts struct { DetectContentType bool `h:"X-Detect-Content-Type"` IfNoneMatch string `h:"If-None-Match"` VersionsLocation string `h:"X-Versions-Location"` + HistoryLocation string `h:"X-History-Location"` } // ToContainerCreateMap formats a CreateOpts into a map of headers. @@ -137,6 +138,8 @@ type UpdateOpts struct { DetectContentType bool `h:"X-Detect-Content-Type"` RemoveVersionsLocation string `h:"X-Remove-Versions-Location"` VersionsLocation string `h:"X-Versions-Location"` + RemoveHistoryLocation string `h:"X-Remove-History-Location"` + HistoryLocation string `h:"X-History-Location"` } // ToContainerUpdateMap formats a UpdateOpts into a map of headers. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go index e8c78880a4..cce2190ff9 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers/results.go @@ -100,6 +100,7 @@ type GetHeader struct { Read []string `json:"-"` TransID string `json:"X-Trans-Id"` VersionsLocation string `json:"X-Versions-Location"` + HistoryLocation string `json:"X-History-Location"` Write []string `json:"-"` StoragePolicy string `json:"X-Storage-Policy"` } diff --git a/vendor/github.com/gophercloud/gophercloud/params.go b/vendor/github.com/gophercloud/gophercloud/params.go index 19b8cf7bf8..b9986660cb 100644 --- a/vendor/github.com/gophercloud/gophercloud/params.go +++ b/vendor/github.com/gophercloud/gophercloud/params.go @@ -120,6 +120,22 @@ func BuildRequestBody(opts interface{}, parent string) (map[string]interface{}, continue } + if v.Kind() == reflect.Slice || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Slice) { + sliceValue := v + if sliceValue.Kind() == reflect.Ptr { + sliceValue = sliceValue.Elem() + } + + for i := 0; i < sliceValue.Len(); i++ { + element := sliceValue.Index(i) + if element.Kind() == reflect.Struct || (element.Kind() == reflect.Ptr && element.Elem().Kind() == reflect.Struct) { + _, err := BuildRequestBody(element.Interface(), "") + if err != nil { + return nil, err + } + } + } + } if v.Kind() == reflect.Struct || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct) { if zero { //fmt.Printf("value before change: %+v\n", optsValue.Field(i)) diff --git a/vendor/github.com/gophercloud/gophercloud/provider_client.go b/vendor/github.com/gophercloud/gophercloud/provider_client.go index 95fa11a788..365b4cbcdf 100644 --- a/vendor/github.com/gophercloud/gophercloud/provider_client.go +++ b/vendor/github.com/gophercloud/gophercloud/provider_client.go @@ -3,6 +3,7 @@ package gophercloud import ( "bytes" "encoding/json" + "errors" "io" "io/ioutil" "net/http" @@ -71,26 +72,36 @@ type ProviderClient struct { // authentication functions for different Identity service versions. ReauthFunc func() error + // Throwaway determines whether if this client is a throw-away client. It's a copy of user's provider client + // with the token and reauth func zeroed. Such client can be used to perform reauthorization. + Throwaway bool + mut *sync.RWMutex reauthmut *reauthlock + + authResult AuthResult } type reauthlock struct { sync.RWMutex - reauthing bool + reauthing bool + reauthingErr error + done *sync.Cond } // AuthenticatedHeaders returns a map of HTTP headers that are common for all -// authenticated service requests. +// authenticated service requests. Blocks if Reauthenticate is in progress. func (client *ProviderClient) AuthenticatedHeaders() (m map[string]string) { + if client.IsThrowaway() { + return + } if client.reauthmut != nil { - client.reauthmut.RLock() - if client.reauthmut.reauthing { - client.reauthmut.RUnlock() - return + client.reauthmut.Lock() + for client.reauthmut.reauthing { + client.reauthmut.done.Wait() } - client.reauthmut.RUnlock() + client.reauthmut.Unlock() } t := client.Token() if t == "" { @@ -106,6 +117,20 @@ func (client *ProviderClient) UseTokenLock() { client.reauthmut = new(reauthlock) } +// GetAuthResult returns the result from the request that was used to obtain a +// provider client's Keystone token. +// +// The result is nil when authentication has not yet taken place, when the token +// was set manually with SetToken(), or when a ReauthFunc was used that does not +// record the AuthResult. +func (client *ProviderClient) GetAuthResult() AuthResult { + if client.mut != nil { + client.mut.RLock() + defer client.mut.RUnlock() + } + return client.authResult +} + // Token safely reads the value of the auth token from the ProviderClient. Applications should // call this method to access the token instead of the TokenID field func (client *ProviderClient) Token() string { @@ -117,20 +142,78 @@ func (client *ProviderClient) Token() string { } // SetToken safely sets the value of the auth token in the ProviderClient. Applications may -// use this method in a custom ReauthFunc +// use this method in a custom ReauthFunc. +// +// WARNING: This function is deprecated. Use SetTokenAndAuthResult() instead. func (client *ProviderClient) SetToken(t string) { if client.mut != nil { client.mut.Lock() defer client.mut.Unlock() } client.TokenID = t + client.authResult = nil } -//Reauthenticate calls client.ReauthFunc in a thread-safe way. If this is -//called because of a 401 response, the caller may pass the previous token. In -//this case, the reauthentication can be skipped if another thread has already -//reauthenticated in the meantime. If no previous token is known, an empty -//string should be passed instead to force unconditional reauthentication. +// SetTokenAndAuthResult safely sets the value of the auth token in the +// ProviderClient and also records the AuthResult that was returned from the +// token creation request. Applications may call this in a custom ReauthFunc. +func (client *ProviderClient) SetTokenAndAuthResult(r AuthResult) error { + tokenID := "" + var err error + if r != nil { + tokenID, err = r.ExtractTokenID() + if err != nil { + return err + } + } + + if client.mut != nil { + client.mut.Lock() + defer client.mut.Unlock() + } + client.TokenID = tokenID + client.authResult = r + return nil +} + +// CopyTokenFrom safely copies the token from another ProviderClient into the +// this one. +func (client *ProviderClient) CopyTokenFrom(other *ProviderClient) { + if client.mut != nil { + client.mut.Lock() + defer client.mut.Unlock() + } + if other.mut != nil && other.mut != client.mut { + other.mut.RLock() + defer other.mut.RUnlock() + } + client.TokenID = other.TokenID + client.authResult = other.authResult +} + +// IsThrowaway safely reads the value of the client Throwaway field. +func (client *ProviderClient) IsThrowaway() bool { + if client.reauthmut != nil { + client.reauthmut.RLock() + defer client.reauthmut.RUnlock() + } + return client.Throwaway +} + +// SetThrowaway safely sets the value of the client Throwaway field. +func (client *ProviderClient) SetThrowaway(v bool) { + if client.reauthmut != nil { + client.reauthmut.Lock() + defer client.reauthmut.Unlock() + } + client.Throwaway = v +} + +// Reauthenticate calls client.ReauthFunc in a thread-safe way. If this is +// called because of a 401 response, the caller may pass the previous token. In +// this case, the reauthentication can be skipped if another thread has already +// reauthenticated in the meantime. If no previous token is known, an empty +// string should be passed instead to force unconditional reauthentication. func (client *ProviderClient) Reauthenticate(previousToken string) (err error) { if client.ReauthFunc == nil { return nil @@ -139,11 +222,25 @@ func (client *ProviderClient) Reauthenticate(previousToken string) (err error) { if client.mut == nil { return client.ReauthFunc() } + + client.reauthmut.Lock() + if client.reauthmut.reauthing { + for !client.reauthmut.reauthing { + client.reauthmut.done.Wait() + } + err = client.reauthmut.reauthingErr + client.reauthmut.Unlock() + return err + } + client.reauthmut.Unlock() + client.mut.Lock() defer client.mut.Unlock() client.reauthmut.Lock() client.reauthmut.reauthing = true + client.reauthmut.done = sync.NewCond(client.reauthmut) + client.reauthmut.reauthingErr = nil client.reauthmut.Unlock() if previousToken == "" || client.TokenID == previousToken { @@ -152,6 +249,8 @@ func (client *ProviderClient) Reauthenticate(previousToken string) (err error) { client.reauthmut.Lock() client.reauthmut.reauthing = false + client.reauthmut.reauthingErr = err + client.reauthmut.done.Broadcast() client.reauthmut.Unlock() return } @@ -192,7 +291,7 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts) // io.ReadSeeker as-is. Default the content-type to application/json. if options.JSONBody != nil { if options.RawBody != nil { - panic("Please provide only one of JSONBody or RawBody to gophercloud.Request().") + return nil, errors.New("please provide only one of JSONBody or RawBody to gophercloud.Request()") } rendered, err := json.Marshal(options.JSONBody) @@ -251,13 +350,14 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts) } // Allow default OkCodes if none explicitly set - if options.OkCodes == nil { - options.OkCodes = defaultOkCodes(method) + okc := options.OkCodes + if okc == nil { + okc = defaultOkCodes(method) } // Validate the HTTP response status. var ok bool - for _, code := range options.OkCodes { + for _, code := range okc { if resp.StatusCode == code { ok = true break @@ -295,11 +395,7 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts) seeker.Seek(0, 0) } } - // make a new call to request with a nil reauth func in order to avoid infinite loop - reauthFunc := client.ReauthFunc - client.ReauthFunc = nil resp, err = client.Request(method, url, options) - client.ReauthFunc = reauthFunc if err != nil { switch err.(type) { case *ErrUnexpectedResponseCode: diff --git a/vendor/github.com/gophercloud/gophercloud/results.go b/vendor/github.com/gophercloud/gophercloud/results.go index 30d3b15599..94a16bff0b 100644 --- a/vendor/github.com/gophercloud/gophercloud/results.go +++ b/vendor/github.com/gophercloud/gophercloud/results.go @@ -90,38 +90,40 @@ func (r Result) extractIntoPtr(to interface{}, label string) error { if typeOfV.NumField() > 0 && typeOfV.Field(0).Anonymous { newSlice := reflect.MakeSlice(reflect.SliceOf(typeOfV), 0, 0) - for _, v := range m[label].([]interface{}) { - // For each iteration of the slice, we create a new struct. - // This is to work around a bug where elements of a slice - // are reused and not overwritten when the same copy of the - // struct is used: - // - // https://github.com/golang/go/issues/21092 - // https://github.com/golang/go/issues/24155 - // https://play.golang.org/p/NHo3ywlPZli - newType := reflect.New(typeOfV).Elem() + if mSlice, ok := m[label].([]interface{}); ok { + for _, v := range mSlice { + // For each iteration of the slice, we create a new struct. + // This is to work around a bug where elements of a slice + // are reused and not overwritten when the same copy of the + // struct is used: + // + // https://github.com/golang/go/issues/21092 + // https://github.com/golang/go/issues/24155 + // https://play.golang.org/p/NHo3ywlPZli + newType := reflect.New(typeOfV).Elem() - b, err := json.Marshal(v) - if err != nil { - return err - } - - // This is needed for structs with an UnmarshalJSON method. - // Technically this is just unmarshalling the response into - // a struct that is never used, but it's good enough to - // trigger the UnmarshalJSON method. - for i := 0; i < newType.NumField(); i++ { - s := newType.Field(i).Addr().Interface() - - // Unmarshal is used rather than NewDecoder to also work - // around the above-mentioned bug. - err = json.Unmarshal(b, s) + b, err := json.Marshal(v) if err != nil { return err } - } - newSlice = reflect.Append(newSlice, newType) + // This is needed for structs with an UnmarshalJSON method. + // Technically this is just unmarshalling the response into + // a struct that is never used, but it's good enough to + // trigger the UnmarshalJSON method. + for i := 0; i < newType.NumField(); i++ { + s := newType.Field(i).Addr().Interface() + + // Unmarshal is used rather than NewDecoder to also work + // around the above-mentioned bug. + err = json.Unmarshal(b, s) + if err != nil { + return err + } + } + + newSlice = reflect.Append(newSlice, newType) + } } // "to" should now be properly modeled to receive the diff --git a/vendor/github.com/gophercloud/gophercloud/service_client.go b/vendor/github.com/gophercloud/gophercloud/service_client.go index 2734510e1b..c889201f95 100644 --- a/vendor/github.com/gophercloud/gophercloud/service_client.go +++ b/vendor/github.com/gophercloud/gophercloud/service_client.go @@ -129,6 +129,8 @@ func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) { opts.MoreHeaders["X-OpenStack-Manila-API-Version"] = client.Microversion case "volume": opts.MoreHeaders["X-OpenStack-Volume-API-Version"] = client.Microversion + case "baremetal": + opts.MoreHeaders["X-OpenStack-Ironic-API-Version"] = client.Microversion } if client.Type != "" {