diff --git a/go.mod b/go.mod index 5e3e71a5..e2a1ec94 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module github.com/sapcc/backup-tools go 1.22 require ( - github.com/gophercloud/gophercloud v1.9.0 + github.com/gophercloud/gophercloud v1.10.0 github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 github.com/gorilla/mux v1.8.1 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/majewsky/schwift v1.3.0 - github.com/prometheus/client_golang v1.18.0 + github.com/prometheus/client_golang v1.19.0 github.com/sapcc/go-api-declarations v1.10.9 - github.com/sapcc/go-bits v0.0.0-20240222221204-90b493ffdee9 + github.com/sapcc/go-bits v0.0.0-20240229224940-f0612298e3a6 go.uber.org/automaxprocs v1.5.3 ) @@ -22,7 +22,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.47.0 // indirect + github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect diff --git a/go.sum b/go.sum index 95dcb4ec..3c662e7a 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= -github.com/gophercloud/gophercloud v1.9.0 h1:zKvmHOmHuaZlnx9d2DJpEgbMxrGt/+CJ/bKOKQh9Xzo= -github.com/gophercloud/gophercloud v1.9.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/gophercloud/gophercloud v1.10.0 h1:watRMsaMDlSLuLkpLeLSQ87yvcuwIajNg6A5uLcjoIU= +github.com/gophercloud/gophercloud v1.10.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE= github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -32,20 +32,20 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= -github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sapcc/go-api-declarations v1.10.9 h1:k+F3W0FTyYLazII4hdFaWLJ7L+MQRcFBD9I9P/hUNBs= github.com/sapcc/go-api-declarations v1.10.9/go.mod h1:83R3hTANhuRXt/pXDby37IJetw8l7DG41s33Tp9NXxI= -github.com/sapcc/go-bits v0.0.0-20240222221204-90b493ffdee9 h1:rbg802tNP3trhxlzQCAQHHnd1UAfjiSB9UR7JqdRxTU= -github.com/sapcc/go-bits v0.0.0-20240222221204-90b493ffdee9/go.mod h1:w+u3Y/Dt7/1F/Km1skkratCVrexj5o0zes1Ds7aJFhE= +github.com/sapcc/go-bits v0.0.0-20240229224940-f0612298e3a6 h1:Re/4mMH3pQwFD9i9ujArSA/HIIpEGmfIoda9tmtYLpY= +github.com/sapcc/go-bits v0.0.0-20240229224940-f0612298e3a6/go.mod h1:F26a4iH+yHhpQxn+jCe8gQvtr7KdMnkyqLLVoNNgFt8= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= diff --git a/vendor/github.com/gophercloud/gophercloud/CHANGELOG.md b/vendor/github.com/gophercloud/gophercloud/CHANGELOG.md index e10078ad..3d99d01f 100644 --- a/vendor/github.com/gophercloud/gophercloud/CHANGELOG.md +++ b/vendor/github.com/gophercloud/gophercloud/CHANGELOG.md @@ -1,3 +1,13 @@ +## v1.10.0 (2024-02-27) + +* [GH-2893](https://github.com/gophercloud/gophercloud/pull/2893) [v1] authentication: Add WithContext functions +* [GH-2894](https://github.com/gophercloud/gophercloud/pull/2894) [v1] pager: Add WithContext functions +* [GH-2899](https://github.com/gophercloud/gophercloud/pull/2899) [v1] Authenticate with a clouds.yaml +* [GH-2917](https://github.com/gophercloud/gophercloud/pull/2917) [v1] Add ParseOption type to made clouds.Parse() more usable for optional With* funcs +* [GH-2924](https://github.com/gophercloud/gophercloud/pull/2924) [v1] build(deps): bump EmilienM/devstack-action from 0.11 to 0.14 +* [GH-2933](https://github.com/gophercloud/gophercloud/pull/2933) [v1] Fix AllowReauth reauthentication +* [GH-2950](https://github.com/gophercloud/gophercloud/pull/2950) [v1] compute: Use volumeID, not attachmentID for volume attachments + ## v1.9.0 (2024-02-02) New features and improvements: diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/client.go b/vendor/github.com/gophercloud/gophercloud/openstack/client.go index 81c907c3..acaa02be 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/client.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/client.go @@ -1,6 +1,7 @@ package openstack import ( + "context" "fmt" "reflect" "strings" @@ -23,20 +24,18 @@ const ( v3 = "v3" ) -/* -NewClient prepares an unauthenticated ProviderClient instance. -Most users will probably prefer using the AuthenticatedClient function -instead. - -This is useful if you wish to explicitly control the version of the identity -service that's used for authentication explicitly, for example. - -A basic example of using this would be: - - ao, err := openstack.AuthOptionsFromEnv() - provider, err := openstack.NewClient(ao.IdentityEndpoint) - client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{}) -*/ +// NewClient prepares an unauthenticated ProviderClient instance. +// Most users will probably prefer using the AuthenticatedClient function +// instead. +// +// This is useful if you wish to explicitly control the version of the identity +// service that's used for authentication explicitly, for example. +// +// A basic example of using this would be: +// +// ao, err := openstack.AuthOptionsFromEnv() +// provider, err := openstack.NewClient(ao.IdentityEndpoint) +// client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{}) func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { base, err := utils.BaseEndpoint(endpoint) if err != nil { @@ -54,42 +53,45 @@ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { return p, nil } -/* -AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint -specified by the options, acquires a token, and returns a Provider Client -instance that's ready to operate. - -If the full path to a versioned identity endpoint was specified (example: -http://example.com:5000/v3), that path will be used as the endpoint to query. - -If a versionless endpoint was specified (example: http://example.com:5000/), -the endpoint will be queried to determine which versions of the identity service -are available, then chooses the most recent or most supported version. - -Example: - - ao, err := openstack.AuthOptionsFromEnv() - provider, err := openstack.AuthenticatedClient(ao) - client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ - Region: os.Getenv("OS_REGION_NAME"), - }) -*/ -func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { +// AuthenticatedClientWithContext logs in to an OpenStack cloud found at the identity endpoint +// specified by the options, acquires a token, and returns a Provider Client +// instance that's ready to operate. +// +// If the full path to a versioned identity endpoint was specified (example: +// http://example.com:5000/v3), that path will be used as the endpoint to query. +// +// If a versionless endpoint was specified (example: http://example.com:5000/), +// the endpoint will be queried to determine which versions of the identity service +// are available, then chooses the most recent or most supported version. +// +// Example: +// +// ao, err := openstack.AuthOptionsFromEnv() +// provider, err := openstack.AuthenticatedClientWithContext(ctx, ao) +// client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ +// Region: os.Getenv("OS_REGION_NAME"), +// }) +func AuthenticatedClientWithContext(ctx context.Context, options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { client, err := NewClient(options.IdentityEndpoint) if err != nil { return nil, err } - err = Authenticate(client, options) + err = AuthenticateWithContext(ctx, client, options) if err != nil { return nil, err } return client, nil } -// Authenticate or re-authenticate against the most recent identity service -// supported at the provided endpoint. -func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { +// AuthenticatedClient is a compatibility wrapper around AuthenticatedClientWithContext +func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) { + return AuthenticatedClientWithContext(context.Background(), options) +} + +// AuthenticateWithContext authenticates or re-authenticates against the most +// recent identity service supported at the provided endpoint. +func AuthenticateWithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { versions := []*utils.Version{ {ID: v2, Priority: 20, Suffix: "/v2.0/"}, {ID: v3, Priority: 30, Suffix: "/v3/"}, @@ -102,21 +104,31 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp switch chosen.ID { case v2: - return v2auth(client, endpoint, options, gophercloud.EndpointOpts{}) + return v2auth(ctx, client, endpoint, options, gophercloud.EndpointOpts{}) case v3: - return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{}) + return v3auth(ctx, client, endpoint, &options, gophercloud.EndpointOpts{}) default: // The switch statement must be out of date from the versions list. return fmt.Errorf("Unrecognized identity version: %s", chosen.ID) } } -// AuthenticateV2 explicitly authenticates against the identity v2 endpoint. +// Authenticate is a compatibility wrapper around AuthenticateWithContext. +func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error { + return AuthenticateWithContext(context.Background(), client, options) +} + +// AuthenticateV2WithContext explicitly authenticates against the identity v2 endpoint. +func AuthenticateV2WithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { + return v2auth(ctx, client, "", options, eo) +} + +// AuthenticateV2 is a compatibility wrapper around AuthenticateV2WithContext. func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { - return v2auth(client, "", options, eo) + return AuthenticateV2WithContext(context.Background(), client, options, eo) } -func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { +func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { v2Client, err := NewIdentityV2(client, eo) if err != nil { return err @@ -136,7 +148,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc TokenID: options.TokenID, } - result := tokens2.Create(v2Client, v2Opts) + result := tokens2.CreateWithContext(ctx, v2Client, v2Opts) err = client.SetTokenAndAuthResult(result) if err != nil { @@ -159,7 +171,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc tao := options tao.AllowReauth = false client.ReauthFunc = func() error { - err := v2auth(&tac, endpoint, tao, eo) + err := v2auth(context.Background(), &tac, endpoint, tao, eo) if err != nil { return err } @@ -174,12 +186,17 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc return nil } -// AuthenticateV3 explicitly authenticates against the identity v3 service. +// AuthenticateV3WithContext explicitly authenticates against the identity v3 service. +func AuthenticateV3WithContext(ctx context.Context, client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { + return v3auth(ctx, client, "", options, eo) +} + +// AuthenticateV3 is a compatibility wrapper around AuthenticateV3WithContext func AuthenticateV3(client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { - return v3auth(client, "", options, eo) + return AuthenticateV3WithContext(context.Background(), client, options, eo) } -func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { +func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { // Override the generated service endpoint with the one returned by the version endpoint. v3Client, err := NewIdentityV3(client, eo) if err != nil { @@ -229,11 +246,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au var result tokens3.CreateResult switch opts.(type) { case *ec2tokens.AuthOptions: - result = ec2tokens.Create(v3Client, opts) + result = ec2tokens.CreateWithContext(ctx, v3Client, opts) case *oauth1.AuthOptions: - result = oauth1.Create(v3Client, opts) + result = oauth1.CreateWithContext(ctx, v3Client, opts) default: - result = tokens3.Create(v3Client, opts) + result = tokens3.CreateWithContext(ctx, v3Client, opts) } err = client.SetTokenAndAuthResult(result) @@ -277,7 +294,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au tao = opts } client.ReauthFunc = func() error { - err := v3auth(&tac, endpoint, tao, eo) + err := v3auth(context.Background(), &tac, endpoint, tao, eo) if err != nil { return err } diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go index 84f16c3f..67c04fce 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v2/tokens/requests.go @@ -1,6 +1,10 @@ package tokens -import "github.com/gophercloud/gophercloud" +import ( + "context" + + "github.com/gophercloud/gophercloud" +) // PasswordCredentialsV2 represents the required options to authenticate // with a username and password. @@ -77,17 +81,17 @@ func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) { return b, nil } -// Create authenticates to the identity service and attempts to acquire a Token. +// CreateWithContext authenticates to the identity service and attempts to acquire a Token. // Generally, rather than interact with this call directly, end users should // call openstack.AuthenticatedClient(), which abstracts all of the gory details // about navigating service catalogs and such. -func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { +func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { b, err := auth.ToTokenV2CreateMap() if err != nil { r.Err = err return } - resp, err := client.Post(CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 203}, OmitHeaders: []string{"X-Auth-Token"}, }) @@ -95,11 +99,21 @@ func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r Creat return } -// Get validates and retrieves information for user's token. -func Get(client *gophercloud.ServiceClient, token string) (r GetResult) { +// Create is a compatibility wrapper around CreateWithContext +func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) { + return CreateWithContext(context.Background(), client, auth) +} + +// GetWithContext validates and retrieves information for user's token. +func GetWithContext(ctx context.Context, client *gophercloud.ServiceClient, token string) (r GetResult) { resp, err := client.Get(GetURL(client, token), &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 203}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// Get is a compatibility wrapper around GetWithContext +func Get(client *gophercloud.ServiceClient, token string) (r GetResult) { + return GetWithContext(context.Background(), client, token) +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2tokens/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2tokens/requests.go index 32ba0e62..b5b5350c 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2tokens/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/ec2tokens/requests.go @@ -1,6 +1,7 @@ package ec2tokens import ( + "context" "crypto/hmac" "crypto/sha1" "crypto/sha256" @@ -287,8 +288,8 @@ func (opts *AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string] return b, nil } -// Create authenticates and either generates a new token from EC2 credentials -func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// CreateWithContext authenticates and either generates a new token from EC2 credentials +func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -298,7 +299,7 @@ func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tok // delete "token" element, since it is used in s3tokens deleteBodyElements(b, "token") - resp, err := c.Post(ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.PostWithContext(ctx, ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: map[string]string{"X-Auth-Token": ""}, OkCodes: []int{200}, }) @@ -306,9 +307,15 @@ func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tok return } -// ValidateS3Token authenticates an S3 request using EC2 credentials. Doesn't -// generate a new token ID, but returns a tokens.CreateResult. -func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// Create is a compatibility wrapper around CreateWithContext +func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { + return CreateWithContext(context.Background(), c, opts) +} + +// ValidateS3TokenWithContext authenticates an S3 request using EC2 +// credentials. Doesn't generate a new token ID, but returns a +// tokens.CreateResult. +func ValidateS3TokenWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -318,7 +325,7 @@ func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilde // delete unused element, since it is used in ec2tokens only deleteBodyElements(b, "body_hash", "headers", "host", "params", "path", "verb") - resp, err := c.Post(s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.PostWithContext(ctx, s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: map[string]string{"X-Auth-Token": ""}, OkCodes: []int{200}, }) @@ -326,6 +333,11 @@ func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilde return } +// ValidateS3Token is a compatibility wrapper around ValidateS3TokenWithContext +func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { + return ValidateS3TokenWithContext(context.Background(), c, opts) +} + // The following are small helper functions used to help build the signature. // sumHMAC1 is a func to implement the HMAC SHA1 signature method. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/oauth1/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/oauth1/requests.go index 028b5a45..99210563 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/oauth1/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/oauth1/requests.go @@ -1,6 +1,7 @@ package oauth1 import ( + "context" "crypto/hmac" "crypto/sha1" "encoding/base64" @@ -133,9 +134,9 @@ func (opts AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string]i return gophercloud.BuildRequestBody(req, "") } -// Create authenticates and either generates a new OpenStack token from an -// OAuth1 token. -func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { +// CreateWithContext authenticates and either generates a new OpenStack token +// from an OAuth1 token. +func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { b, err := opts.ToTokenV3CreateMap(nil) if err != nil { r.Err = err @@ -153,7 +154,7 @@ func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) ( return } - resp, err := client.Post(authURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, authURL(client), b, &r.Body, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, }) @@ -161,6 +162,11 @@ func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) ( return } +// Create is a compatibility wrapper around CreateWithContext. +func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) { + return CreateWithContext(context.Background(), client, opts) +} + // CreateConsumerOptsBuilder allows extensions to add additional parameters to // the CreateConsumer request. type CreateConsumerOptsBuilder interface { @@ -178,27 +184,37 @@ func (opts CreateConsumerOpts) ToOAuth1CreateConsumerMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "consumer") } -// Create creates a new Consumer. -func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { +// CreateConsumerWithContext creates a new Consumer. +func CreateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { b, err := opts.ToOAuth1CreateConsumerMap() if err != nil { r.Err = err return } - resp, err := client.Post(consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{201}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// Delete deletes a Consumer. -func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { - resp, err := client.Delete(consumerURL(client, id), nil) +// CreateConsumer is a compatibility wrapper around CreateConsumerWithContext. +func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) { + return CreateConsumerWithContext(context.Background(), client, opts) +} + +// DeleteConsumerWithContext deletes a Consumer. +func DeleteConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { + resp, err := client.DeleteWithContext(ctx, consumerURL(client, id), nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// DeleteConsumer is a compatibility wrapper around DeleteConsumerWithContext. +func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) { + return DeleteConsumerWithContext(context.Background(), client, id) +} + // List enumerates Consumers. func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager { return pagination.NewPager(client, consumersURL(client), func(r pagination.PageResult) pagination.Page { @@ -206,13 +222,18 @@ func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager { }) } -// GetConsumer retrieves details on a single Consumer by ID. -func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { - resp, err := client.Get(consumerURL(client, id), &r.Body, nil) +// GetConsumerWithContext retrieves details on a single Consumer by ID. +func GetConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { + resp, err := client.GetWithContext(ctx, consumerURL(client, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// GetConsumer is a compatibility wrapper around GetConsumerWithContext. +func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) { + return GetConsumerWithContext(context.Background(), client, id) +} + // UpdateConsumerOpts provides options used to update a consumer. type UpdateConsumerOpts struct { // Description is the consumer description. @@ -225,20 +246,25 @@ func (opts UpdateConsumerOpts) ToOAuth1UpdateConsumerMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "consumer") } -// UpdateConsumer updates an existing Consumer. -func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { +// UpdateConsumerWithContext updates an existing Consumer. +func UpdateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { b, err := opts.ToOAuth1UpdateConsumerMap() if err != nil { r.Err = err return } - resp, err := client.Patch(consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PatchWithContext(ctx, consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// UpdateConsumer is a compatibility wrapper around UpdateConsumerWithContext. +func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) { + return UpdateConsumerWithContext(context.Background(), client, id, opts) +} + // RequestTokenOptsBuilder allows extensions to add additional parameters to the // RequestToken request. type RequestTokenOptsBuilder interface { @@ -297,15 +323,15 @@ func (opts RequestTokenOpts) ToOAuth1RequestTokenHeaders(method, u string) (map[ return h, nil } -// RequestToken requests an unauthorized OAuth1 Token. -func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { +// RequestTokenWithContext requests an unauthorized OAuth1 Token. +func RequestTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { h, err := opts.ToOAuth1RequestTokenHeaders("POST", requestTokenURL(client)) if err != nil { r.Err = err return } - resp, err := client.Post(requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, KeepResponseBody: true, @@ -323,6 +349,11 @@ func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilde return } +// RequestToken is a compatibility wrapper around RequestTokenWithContext. +func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) { + return RequestTokenWithContext(context.Background(), client, opts) +} + // AuthorizeTokenOptsBuilder allows extensions to add additional parameters to // the AuthorizeToken request. type AuthorizeTokenOptsBuilder interface { @@ -351,20 +382,25 @@ func (opts AuthorizeTokenOpts) ToOAuth1AuthorizeTokenMap() (map[string]interface return gophercloud.BuildRequestBody(opts, "") } -// AuthorizeToken authorizes an unauthorized consumer token. -func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { +// AuthorizeTokenWithContext authorizes an unauthorized consumer token. +func AuthorizeTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { b, err := opts.ToOAuth1AuthorizeTokenMap() if err != nil { r.Err = err return } - resp, err := client.Put(authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := client.PutWithContext(ctx, authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// AuthorizeToken is a compatibility wrapper around AuthorizeTokenWithContext. +func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) { + return AuthorizeTokenWithContext(context.Background(), client, id, opts) +} + // CreateAccessTokenOptsBuilder allows extensions to add additional parameters // to the CreateAccessToken request. type CreateAccessTokenOptsBuilder interface { @@ -425,15 +461,15 @@ func (opts CreateAccessTokenOpts) ToOAuth1CreateAccessTokenHeaders(method, u str return headers, nil } -// CreateAccessToken creates a new OAuth1 Access Token -func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { +// CreateAccessTokenWithContext creates a new OAuth1 Access Token +func CreateAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { h, err := opts.ToOAuth1CreateAccessTokenHeaders("POST", createAccessTokenURL(client)) if err != nil { r.Err = err return } - resp, err := client.Post(createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{ + resp, err := client.PostWithContext(ctx, createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{201}, KeepResponseBody: true, @@ -451,20 +487,35 @@ func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessToken return } -// GetAccessToken retrieves details on a single OAuth1 access token by an ID. -func GetAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { - resp, err := client.Get(userAccessTokenURL(client, userID, id), &r.Body, nil) +// CreateAccessToken is a compatibility wrapper around CreateAccessTokenWithContext. +func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) { + return CreateAccessTokenWithContext(context.Background(), client, opts) +} + +// GetAccessTokenWithContext retrieves details on a single OAuth1 access token by an ID. +func GetAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { + resp, err := client.GetWithContext(ctx, userAccessTokenURL(client, userID, id), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// RevokeAccessToken revokes an OAuth1 access token. -func RevokeAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { - resp, err := client.Delete(userAccessTokenURL(client, userID, id), nil) +// GetAccessToken is a compatibility wrapper around GetAccessTokenWithContext. +func GetAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) { + return GetAccessTokenWithContext(context.Background(), client, userID, id) +} + +// RevokeAccessTokenWithContext revokes an OAuth1 access token. +func RevokeAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { + resp, err := client.DeleteWithContext(ctx, userAccessTokenURL(client, userID, id), nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// RevokeAccessToken is a compatibility wrapper around RevokeAccessTokenWithContext. +func RevokeAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) { + return RevokeAccessTokenWithContext(context.Background(), client, userID, id) +} + // ListAccessTokens enumerates authorized access tokens. func ListAccessTokens(client *gophercloud.ServiceClient, userID string) pagination.Pager { url := userAccessTokensURL(client, userID) @@ -481,14 +532,19 @@ func ListAccessTokenRoles(client *gophercloud.ServiceClient, userID string, id s }) } -// GetAccessTokenRole retrieves details on a single OAuth1 access token role by +// GetAccessTokenRoleWithContext retrieves details on a single OAuth1 access token role by // an ID. -func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { - resp, err := client.Get(userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil) +func GetAccessTokenRoleWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { + resp, err := client.GetWithContext(ctx, userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } +// GetAccessTokenRole is a compatibility wrapper around GetAccessTokenRoleWithContext. +func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) { + return GetAccessTokenRoleWithContext(context.Background(), client, userID, id, roleID) +} + // The following are small helper functions used to help build the signature. // buildOAuth1QueryString builds a URLEncoded parameters string specific for 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 1af55d81..d5b2fe83 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 @@ -1,6 +1,10 @@ package tokens -import "github.com/gophercloud/gophercloud" +import ( + "context" + + "github.com/gophercloud/gophercloud" +) // Scope allows a created token to be limited to a specific domain or project. type Scope struct { @@ -119,9 +123,9 @@ func subjectTokenHeaders(subjectToken string) map[string]string { } } -// Create authenticates and either generates a new token, or changes the Scope +// CreateWithContext authenticates and either generates a new token, or changes the Scope // of an existing token. -func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { +func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { scope, err := opts.ToTokenV3ScopeMap() if err != nil { r.Err = err @@ -134,16 +138,21 @@ func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResu return } - resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ + resp, err := c.PostWithContext(ctx, tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{ OmitHeaders: []string{"X-Auth-Token"}, }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } -// Get validates and retrieves information about another token. -func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { - resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{ +// Create is a compatibility wrapper around CreateWithContext +func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { + return CreateWithContext(context.Background(), c, opts) +} + +// GetGetWithContext validates and retrieves information about another token. +func GetWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r GetResult) { + resp, err := c.GetWithContext(ctx, tokenURL(c), &r.Body, &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), OkCodes: []int{200, 203}, }) @@ -151,9 +160,14 @@ func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { return } -// Validate determines if a specified token is valid or not. -func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { - resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{ +// Get is a compatibility wrapper around GetWithContext +func Get(c *gophercloud.ServiceClient, token string) (r GetResult) { + return GetWithContext(context.Background(), c, token) +} + +// ValidateWithContext determines if a specified token is valid or not. +func ValidateWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (bool, error) { + resp, err := c.HeadWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), OkCodes: []int{200, 204, 404}, }) @@ -164,11 +178,21 @@ func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { return resp.StatusCode == 200 || resp.StatusCode == 204, nil } -// Revoke immediately makes specified token invalid. -func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { - resp, err := c.Delete(tokenURL(c), &gophercloud.RequestOpts{ +// Validate is a compatibility wrapper around ValidateWithContext +func Validate(c *gophercloud.ServiceClient, token string) (bool, error) { + return ValidateWithContext(context.Background(), c, token) +} + +// RevokeWithContext immediately makes specified token invalid. +func RevokeWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r RevokeResult) { + resp, err := c.DeleteWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{ MoreHeaders: subjectTokenHeaders(token), }) _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) return } + +// Revoke is a compatibility wrapper around RevokeWithContext +func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) { + return RevokeWithContext(context.Background(), c, token) +} diff --git a/vendor/github.com/gophercloud/gophercloud/pagination/http.go b/vendor/github.com/gophercloud/gophercloud/pagination/http.go index 7845cda1..13b39252 100644 --- a/vendor/github.com/gophercloud/gophercloud/pagination/http.go +++ b/vendor/github.com/gophercloud/gophercloud/pagination/http.go @@ -1,6 +1,7 @@ package pagination import ( + "context" "encoding/json" "io/ioutil" "net/http" @@ -52,11 +53,16 @@ func PageResultFromParsed(resp *http.Response, body interface{}) PageResult { } } -// Request performs an HTTP request and extracts the http.Response from the result. -func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { - return client.Get(url, nil, &gophercloud.RequestOpts{ +// RequestWithContext performs an HTTP request and extracts the http.Response from the result. +func RequestWithContext(ctx context.Context, client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { + return client.GetWithContext(ctx, url, nil, &gophercloud.RequestOpts{ MoreHeaders: headers, OkCodes: []int{200, 204, 300}, KeepResponseBody: true, }) } + +// Request is a compatibility wrapper around RequestWithContext. +func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) { + return RequestWithContext(context.Background(), client, headers, url) +} diff --git a/vendor/github.com/gophercloud/gophercloud/pagination/pager.go b/vendor/github.com/gophercloud/gophercloud/pagination/pager.go index 1dec2703..8bc66808 100644 --- a/vendor/github.com/gophercloud/gophercloud/pagination/pager.go +++ b/vendor/github.com/gophercloud/gophercloud/pagination/pager.go @@ -1,6 +1,7 @@ package pagination import ( + "context" "errors" "fmt" "net/http" @@ -69,8 +70,8 @@ func (p Pager) WithPageCreator(createPage func(r PageResult) Page) Pager { } } -func (p Pager) fetchNextPage(url string) (Page, error) { - resp, err := Request(p.client, p.Headers, url) +func (p Pager) fetchNextPage(ctx context.Context, url string) (Page, error) { + resp, err := RequestWithContext(ctx, p.client, p.Headers, url) if err != nil { return nil, err } @@ -83,9 +84,10 @@ func (p Pager) fetchNextPage(url string) (Page, error) { return p.createPage(remembered), nil } -// EachPage iterates over each page returned by a Pager, yielding one at a time to a handler function. -// Return "false" from the handler to prematurely stop iterating. -func (p Pager) EachPage(handler func(Page) (bool, error)) error { +// EachPageWithContext iterates over each page returned by a Pager, yielding +// one at a time to a handler function. Return "false" from the handler to +// prematurely stop iterating. +func (p Pager) EachPageWithContext(ctx context.Context, handler func(context.Context, Page) (bool, error)) error { if p.Err != nil { return p.Err } @@ -99,7 +101,7 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error { p.firstPage = nil } else { var err error - currentPage, err = p.fetchNextPage(currentURL) + currentPage, err = p.fetchNextPage(ctx, currentURL) if err != nil { return err } @@ -113,7 +115,7 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error { return nil } - ok, err := handler(currentPage) + ok, err := handler(ctx, currentPage) if err != nil { return err } @@ -131,9 +133,16 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error { } } -// AllPages returns all the pages from a `List` operation in a single page, +// EachPage is a compatibility wrapper around EachPageWithContext. +func (p Pager) EachPage(handler func(Page) (bool, error)) error { + return p.EachPageWithContext(context.Background(), func(_ context.Context, p Page) (bool, error) { + return handler(p) + }) +} + +// AllPagesWithContext returns all the pages from a `List` operation in a single page, // allowing the user to retrieve all the pages at once. -func (p Pager) AllPages() (Page, error) { +func (p Pager) AllPagesWithContext(ctx context.Context) (Page, error) { if p.Err != nil { return nil, p.Err } @@ -143,7 +152,7 @@ func (p Pager) AllPages() (Page, error) { var body reflect.Value // Grab a first page to ascertain the page body type. - firstPage, err := p.fetchNextPage(p.initialURL) + firstPage, err := p.fetchNextPage(ctx, p.initialURL) if err != nil { return nil, err } @@ -252,3 +261,8 @@ func (p Pager) AllPages() (Page, error) { // `Extract*` methods will work. return page.Elem().Interface().(Page), err } + +// AllPages is a compatibility wrapper around AllPagesWithContext. +func (p Pager) AllPages() (Page, error) { + return p.AllPagesWithContext(context.Background()) +} diff --git a/vendor/github.com/gophercloud/gophercloud/provider_client.go b/vendor/github.com/gophercloud/gophercloud/provider_client.go index 5cb5e150..64787e53 100644 --- a/vendor/github.com/gophercloud/gophercloud/provider_client.go +++ b/vendor/github.com/gophercloud/gophercloud/provider_client.go @@ -16,7 +16,7 @@ import ( // DefaultUserAgent is the default User-Agent string set in the request header. const ( - DefaultUserAgent = "gophercloud/v1.9.0" + DefaultUserAgent = "gophercloud/v1.10.0" DefaultMaxBackoffRetries = 60 ) diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go index 3597bfd9..b2b89b01 100644 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ b/vendor/github.com/prometheus/common/expfmt/decode.go @@ -45,7 +45,7 @@ func ResponseFormat(h http.Header) Format { mediatype, params, err := mime.ParseMediaType(ct) if err != nil { - return FmtUnknown + return fmtUnknown } const textType = "text/plain" @@ -53,21 +53,21 @@ func ResponseFormat(h http.Header) Format { switch mediatype { case ProtoType: if p, ok := params["proto"]; ok && p != ProtoProtocol { - return FmtUnknown + return fmtUnknown } if e, ok := params["encoding"]; ok && e != "delimited" { - return FmtUnknown + return fmtUnknown } - return FmtProtoDelim + return fmtProtoDelim case textType: if v, ok := params["version"]; ok && v != TextVersion { - return FmtUnknown + return fmtUnknown } - return FmtText + return fmtText } - return FmtUnknown + return fmtUnknown } // NewDecoder returns a new decoder based on the given input format. diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go index 97ee673d..8fd80618 100644 --- a/vendor/github.com/prometheus/common/expfmt/encode.go +++ b/vendor/github.com/prometheus/common/expfmt/encode.go @@ -76,18 +76,18 @@ func Negotiate(h http.Header) Format { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return FmtProtoDelim + escapingScheme + return fmtProtoDelim + escapingScheme case "text": - return FmtProtoText + escapingScheme + return fmtProtoText + escapingScheme case "compact-text": - return FmtProtoCompact + escapingScheme + return fmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return FmtText + escapingScheme + return fmtText + escapingScheme } } - return FmtText + escapingScheme + return fmtText + escapingScheme } // NegotiateIncludingOpenMetrics works like Negotiate but includes @@ -109,26 +109,26 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return FmtProtoDelim + escapingScheme + return fmtProtoDelim + escapingScheme case "text": - return FmtProtoText + escapingScheme + return fmtProtoText + escapingScheme case "compact-text": - return FmtProtoCompact + escapingScheme + return fmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return FmtText + escapingScheme + return fmtText + escapingScheme } if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") { switch ver { case OpenMetricsVersion_1_0_0: - return FmtOpenMetrics_1_0_0 + escapingScheme + return fmtOpenMetrics_1_0_0 + escapingScheme default: - return FmtOpenMetrics_0_0_1 + escapingScheme + return fmtOpenMetrics_0_0_1 + escapingScheme } } } - return FmtText + escapingScheme + return fmtText + escapingScheme } // NewEncoder returns a new encoder based on content type negotiation. All diff --git a/vendor/github.com/prometheus/common/expfmt/expfmt.go b/vendor/github.com/prometheus/common/expfmt/expfmt.go index f9b6f70f..6fc9555e 100644 --- a/vendor/github.com/prometheus/common/expfmt/expfmt.go +++ b/vendor/github.com/prometheus/common/expfmt/expfmt.go @@ -34,20 +34,21 @@ const ( TextVersion = "0.0.4" ProtoType = `application/vnd.google.protobuf` ProtoProtocol = `io.prometheus.client.MetricFamily` - ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" + protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" OpenMetricsType = `application/openmetrics-text` OpenMetricsVersion_0_0_1 = "0.0.1" OpenMetricsVersion_1_0_0 = "1.0.0" - // The Content-Type values for the different wire protocols. Do not do direct - // comparisons to these constants, instead use the comparison functions. - FmtUnknown Format = `` - FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` - FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` - FmtProtoText Format = ProtoFmt + ` encoding=text` - FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` - FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` - FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` + // The Content-Type values for the different wire protocols. Note that these + // values are now unexported. If code was relying on comparisons to these + // constants, instead use FormatType(). + fmtUnknown Format = `` + fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` + fmtProtoDelim Format = protoFmt + ` encoding=delimited` + fmtProtoText Format = protoFmt + ` encoding=text` + fmtProtoCompact Format = protoFmt + ` encoding=compact-text` + fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` + fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` ) const ( @@ -70,6 +71,26 @@ const ( TypeOpenMetrics ) +// NewFormat generates a new Format from the type provided. Mostly used for +// tests, most Formats should be generated as part of content negotiation in +// encode.go. +func NewFormat(t FormatType) Format { + switch t { + case TypeProtoCompact: + return fmtProtoCompact + case TypeProtoDelim: + return fmtProtoDelim + case TypeProtoText: + return fmtProtoText + case TypeTextPlain: + return fmtText + case TypeOpenMetrics: + return fmtOpenMetrics_1_0_0 + default: + return fmtUnknown + } +} + // FormatType deduces an overall FormatType for the given format. func (f Format) FormatType() FormatType { toks := strings.Split(string(f), ";") diff --git a/vendor/github.com/sapcc/go-bits/httpext/server.go b/vendor/github.com/sapcc/go-bits/httpext/server.go index 69912752..379582aa 100644 --- a/vendor/github.com/sapcc/go-bits/httpext/server.go +++ b/vendor/github.com/sapcc/go-bits/httpext/server.go @@ -33,6 +33,15 @@ import ( var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} +// ShutdownTimeout is the timeout that ListenAndServeContext() will impose on +// server.Shutdown() before forcefully terminating request handlers that are +// still in progress. +// +// The default timeout is quite lenient to accommodate long-running requests, +// but it can be lowered for servers running in an interactive terminal session +// where a quick response to Ctrl-C is more important. +var ShutdownTimeout = 30 * time.Second + // ContextWithSIGINT creates a new context.Context using the provided Context, and // launches a goroutine that cancels the Context when an interrupt signal is caught. // @@ -80,7 +89,7 @@ func ListenAndServeContext(ctx context.Context, addr string, handler http.Handle logg.Info("Shutting down HTTP server...") - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), ShutdownTimeout) err := server.Shutdown(ctx) cancel() waitForServerShutdown <- err diff --git a/vendor/github.com/sapcc/go-bits/respondwith/pkg.go b/vendor/github.com/sapcc/go-bits/respondwith/pkg.go index 754e5378..0369ae5a 100644 --- a/vendor/github.com/sapcc/go-bits/respondwith/pkg.go +++ b/vendor/github.com/sapcc/go-bits/respondwith/pkg.go @@ -25,18 +25,26 @@ package respondwith import ( "encoding/json" "net/http" + + "github.com/sapcc/go-bits/logg" ) // JSON serializes the given data into an HTTP response body // The `code` argument specifies the HTTP response code, usually 200. func JSON(w http.ResponseWriter, code int, data any) { - bytes, err := json.Marshal(&data) - if err == nil { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(code) - w.Write(bytes) //nolint:errcheck - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + + //NOTE 1: We used to do json.Marshal() here, but switched to json.Encoder.Encode() to avoid + //allocating an additional []byte buffer with the entire JSON response before writing it out. + // + //NOTE 2: Intuition would suggest to wrap `w` in a bufio.Writer, but json.Encoder already writes + //into an internal buffer first and then sends that entire buffer into w.Write() all at once, so + //we do not need to add buffering ourselves. + + err := json.NewEncoder(w).Encode(data) + if err != nil { + logg.Error("could not respondwith.JSON(): " + err.Error()) } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 00564191..857f3b92 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -4,7 +4,7 @@ github.com/beorn7/perks/quantile # github.com/cespare/xxhash/v2 v2.2.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 -# github.com/gophercloud/gophercloud v1.9.0 +# github.com/gophercloud/gophercloud v1.10.0 ## explicit; go 1.14 github.com/gophercloud/gophercloud github.com/gophercloud/gophercloud/internal/ctxt @@ -45,15 +45,15 @@ github.com/majewsky/schwift/internal/errext # github.com/mitchellh/go-homedir v1.1.0 ## explicit github.com/mitchellh/go-homedir -# github.com/prometheus/client_golang v1.18.0 -## explicit; go 1.19 +# github.com/prometheus/client_golang v1.19.0 +## explicit; go 1.20 github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promhttp # github.com/prometheus/client_model v0.5.0 ## explicit; go 1.19 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.47.0 +# github.com/prometheus/common v0.48.0 ## explicit; go 1.20 github.com/prometheus/common/expfmt github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg @@ -66,7 +66,7 @@ github.com/prometheus/procfs/internal/util # github.com/sapcc/go-api-declarations v1.10.9 ## explicit; go 1.21 github.com/sapcc/go-api-declarations/bininfo -# github.com/sapcc/go-bits v0.0.0-20240222221204-90b493ffdee9 +# github.com/sapcc/go-bits v0.0.0-20240229224940-f0612298e3a6 ## explicit; go 1.21 github.com/sapcc/go-bits/errext github.com/sapcc/go-bits/httpapi