build(deps): bump github.com/gophercloud/gophercloud
Bumps [github.com/gophercloud/gophercloud](https://github.com/gophercloud/gophercloud) from 0.11.0 to 0.20.0. - [Release notes](https://github.com/gophercloud/gophercloud/releases) - [Changelog](https://github.com/gophercloud/gophercloud/blob/master/CHANGELOG.md) - [Commits](https://github.com/gophercloud/gophercloud/compare/v0.11.0...v0.20.0) --- updated-dependencies: - dependency-name: github.com/gophercloud/gophercloud dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
parent
24727bb2e3
commit
839a708755
20 changed files with 593 additions and 194 deletions
134
vendor/github.com/gophercloud/gophercloud/provider_client.go
generated
vendored
134
vendor/github.com/gophercloud/gophercloud/provider_client.go
generated
vendored
|
|
@ -13,7 +13,10 @@ import (
|
|||
)
|
||||
|
||||
// DefaultUserAgent is the default User-Agent string set in the request header.
|
||||
const DefaultUserAgent = "gophercloud/2.0.0"
|
||||
const (
|
||||
DefaultUserAgent = "gophercloud/2.0.0"
|
||||
DefaultMaxBackoffRetries = 60
|
||||
)
|
||||
|
||||
// UserAgent represents a User-Agent header.
|
||||
type UserAgent struct {
|
||||
|
|
@ -22,6 +25,14 @@ type UserAgent struct {
|
|||
prepend []string
|
||||
}
|
||||
|
||||
type RetryBackoffFunc func(context.Context, *ErrUnexpectedResponseCode, error, uint) error
|
||||
|
||||
// RetryFunc is a catch-all function for retrying failed API requests.
|
||||
// If it returns nil, the request will be retried. If it returns an error,
|
||||
// the request method will exit with that error. failCount is the number of
|
||||
// times the request has failed (starting at 1).
|
||||
type RetryFunc func(context context.Context, method, url string, options *RequestOpts, err error, failCount uint) error
|
||||
|
||||
// Prepend prepends a user-defined string to the default User-Agent string. Users
|
||||
// may pass in one or more strings to prepend.
|
||||
func (ua *UserAgent) Prepend(s ...string) {
|
||||
|
|
@ -80,6 +91,16 @@ type ProviderClient struct {
|
|||
// Context is the context passed to the HTTP request.
|
||||
Context context.Context
|
||||
|
||||
// Retry backoff func is called when rate limited.
|
||||
RetryBackoffFunc RetryBackoffFunc
|
||||
|
||||
// MaxBackoffRetries set the maximum number of backoffs. When not set, defaults to DefaultMaxBackoffRetries
|
||||
MaxBackoffRetries uint
|
||||
|
||||
// A general failed request handler method - this is always called in the end if a request failed. Leave as nil
|
||||
// to abort when an error is encountered.
|
||||
RetryFunc RetryFunc
|
||||
|
||||
// mut is a mutex for the client. It protects read and write access to client attributes such as getting
|
||||
// and setting the TokenID.
|
||||
mut *sync.RWMutex
|
||||
|
|
@ -94,10 +115,32 @@ type ProviderClient struct {
|
|||
// reauthlock represents a set of attributes used to help in the reauthentication process.
|
||||
type reauthlock struct {
|
||||
sync.RWMutex
|
||||
// This channel is non-nil during reauthentication. It can be used to ask the
|
||||
// goroutine doing Reauthenticate() for its result. Look at the implementation
|
||||
// of Reauthenticate() for details.
|
||||
ongoing chan<- (chan<- error)
|
||||
ongoing *reauthFuture
|
||||
}
|
||||
|
||||
// reauthFuture represents future result of the reauthentication process.
|
||||
// while done channel is not closed, reauthentication is in progress.
|
||||
// when done channel is closed, err contains the result of reauthentication.
|
||||
type reauthFuture struct {
|
||||
done chan struct{}
|
||||
err error
|
||||
}
|
||||
|
||||
func newReauthFuture() *reauthFuture {
|
||||
return &reauthFuture{
|
||||
make(chan struct{}),
|
||||
nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *reauthFuture) Set(err error) {
|
||||
f.err = err
|
||||
close(f.done)
|
||||
}
|
||||
|
||||
func (f *reauthFuture) Get() error {
|
||||
<-f.done
|
||||
return f.err
|
||||
}
|
||||
|
||||
// AuthenticatedHeaders returns a map of HTTP headers that are common for all
|
||||
|
|
@ -112,9 +155,7 @@ func (client *ProviderClient) AuthenticatedHeaders() (m map[string]string) {
|
|||
ongoing := client.reauthmut.ongoing
|
||||
client.reauthmut.Unlock()
|
||||
if ongoing != nil {
|
||||
responseChannel := make(chan error)
|
||||
ongoing <- responseChannel
|
||||
_ = <-responseChannel
|
||||
_ = ongoing.Get()
|
||||
}
|
||||
}
|
||||
t := client.Token()
|
||||
|
|
@ -237,21 +278,19 @@ func (client *ProviderClient) Reauthenticate(previousToken string) error {
|
|||
return client.ReauthFunc()
|
||||
}
|
||||
|
||||
messages := make(chan (chan<- error))
|
||||
future := newReauthFuture()
|
||||
|
||||
// Check if a Reauthenticate is in progress, or start one if not.
|
||||
client.reauthmut.Lock()
|
||||
ongoing := client.reauthmut.ongoing
|
||||
if ongoing == nil {
|
||||
client.reauthmut.ongoing = messages
|
||||
client.reauthmut.ongoing = future
|
||||
}
|
||||
client.reauthmut.Unlock()
|
||||
|
||||
// If Reauthenticate is running elsewhere, wait for its result.
|
||||
if ongoing != nil {
|
||||
responseChannel := make(chan error)
|
||||
ongoing <- responseChannel
|
||||
return <-responseChannel
|
||||
return ongoing.Get()
|
||||
}
|
||||
|
||||
// Perform the actual reauthentication.
|
||||
|
|
@ -264,22 +303,10 @@ func (client *ProviderClient) Reauthenticate(previousToken string) error {
|
|||
|
||||
// Mark Reauthenticate as finished.
|
||||
client.reauthmut.Lock()
|
||||
client.reauthmut.ongoing.Set(err)
|
||||
client.reauthmut.ongoing = nil
|
||||
client.reauthmut.Unlock()
|
||||
|
||||
// Report result to all other interested goroutines.
|
||||
//
|
||||
// This happens in a separate goroutine because another goroutine might have
|
||||
// acquired a copy of `client.reauthmut.ongoing` before we cleared it, but not
|
||||
// have come around to sending its request. By answering in a goroutine, we
|
||||
// can have that goroutine linger until all responseChannels have been sent.
|
||||
// When GC has collected all sendings ends of the channel, our receiving end
|
||||
// will be closed and the goroutine will end.
|
||||
go func() {
|
||||
for responseChannel := range messages {
|
||||
responseChannel <- err
|
||||
}
|
||||
}()
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -317,6 +344,8 @@ type requestState struct {
|
|||
// reauthenticate, but keep getting 401 responses with the fresh token, reauthenticating some more
|
||||
// will just get us into an infinite loop.
|
||||
hasReauthenticated bool
|
||||
// Retry-After backoff counter, increments during each backoff call
|
||||
retries uint
|
||||
}
|
||||
|
||||
var applicationJSON = "application/json"
|
||||
|
|
@ -397,6 +426,16 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts
|
|||
// Issue the request.
|
||||
resp, err := client.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
if client.RetryFunc != nil {
|
||||
var e error
|
||||
state.retries = state.retries + 1
|
||||
e = client.RetryFunc(client.Context, method, url, options, err, state.retries)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return client.doRequest(method, url, options, state)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -421,7 +460,7 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts
|
|||
respErr := ErrUnexpectedResponseCode{
|
||||
URL: url,
|
||||
Method: method,
|
||||
Expected: options.OkCodes,
|
||||
Expected: okc,
|
||||
Actual: resp.StatusCode,
|
||||
Body: body,
|
||||
ResponseHeader: resp.Header,
|
||||
|
|
@ -492,11 +531,29 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts
|
|||
if error409er, ok := errType.(Err409er); ok {
|
||||
err = error409er.Error409(respErr)
|
||||
}
|
||||
case 429:
|
||||
case http.StatusTooManyRequests, 498:
|
||||
err = ErrDefault429{respErr}
|
||||
if error429er, ok := errType.(Err429er); ok {
|
||||
err = error429er.Error429(respErr)
|
||||
}
|
||||
|
||||
maxTries := client.MaxBackoffRetries
|
||||
if maxTries == 0 {
|
||||
maxTries = DefaultMaxBackoffRetries
|
||||
}
|
||||
|
||||
if f := client.RetryBackoffFunc; f != nil && state.retries < maxTries {
|
||||
var e error
|
||||
|
||||
state.retries = state.retries + 1
|
||||
e = f(client.Context, &respErr, err, state.retries)
|
||||
|
||||
if e != nil {
|
||||
return resp, e
|
||||
}
|
||||
|
||||
return client.doRequest(method, url, options, state)
|
||||
}
|
||||
case http.StatusInternalServerError:
|
||||
err = ErrDefault500{respErr}
|
||||
if error500er, ok := errType.(Err500er); ok {
|
||||
|
|
@ -513,6 +570,17 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts
|
|||
err = respErr
|
||||
}
|
||||
|
||||
if err != nil && client.RetryFunc != nil {
|
||||
var e error
|
||||
state.retries = state.retries + 1
|
||||
e = client.RetryFunc(client.Context, method, url, options, err, state.retries)
|
||||
if e != nil {
|
||||
return resp, e
|
||||
}
|
||||
|
||||
return client.doRequest(method, url, options, state)
|
||||
}
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
|
|
@ -526,6 +594,16 @@ func (client *ProviderClient) doRequest(method, url string, options *RequestOpts
|
|||
return resp, err
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(options.JSONResponse); err != nil {
|
||||
if client.RetryFunc != nil {
|
||||
var e error
|
||||
state.retries = state.retries + 1
|
||||
e = client.RetryFunc(client.Context, method, url, options, err, state.retries)
|
||||
if e != nil {
|
||||
return resp, e
|
||||
}
|
||||
|
||||
return client.doRequest(method, url, options, state)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue