VENDOR intensifies
This commit is contained in:
19
vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go
generated
vendored
Executable file
19
vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go
generated
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
// +build !appengine,!plan9
|
||||
|
||||
package request
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func isErrConnectionReset(err error) bool {
|
||||
if opErr, ok := err.(*net.OpError); ok {
|
||||
if sysErr, ok := opErr.Err.(*os.SyscallError); ok {
|
||||
return sysErr.Err == syscall.ECONNRESET
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
11
vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go
generated
vendored
Executable file
11
vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go
generated
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
// +build appengine plan9
|
||||
|
||||
package request
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func isErrConnectionReset(err error) bool {
|
||||
return strings.Contains(err.Error(), "connection reset")
|
||||
}
|
||||
277
vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
generated
vendored
Executable file
277
vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
generated
vendored
Executable file
@@ -0,0 +1,277 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A Handlers provides a collection of request handlers for various
|
||||
// stages of handling requests.
|
||||
type Handlers struct {
|
||||
Validate HandlerList
|
||||
Build HandlerList
|
||||
Sign HandlerList
|
||||
Send HandlerList
|
||||
ValidateResponse HandlerList
|
||||
Unmarshal HandlerList
|
||||
UnmarshalStream HandlerList
|
||||
UnmarshalMeta HandlerList
|
||||
UnmarshalError HandlerList
|
||||
Retry HandlerList
|
||||
AfterRetry HandlerList
|
||||
CompleteAttempt HandlerList
|
||||
Complete HandlerList
|
||||
}
|
||||
|
||||
// Copy returns of this handler's lists.
|
||||
func (h *Handlers) Copy() Handlers {
|
||||
return Handlers{
|
||||
Validate: h.Validate.copy(),
|
||||
Build: h.Build.copy(),
|
||||
Sign: h.Sign.copy(),
|
||||
Send: h.Send.copy(),
|
||||
ValidateResponse: h.ValidateResponse.copy(),
|
||||
Unmarshal: h.Unmarshal.copy(),
|
||||
UnmarshalStream: h.UnmarshalStream.copy(),
|
||||
UnmarshalError: h.UnmarshalError.copy(),
|
||||
UnmarshalMeta: h.UnmarshalMeta.copy(),
|
||||
Retry: h.Retry.copy(),
|
||||
AfterRetry: h.AfterRetry.copy(),
|
||||
CompleteAttempt: h.CompleteAttempt.copy(),
|
||||
Complete: h.Complete.copy(),
|
||||
}
|
||||
}
|
||||
|
||||
// Clear removes callback functions for all handlers
|
||||
func (h *Handlers) Clear() {
|
||||
h.Validate.Clear()
|
||||
h.Build.Clear()
|
||||
h.Send.Clear()
|
||||
h.Sign.Clear()
|
||||
h.Unmarshal.Clear()
|
||||
h.UnmarshalStream.Clear()
|
||||
h.UnmarshalMeta.Clear()
|
||||
h.UnmarshalError.Clear()
|
||||
h.ValidateResponse.Clear()
|
||||
h.Retry.Clear()
|
||||
h.AfterRetry.Clear()
|
||||
h.CompleteAttempt.Clear()
|
||||
h.Complete.Clear()
|
||||
}
|
||||
|
||||
// A HandlerListRunItem represents an entry in the HandlerList which
|
||||
// is being run.
|
||||
type HandlerListRunItem struct {
|
||||
Index int
|
||||
Handler NamedHandler
|
||||
Request *Request
|
||||
}
|
||||
|
||||
// A HandlerList manages zero or more handlers in a list.
|
||||
type HandlerList struct {
|
||||
list []NamedHandler
|
||||
|
||||
// Called after each request handler in the list is called. If set
|
||||
// and the func returns true the HandlerList will continue to iterate
|
||||
// over the request handlers. If false is returned the HandlerList
|
||||
// will stop iterating.
|
||||
//
|
||||
// Should be used if extra logic to be performed between each handler
|
||||
// in the list. This can be used to terminate a list's iteration
|
||||
// based on a condition such as error like, HandlerListStopOnError.
|
||||
// Or for logging like HandlerListLogItem.
|
||||
AfterEachFn func(item HandlerListRunItem) bool
|
||||
}
|
||||
|
||||
// A NamedHandler is a struct that contains a name and function callback.
|
||||
type NamedHandler struct {
|
||||
Name string
|
||||
Fn func(*Request)
|
||||
}
|
||||
|
||||
// copy creates a copy of the handler list.
|
||||
func (l *HandlerList) copy() HandlerList {
|
||||
n := HandlerList{
|
||||
AfterEachFn: l.AfterEachFn,
|
||||
}
|
||||
if len(l.list) == 0 {
|
||||
return n
|
||||
}
|
||||
|
||||
n.list = append(make([]NamedHandler, 0, len(l.list)), l.list...)
|
||||
return n
|
||||
}
|
||||
|
||||
// Clear clears the handler list.
|
||||
func (l *HandlerList) Clear() {
|
||||
l.list = l.list[0:0]
|
||||
}
|
||||
|
||||
// Len returns the number of handlers in the list.
|
||||
func (l *HandlerList) Len() int {
|
||||
return len(l.list)
|
||||
}
|
||||
|
||||
// PushBack pushes handler f to the back of the handler list.
|
||||
func (l *HandlerList) PushBack(f func(*Request)) {
|
||||
l.PushBackNamed(NamedHandler{"__anonymous", f})
|
||||
}
|
||||
|
||||
// PushBackNamed pushes named handler f to the back of the handler list.
|
||||
func (l *HandlerList) PushBackNamed(n NamedHandler) {
|
||||
if cap(l.list) == 0 {
|
||||
l.list = make([]NamedHandler, 0, 5)
|
||||
}
|
||||
l.list = append(l.list, n)
|
||||
}
|
||||
|
||||
// PushFront pushes handler f to the front of the handler list.
|
||||
func (l *HandlerList) PushFront(f func(*Request)) {
|
||||
l.PushFrontNamed(NamedHandler{"__anonymous", f})
|
||||
}
|
||||
|
||||
// PushFrontNamed pushes named handler f to the front of the handler list.
|
||||
func (l *HandlerList) PushFrontNamed(n NamedHandler) {
|
||||
if cap(l.list) == len(l.list) {
|
||||
// Allocating new list required
|
||||
l.list = append([]NamedHandler{n}, l.list...)
|
||||
} else {
|
||||
// Enough room to prepend into list.
|
||||
l.list = append(l.list, NamedHandler{})
|
||||
copy(l.list[1:], l.list)
|
||||
l.list[0] = n
|
||||
}
|
||||
}
|
||||
|
||||
// Remove removes a NamedHandler n
|
||||
func (l *HandlerList) Remove(n NamedHandler) {
|
||||
l.RemoveByName(n.Name)
|
||||
}
|
||||
|
||||
// RemoveByName removes a NamedHandler by name.
|
||||
func (l *HandlerList) RemoveByName(name string) {
|
||||
for i := 0; i < len(l.list); i++ {
|
||||
m := l.list[i]
|
||||
if m.Name == name {
|
||||
// Shift array preventing creating new arrays
|
||||
copy(l.list[i:], l.list[i+1:])
|
||||
l.list[len(l.list)-1] = NamedHandler{}
|
||||
l.list = l.list[:len(l.list)-1]
|
||||
|
||||
// decrement list so next check to length is correct
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SwapNamed will swap out any existing handlers with the same name as the
|
||||
// passed in NamedHandler returning true if handlers were swapped. False is
|
||||
// returned otherwise.
|
||||
func (l *HandlerList) SwapNamed(n NamedHandler) (swapped bool) {
|
||||
for i := 0; i < len(l.list); i++ {
|
||||
if l.list[i].Name == n.Name {
|
||||
l.list[i].Fn = n.Fn
|
||||
swapped = true
|
||||
}
|
||||
}
|
||||
|
||||
return swapped
|
||||
}
|
||||
|
||||
// Swap will swap out all handlers matching the name passed in. The matched
|
||||
// handlers will be swapped in. True is returned if the handlers were swapped.
|
||||
func (l *HandlerList) Swap(name string, replace NamedHandler) bool {
|
||||
var swapped bool
|
||||
|
||||
for i := 0; i < len(l.list); i++ {
|
||||
if l.list[i].Name == name {
|
||||
l.list[i] = replace
|
||||
swapped = true
|
||||
}
|
||||
}
|
||||
|
||||
return swapped
|
||||
}
|
||||
|
||||
// SetBackNamed will replace the named handler if it exists in the handler list.
|
||||
// If the handler does not exist the handler will be added to the end of the list.
|
||||
func (l *HandlerList) SetBackNamed(n NamedHandler) {
|
||||
if !l.SwapNamed(n) {
|
||||
l.PushBackNamed(n)
|
||||
}
|
||||
}
|
||||
|
||||
// SetFrontNamed will replace the named handler if it exists in the handler list.
|
||||
// If the handler does not exist the handler will be added to the beginning of
|
||||
// the list.
|
||||
func (l *HandlerList) SetFrontNamed(n NamedHandler) {
|
||||
if !l.SwapNamed(n) {
|
||||
l.PushFrontNamed(n)
|
||||
}
|
||||
}
|
||||
|
||||
// Run executes all handlers in the list with a given request object.
|
||||
func (l *HandlerList) Run(r *Request) {
|
||||
for i, h := range l.list {
|
||||
h.Fn(r)
|
||||
item := HandlerListRunItem{
|
||||
Index: i, Handler: h, Request: r,
|
||||
}
|
||||
if l.AfterEachFn != nil && !l.AfterEachFn(item) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HandlerListLogItem logs the request handler and the state of the
|
||||
// request's Error value. Always returns true to continue iterating
|
||||
// request handlers in a HandlerList.
|
||||
func HandlerListLogItem(item HandlerListRunItem) bool {
|
||||
if item.Request.Config.Logger == nil {
|
||||
return true
|
||||
}
|
||||
item.Request.Config.Logger.Log("DEBUG: RequestHandler",
|
||||
item.Index, item.Handler.Name, item.Request.Error)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// HandlerListStopOnError returns false to stop the HandlerList iterating
|
||||
// over request handlers if Request.Error is not nil. True otherwise
|
||||
// to continue iterating.
|
||||
func HandlerListStopOnError(item HandlerListRunItem) bool {
|
||||
return item.Request.Error == nil
|
||||
}
|
||||
|
||||
// WithAppendUserAgent will add a string to the user agent prefixed with a
|
||||
// single white space.
|
||||
func WithAppendUserAgent(s string) Option {
|
||||
return func(r *Request) {
|
||||
r.Handlers.Build.PushBack(func(r2 *Request) {
|
||||
AddToUserAgent(r, s)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request
|
||||
// header. If the extra parameters are provided they will be added as metadata to the
|
||||
// name/version pair resulting in the following format.
|
||||
// "name/version (extra0; extra1; ...)"
|
||||
// The user agent part will be concatenated with this current request's user agent string.
|
||||
func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) {
|
||||
ua := fmt.Sprintf("%s/%s", name, version)
|
||||
if len(extra) > 0 {
|
||||
ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; "))
|
||||
}
|
||||
return func(r *Request) {
|
||||
AddToUserAgent(r, ua)
|
||||
}
|
||||
}
|
||||
|
||||
// MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header.
|
||||
// The input string will be concatenated with the current request's user agent string.
|
||||
func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) {
|
||||
return func(r *Request) {
|
||||
AddToUserAgent(r, s)
|
||||
}
|
||||
}
|
||||
24
vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
generated
vendored
Executable file
24
vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
generated
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
|
||||
req := new(http.Request)
|
||||
*req = *r
|
||||
req.URL = &url.URL{}
|
||||
*req.URL = *r.URL
|
||||
req.Body = body
|
||||
|
||||
req.Header = http.Header{}
|
||||
for k, v := range r.Header {
|
||||
for _, vv := range v {
|
||||
req.Header.Add(k, vv)
|
||||
}
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
60
vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
generated
vendored
Executable file
60
vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
generated
vendored
Executable file
@@ -0,0 +1,60 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/aws/aws-sdk-go/internal/sdkio"
|
||||
)
|
||||
|
||||
// offsetReader is a thread-safe io.ReadCloser to prevent racing
|
||||
// with retrying requests
|
||||
type offsetReader struct {
|
||||
buf io.ReadSeeker
|
||||
lock sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader {
|
||||
reader := &offsetReader{}
|
||||
buf.Seek(offset, sdkio.SeekStart)
|
||||
|
||||
reader.buf = buf
|
||||
return reader
|
||||
}
|
||||
|
||||
// Close will close the instance of the offset reader's access to
|
||||
// the underlying io.ReadSeeker.
|
||||
func (o *offsetReader) Close() error {
|
||||
o.lock.Lock()
|
||||
defer o.lock.Unlock()
|
||||
o.closed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read is a thread-safe read of the underlying io.ReadSeeker
|
||||
func (o *offsetReader) Read(p []byte) (int, error) {
|
||||
o.lock.Lock()
|
||||
defer o.lock.Unlock()
|
||||
|
||||
if o.closed {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
return o.buf.Read(p)
|
||||
}
|
||||
|
||||
// Seek is a thread-safe seeking operation.
|
||||
func (o *offsetReader) Seek(offset int64, whence int) (int64, error) {
|
||||
o.lock.Lock()
|
||||
defer o.lock.Unlock()
|
||||
|
||||
return o.buf.Seek(offset, whence)
|
||||
}
|
||||
|
||||
// CloseAndCopy will return a new offsetReader with a copy of the old buffer
|
||||
// and close the old buffer.
|
||||
func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader {
|
||||
o.Close()
|
||||
return newOffsetReader(o.buf, offset)
|
||||
}
|
||||
673
vendor/github.com/aws/aws-sdk-go/aws/request/request.go
generated
vendored
Executable file
673
vendor/github.com/aws/aws-sdk-go/aws/request/request.go
generated
vendored
Executable file
@@ -0,0 +1,673 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||
"github.com/aws/aws-sdk-go/internal/sdkio"
|
||||
)
|
||||
|
||||
const (
|
||||
// ErrCodeSerialization is the serialization error code that is received
|
||||
// during protocol unmarshaling.
|
||||
ErrCodeSerialization = "SerializationError"
|
||||
|
||||
// ErrCodeRead is an error that is returned during HTTP reads.
|
||||
ErrCodeRead = "ReadError"
|
||||
|
||||
// ErrCodeResponseTimeout is the connection timeout error that is received
|
||||
// during body reads.
|
||||
ErrCodeResponseTimeout = "ResponseTimeout"
|
||||
|
||||
// ErrCodeInvalidPresignExpire is returned when the expire time provided to
|
||||
// presign is invalid
|
||||
ErrCodeInvalidPresignExpire = "InvalidPresignExpireError"
|
||||
|
||||
// CanceledErrorCode is the error code that will be returned by an
|
||||
// API request that was canceled. Requests given a aws.Context may
|
||||
// return this error when canceled.
|
||||
CanceledErrorCode = "RequestCanceled"
|
||||
)
|
||||
|
||||
// A Request is the service request to be made.
|
||||
type Request struct {
|
||||
Config aws.Config
|
||||
ClientInfo metadata.ClientInfo
|
||||
Handlers Handlers
|
||||
|
||||
Retryer
|
||||
AttemptTime time.Time
|
||||
Time time.Time
|
||||
Operation *Operation
|
||||
HTTPRequest *http.Request
|
||||
HTTPResponse *http.Response
|
||||
Body io.ReadSeeker
|
||||
BodyStart int64 // offset from beginning of Body that the request body starts
|
||||
Params interface{}
|
||||
Error error
|
||||
Data interface{}
|
||||
RequestID string
|
||||
RetryCount int
|
||||
Retryable *bool
|
||||
RetryDelay time.Duration
|
||||
NotHoist bool
|
||||
SignedHeaderVals http.Header
|
||||
LastSignedAt time.Time
|
||||
DisableFollowRedirects bool
|
||||
|
||||
// A value greater than 0 instructs the request to be signed as Presigned URL
|
||||
// You should not set this field directly. Instead use Request's
|
||||
// Presign or PresignRequest methods.
|
||||
ExpireTime time.Duration
|
||||
|
||||
context aws.Context
|
||||
|
||||
built bool
|
||||
|
||||
// Need to persist an intermediate body between the input Body and HTTP
|
||||
// request body because the HTTP Client's transport can maintain a reference
|
||||
// to the HTTP request's body after the client has returned. This value is
|
||||
// safe to use concurrently and wrap the input Body for each HTTP request.
|
||||
safeBody *offsetReader
|
||||
}
|
||||
|
||||
// An Operation is the service API operation to be made.
|
||||
type Operation struct {
|
||||
Name string
|
||||
HTTPMethod string
|
||||
HTTPPath string
|
||||
*Paginator
|
||||
|
||||
BeforePresignFn func(r *Request) error
|
||||
}
|
||||
|
||||
// New returns a new Request pointer for the service API
|
||||
// operation and parameters.
|
||||
//
|
||||
// Params is any value of input parameters to be the request payload.
|
||||
// Data is pointer value to an object which the request's response
|
||||
// payload will be deserialized to.
|
||||
func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,
|
||||
retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request {
|
||||
|
||||
method := operation.HTTPMethod
|
||||
if method == "" {
|
||||
method = "POST"
|
||||
}
|
||||
|
||||
httpReq, _ := http.NewRequest(method, "", nil)
|
||||
|
||||
var err error
|
||||
httpReq.URL, err = url.Parse(clientInfo.Endpoint + operation.HTTPPath)
|
||||
if err != nil {
|
||||
httpReq.URL = &url.URL{}
|
||||
err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err)
|
||||
}
|
||||
|
||||
SanitizeHostForHeader(httpReq)
|
||||
|
||||
r := &Request{
|
||||
Config: cfg,
|
||||
ClientInfo: clientInfo,
|
||||
Handlers: handlers.Copy(),
|
||||
|
||||
Retryer: retryer,
|
||||
Time: time.Now(),
|
||||
ExpireTime: 0,
|
||||
Operation: operation,
|
||||
HTTPRequest: httpReq,
|
||||
Body: nil,
|
||||
Params: params,
|
||||
Error: err,
|
||||
Data: data,
|
||||
}
|
||||
r.SetBufferBody([]byte{})
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// A Option is a functional option that can augment or modify a request when
|
||||
// using a WithContext API operation method.
|
||||
type Option func(*Request)
|
||||
|
||||
// WithGetResponseHeader builds a request Option which will retrieve a single
|
||||
// header value from the HTTP Response. If there are multiple values for the
|
||||
// header key use WithGetResponseHeaders instead to access the http.Header
|
||||
// map directly. The passed in val pointer must be non-nil.
|
||||
//
|
||||
// This Option can be used multiple times with a single API operation.
|
||||
//
|
||||
// var id2, versionID string
|
||||
// svc.PutObjectWithContext(ctx, params,
|
||||
// request.WithGetResponseHeader("x-amz-id-2", &id2),
|
||||
// request.WithGetResponseHeader("x-amz-version-id", &versionID),
|
||||
// )
|
||||
func WithGetResponseHeader(key string, val *string) Option {
|
||||
return func(r *Request) {
|
||||
r.Handlers.Complete.PushBack(func(req *Request) {
|
||||
*val = req.HTTPResponse.Header.Get(key)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithGetResponseHeaders builds a request Option which will retrieve the
|
||||
// headers from the HTTP response and assign them to the passed in headers
|
||||
// variable. The passed in headers pointer must be non-nil.
|
||||
//
|
||||
// var headers http.Header
|
||||
// svc.PutObjectWithContext(ctx, params, request.WithGetResponseHeaders(&headers))
|
||||
func WithGetResponseHeaders(headers *http.Header) Option {
|
||||
return func(r *Request) {
|
||||
r.Handlers.Complete.PushBack(func(req *Request) {
|
||||
*headers = req.HTTPResponse.Header
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithLogLevel is a request option that will set the request to use a specific
|
||||
// log level when the request is made.
|
||||
//
|
||||
// svc.PutObjectWithContext(ctx, params, request.WithLogLevel(aws.LogDebugWithHTTPBody)
|
||||
func WithLogLevel(l aws.LogLevelType) Option {
|
||||
return func(r *Request) {
|
||||
r.Config.LogLevel = aws.LogLevel(l)
|
||||
}
|
||||
}
|
||||
|
||||
// ApplyOptions will apply each option to the request calling them in the order
|
||||
// the were provided.
|
||||
func (r *Request) ApplyOptions(opts ...Option) {
|
||||
for _, opt := range opts {
|
||||
opt(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Context will always returns a non-nil context. If Request does not have a
|
||||
// context aws.BackgroundContext will be returned.
|
||||
func (r *Request) Context() aws.Context {
|
||||
if r.context != nil {
|
||||
return r.context
|
||||
}
|
||||
return aws.BackgroundContext()
|
||||
}
|
||||
|
||||
// SetContext adds a Context to the current request that can be used to cancel
|
||||
// a in-flight request. The Context value must not be nil, or this method will
|
||||
// panic.
|
||||
//
|
||||
// Unlike http.Request.WithContext, SetContext does not return a copy of the
|
||||
// Request. It is not safe to use use a single Request value for multiple
|
||||
// requests. A new Request should be created for each API operation request.
|
||||
//
|
||||
// Go 1.6 and below:
|
||||
// The http.Request's Cancel field will be set to the Done() value of
|
||||
// the context. This will overwrite the Cancel field's value.
|
||||
//
|
||||
// Go 1.7 and above:
|
||||
// The http.Request.WithContext will be used to set the context on the underlying
|
||||
// http.Request. This will create a shallow copy of the http.Request. The SDK
|
||||
// may create sub contexts in the future for nested requests such as retries.
|
||||
func (r *Request) SetContext(ctx aws.Context) {
|
||||
if ctx == nil {
|
||||
panic("context cannot be nil")
|
||||
}
|
||||
setRequestContext(r, ctx)
|
||||
}
|
||||
|
||||
// WillRetry returns if the request's can be retried.
|
||||
func (r *Request) WillRetry() bool {
|
||||
if !aws.IsReaderSeekable(r.Body) && r.HTTPRequest.Body != NoBody {
|
||||
return false
|
||||
}
|
||||
return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries()
|
||||
}
|
||||
|
||||
// ParamsFilled returns if the request's parameters have been populated
|
||||
// and the parameters are valid. False is returned if no parameters are
|
||||
// provided or invalid.
|
||||
func (r *Request) ParamsFilled() bool {
|
||||
return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid()
|
||||
}
|
||||
|
||||
// DataFilled returns true if the request's data for response deserialization
|
||||
// target has been set and is a valid. False is returned if data is not
|
||||
// set, or is invalid.
|
||||
func (r *Request) DataFilled() bool {
|
||||
return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid()
|
||||
}
|
||||
|
||||
// SetBufferBody will set the request's body bytes that will be sent to
|
||||
// the service API.
|
||||
func (r *Request) SetBufferBody(buf []byte) {
|
||||
r.SetReaderBody(bytes.NewReader(buf))
|
||||
}
|
||||
|
||||
// SetStringBody sets the body of the request to be backed by a string.
|
||||
func (r *Request) SetStringBody(s string) {
|
||||
r.SetReaderBody(strings.NewReader(s))
|
||||
}
|
||||
|
||||
// SetReaderBody will set the request's body reader.
|
||||
func (r *Request) SetReaderBody(reader io.ReadSeeker) {
|
||||
r.Body = reader
|
||||
r.BodyStart, _ = reader.Seek(0, sdkio.SeekCurrent) // Get the Bodies current offset.
|
||||
r.ResetBody()
|
||||
}
|
||||
|
||||
// Presign returns the request's signed URL. Error will be returned
|
||||
// if the signing fails. The expire parameter is only used for presigned Amazon
|
||||
// S3 API requests. All other AWS services will use a fixed expiration
|
||||
// time of 15 minutes.
|
||||
//
|
||||
// It is invalid to create a presigned URL with a expire duration 0 or less. An
|
||||
// error is returned if expire duration is 0 or less.
|
||||
func (r *Request) Presign(expire time.Duration) (string, error) {
|
||||
r = r.copy()
|
||||
|
||||
// Presign requires all headers be hoisted. There is no way to retrieve
|
||||
// the signed headers not hoisted without this. Making the presigned URL
|
||||
// useless.
|
||||
r.NotHoist = false
|
||||
|
||||
u, _, err := getPresignedURL(r, expire)
|
||||
return u, err
|
||||
}
|
||||
|
||||
// PresignRequest behaves just like presign, with the addition of returning a
|
||||
// set of headers that were signed. The expire parameter is only used for
|
||||
// presigned Amazon S3 API requests. All other AWS services will use a fixed
|
||||
// expiration time of 15 minutes.
|
||||
//
|
||||
// It is invalid to create a presigned URL with a expire duration 0 or less. An
|
||||
// error is returned if expire duration is 0 or less.
|
||||
//
|
||||
// Returns the URL string for the API operation with signature in the query string,
|
||||
// and the HTTP headers that were included in the signature. These headers must
|
||||
// be included in any HTTP request made with the presigned URL.
|
||||
//
|
||||
// To prevent hoisting any headers to the query string set NotHoist to true on
|
||||
// this Request value prior to calling PresignRequest.
|
||||
func (r *Request) PresignRequest(expire time.Duration) (string, http.Header, error) {
|
||||
r = r.copy()
|
||||
return getPresignedURL(r, expire)
|
||||
}
|
||||
|
||||
// IsPresigned returns true if the request represents a presigned API url.
|
||||
func (r *Request) IsPresigned() bool {
|
||||
return r.ExpireTime != 0
|
||||
}
|
||||
|
||||
func getPresignedURL(r *Request, expire time.Duration) (string, http.Header, error) {
|
||||
if expire <= 0 {
|
||||
return "", nil, awserr.New(
|
||||
ErrCodeInvalidPresignExpire,
|
||||
"presigned URL requires an expire duration greater than 0",
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
r.ExpireTime = expire
|
||||
|
||||
if r.Operation.BeforePresignFn != nil {
|
||||
if err := r.Operation.BeforePresignFn(r); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := r.Sign(); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil
|
||||
}
|
||||
|
||||
func debugLogReqError(r *Request, stage string, retrying bool, err error) {
|
||||
if !r.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) {
|
||||
return
|
||||
}
|
||||
|
||||
retryStr := "not retrying"
|
||||
if retrying {
|
||||
retryStr = "will retry"
|
||||
}
|
||||
|
||||
r.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v",
|
||||
stage, r.ClientInfo.ServiceName, r.Operation.Name, retryStr, err))
|
||||
}
|
||||
|
||||
// Build will build the request's object so it can be signed and sent
|
||||
// to the service. Build will also validate all the request's parameters.
|
||||
// Any additional build Handlers set on this request will be run
|
||||
// in the order they were set.
|
||||
//
|
||||
// The request will only be built once. Multiple calls to build will have
|
||||
// no effect.
|
||||
//
|
||||
// If any Validate or Build errors occur the build will stop and the error
|
||||
// which occurred will be returned.
|
||||
func (r *Request) Build() error {
|
||||
if !r.built {
|
||||
r.Handlers.Validate.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Validate Request", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
r.Handlers.Build.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Build Request", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
r.built = true
|
||||
}
|
||||
|
||||
return r.Error
|
||||
}
|
||||
|
||||
// Sign will sign the request, returning error if errors are encountered.
|
||||
//
|
||||
// Sign will build the request prior to signing. All Sign Handlers will
|
||||
// be executed in the order they were set.
|
||||
func (r *Request) Sign() error {
|
||||
r.Build()
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Build Request", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
|
||||
r.Handlers.Sign.Run(r)
|
||||
return r.Error
|
||||
}
|
||||
|
||||
func (r *Request) getNextRequestBody() (io.ReadCloser, error) {
|
||||
if r.safeBody != nil {
|
||||
r.safeBody.Close()
|
||||
}
|
||||
|
||||
r.safeBody = newOffsetReader(r.Body, r.BodyStart)
|
||||
|
||||
// Go 1.8 tightened and clarified the rules code needs to use when building
|
||||
// requests with the http package. Go 1.8 removed the automatic detection
|
||||
// of if the Request.Body was empty, or actually had bytes in it. The SDK
|
||||
// always sets the Request.Body even if it is empty and should not actually
|
||||
// be sent. This is incorrect.
|
||||
//
|
||||
// Go 1.8 did add a http.NoBody value that the SDK can use to tell the http
|
||||
// client that the request really should be sent without a body. The
|
||||
// Request.Body cannot be set to nil, which is preferable, because the
|
||||
// field is exported and could introduce nil pointer dereferences for users
|
||||
// of the SDK if they used that field.
|
||||
//
|
||||
// Related golang/go#18257
|
||||
l, err := aws.SeekerLen(r.Body)
|
||||
if err != nil {
|
||||
return nil, awserr.New(ErrCodeSerialization, "failed to compute request body size", err)
|
||||
}
|
||||
|
||||
var body io.ReadCloser
|
||||
if l == 0 {
|
||||
body = NoBody
|
||||
} else if l > 0 {
|
||||
body = r.safeBody
|
||||
} else {
|
||||
// Hack to prevent sending bodies for methods where the body
|
||||
// should be ignored by the server. Sending bodies on these
|
||||
// methods without an associated ContentLength will cause the
|
||||
// request to socket timeout because the server does not handle
|
||||
// Transfer-Encoding: chunked bodies for these methods.
|
||||
//
|
||||
// This would only happen if a aws.ReaderSeekerCloser was used with
|
||||
// a io.Reader that was not also an io.Seeker, or did not implement
|
||||
// Len() method.
|
||||
switch r.Operation.HTTPMethod {
|
||||
case "GET", "HEAD", "DELETE":
|
||||
body = NoBody
|
||||
default:
|
||||
body = r.safeBody
|
||||
}
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// GetBody will return an io.ReadSeeker of the Request's underlying
|
||||
// input body with a concurrency safe wrapper.
|
||||
func (r *Request) GetBody() io.ReadSeeker {
|
||||
return r.safeBody
|
||||
}
|
||||
|
||||
// Send will send the request, returning error if errors are encountered.
|
||||
//
|
||||
// Send will sign the request prior to sending. All Send Handlers will
|
||||
// be executed in the order they were set.
|
||||
//
|
||||
// Canceling a request is non-deterministic. If a request has been canceled,
|
||||
// then the transport will choose, randomly, one of the state channels during
|
||||
// reads or getting the connection.
|
||||
//
|
||||
// readLoop() and getConn(req *Request, cm connectMethod)
|
||||
// https://github.com/golang/go/blob/master/src/net/http/transport.go
|
||||
//
|
||||
// Send will not close the request.Request's body.
|
||||
func (r *Request) Send() error {
|
||||
defer func() {
|
||||
// Regardless of success or failure of the request trigger the Complete
|
||||
// request handlers.
|
||||
r.Handlers.Complete.Run(r)
|
||||
}()
|
||||
|
||||
if err := r.Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
r.Error = nil
|
||||
r.AttemptTime = time.Now()
|
||||
|
||||
if err := r.Sign(); err != nil {
|
||||
debugLogReqError(r, "Sign Request", false, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.sendRequest(); err == nil {
|
||||
return nil
|
||||
} else if !shouldRetryCancel(r.Error) {
|
||||
return err
|
||||
} else {
|
||||
r.Handlers.Retry.Run(r)
|
||||
r.Handlers.AfterRetry.Run(r)
|
||||
|
||||
if r.Error != nil || !aws.BoolValue(r.Retryable) {
|
||||
return r.Error
|
||||
}
|
||||
|
||||
r.prepareRetry()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Request) prepareRetry() {
|
||||
if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
|
||||
r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
|
||||
r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
|
||||
}
|
||||
|
||||
// The previous http.Request will have a reference to the r.Body
|
||||
// and the HTTP Client's Transport may still be reading from
|
||||
// the request's body even though the Client's Do returned.
|
||||
r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil)
|
||||
r.ResetBody()
|
||||
|
||||
// Closing response body to ensure that no response body is leaked
|
||||
// between retry attempts.
|
||||
if r.HTTPResponse != nil && r.HTTPResponse.Body != nil {
|
||||
r.HTTPResponse.Body.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Request) sendRequest() (sendErr error) {
|
||||
defer r.Handlers.CompleteAttempt.Run(r)
|
||||
|
||||
r.Retryable = nil
|
||||
r.Handlers.Send.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Send Request", r.WillRetry(), r.Error)
|
||||
return r.Error
|
||||
}
|
||||
|
||||
r.Handlers.UnmarshalMeta.Run(r)
|
||||
r.Handlers.ValidateResponse.Run(r)
|
||||
if r.Error != nil {
|
||||
r.Handlers.UnmarshalError.Run(r)
|
||||
debugLogReqError(r, "Validate Response", r.WillRetry(), r.Error)
|
||||
return r.Error
|
||||
}
|
||||
|
||||
r.Handlers.Unmarshal.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Unmarshal Response", r.WillRetry(), r.Error)
|
||||
return r.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// copy will copy a request which will allow for local manipulation of the
|
||||
// request.
|
||||
func (r *Request) copy() *Request {
|
||||
req := &Request{}
|
||||
*req = *r
|
||||
req.Handlers = r.Handlers.Copy()
|
||||
op := *r.Operation
|
||||
req.Operation = &op
|
||||
return req
|
||||
}
|
||||
|
||||
// AddToUserAgent adds the string to the end of the request's current user agent.
|
||||
func AddToUserAgent(r *Request, s string) {
|
||||
curUA := r.HTTPRequest.Header.Get("User-Agent")
|
||||
if len(curUA) > 0 {
|
||||
s = curUA + " " + s
|
||||
}
|
||||
r.HTTPRequest.Header.Set("User-Agent", s)
|
||||
}
|
||||
|
||||
type temporary interface {
|
||||
Temporary() bool
|
||||
}
|
||||
|
||||
func shouldRetryCancel(err error) bool {
|
||||
switch err := err.(type) {
|
||||
case awserr.Error:
|
||||
if err.Code() == CanceledErrorCode {
|
||||
return false
|
||||
}
|
||||
return shouldRetryCancel(err.OrigErr())
|
||||
case *url.Error:
|
||||
if strings.Contains(err.Error(), "connection refused") {
|
||||
// Refused connections should be retried as the service may not yet
|
||||
// be running on the port. Go TCP dial considers refused
|
||||
// connections as not temporary.
|
||||
return true
|
||||
}
|
||||
// *url.Error only implements Temporary after golang 1.6 but since
|
||||
// url.Error only wraps the error:
|
||||
return shouldRetryCancel(err.Err)
|
||||
case temporary:
|
||||
// If the error is temporary, we want to allow continuation of the
|
||||
// retry process
|
||||
return err.Temporary()
|
||||
case nil:
|
||||
// `awserr.Error.OrigErr()` can be nil, meaning there was an error but
|
||||
// because we don't know the cause, it is marked as retriable. See
|
||||
// TestRequest4xxUnretryable for an example.
|
||||
return true
|
||||
default:
|
||||
switch err.Error() {
|
||||
case "net/http: request canceled",
|
||||
"net/http: request canceled while waiting for connection":
|
||||
// known 1.5 error case when an http request is cancelled
|
||||
return false
|
||||
}
|
||||
// here we don't know the error; so we allow a retry.
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// SanitizeHostForHeader removes default port from host and updates request.Host
|
||||
func SanitizeHostForHeader(r *http.Request) {
|
||||
host := getHost(r)
|
||||
port := portOnly(host)
|
||||
if port != "" && isDefaultPort(r.URL.Scheme, port) {
|
||||
r.Host = stripPort(host)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns host from request
|
||||
func getHost(r *http.Request) string {
|
||||
if r.Host != "" {
|
||||
return r.Host
|
||||
}
|
||||
|
||||
return r.URL.Host
|
||||
}
|
||||
|
||||
// Hostname returns u.Host, without any port number.
|
||||
//
|
||||
// If Host is an IPv6 literal with a port number, Hostname returns the
|
||||
// IPv6 literal without the square brackets. IPv6 literals may include
|
||||
// a zone identifier.
|
||||
//
|
||||
// Copied from the Go 1.8 standard library (net/url)
|
||||
func stripPort(hostport string) string {
|
||||
colon := strings.IndexByte(hostport, ':')
|
||||
if colon == -1 {
|
||||
return hostport
|
||||
}
|
||||
if i := strings.IndexByte(hostport, ']'); i != -1 {
|
||||
return strings.TrimPrefix(hostport[:i], "[")
|
||||
}
|
||||
return hostport[:colon]
|
||||
}
|
||||
|
||||
// Port returns the port part of u.Host, without the leading colon.
|
||||
// If u.Host doesn't contain a port, Port returns an empty string.
|
||||
//
|
||||
// Copied from the Go 1.8 standard library (net/url)
|
||||
func portOnly(hostport string) string {
|
||||
colon := strings.IndexByte(hostport, ':')
|
||||
if colon == -1 {
|
||||
return ""
|
||||
}
|
||||
if i := strings.Index(hostport, "]:"); i != -1 {
|
||||
return hostport[i+len("]:"):]
|
||||
}
|
||||
if strings.Contains(hostport, "]") {
|
||||
return ""
|
||||
}
|
||||
return hostport[colon+len(":"):]
|
||||
}
|
||||
|
||||
// Returns true if the specified URI is using the standard port
|
||||
// (i.e. port 80 for HTTP URIs or 443 for HTTPS URIs)
|
||||
func isDefaultPort(scheme, port string) bool {
|
||||
if port == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
lowerCaseScheme := strings.ToLower(scheme)
|
||||
if (lowerCaseScheme == "http" && port == "80") || (lowerCaseScheme == "https" && port == "443") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
39
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go
generated
vendored
Executable file
39
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go
generated
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
// +build !go1.8
|
||||
|
||||
package request
|
||||
|
||||
import "io"
|
||||
|
||||
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
|
||||
// and Close always returns nil. It can be used in an outgoing client
|
||||
// request to explicitly signal that a request has zero bytes.
|
||||
// An alternative, however, is to simply set Request.Body to nil.
|
||||
//
|
||||
// Copy of Go 1.8 NoBody type from net/http/http.go
|
||||
type noBody struct{}
|
||||
|
||||
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
|
||||
func (noBody) Close() error { return nil }
|
||||
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
|
||||
|
||||
// NoBody is an empty reader that will trigger the Go HTTP client to not include
|
||||
// and body in the HTTP request.
|
||||
var NoBody = noBody{}
|
||||
|
||||
// ResetBody rewinds the request body back to its starting position, and
|
||||
// sets the HTTP Request body reference. When the body is read prior
|
||||
// to being sent in the HTTP request it will need to be rewound.
|
||||
//
|
||||
// ResetBody will automatically be called by the SDK's build handler, but if
|
||||
// the request is being used directly ResetBody must be called before the request
|
||||
// is Sent. SetStringBody, SetBufferBody, and SetReaderBody will automatically
|
||||
// call ResetBody.
|
||||
func (r *Request) ResetBody() {
|
||||
body, err := r.getNextRequestBody()
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return
|
||||
}
|
||||
|
||||
r.HTTPRequest.Body = body
|
||||
}
|
||||
33
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go
generated
vendored
Executable file
33
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go
generated
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
// +build go1.8
|
||||
|
||||
package request
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// NoBody is a http.NoBody reader instructing Go HTTP client to not include
|
||||
// and body in the HTTP request.
|
||||
var NoBody = http.NoBody
|
||||
|
||||
// ResetBody rewinds the request body back to its starting position, and
|
||||
// sets the HTTP Request body reference. When the body is read prior
|
||||
// to being sent in the HTTP request it will need to be rewound.
|
||||
//
|
||||
// ResetBody will automatically be called by the SDK's build handler, but if
|
||||
// the request is being used directly ResetBody must be called before the request
|
||||
// is Sent. SetStringBody, SetBufferBody, and SetReaderBody will automatically
|
||||
// call ResetBody.
|
||||
//
|
||||
// Will also set the Go 1.8's http.Request.GetBody member to allow retrying
|
||||
// PUT/POST redirects.
|
||||
func (r *Request) ResetBody() {
|
||||
body, err := r.getNextRequestBody()
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return
|
||||
}
|
||||
|
||||
r.HTTPRequest.Body = body
|
||||
r.HTTPRequest.GetBody = r.getNextRequestBody
|
||||
}
|
||||
14
vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go
generated
vendored
Executable file
14
vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go
generated
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
// +build go1.7
|
||||
|
||||
package request
|
||||
|
||||
import "github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
// setContext updates the Request to use the passed in context for cancellation.
|
||||
// Context will also be used for request retry delay.
|
||||
//
|
||||
// Creates shallow copy of the http.Request with the WithContext method.
|
||||
func setRequestContext(r *Request, ctx aws.Context) {
|
||||
r.context = ctx
|
||||
r.HTTPRequest = r.HTTPRequest.WithContext(ctx)
|
||||
}
|
||||
14
vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go
generated
vendored
Executable file
14
vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go
generated
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
// +build !go1.7
|
||||
|
||||
package request
|
||||
|
||||
import "github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
// setContext updates the Request to use the passed in context for cancellation.
|
||||
// Context will also be used for request retry delay.
|
||||
//
|
||||
// Creates shallow copy of the http.Request with the WithContext method.
|
||||
func setRequestContext(r *Request, ctx aws.Context) {
|
||||
r.context = ctx
|
||||
r.HTTPRequest.Cancel = ctx.Done()
|
||||
}
|
||||
264
vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
generated
vendored
Executable file
264
vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
generated
vendored
Executable file
@@ -0,0 +1,264 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
)
|
||||
|
||||
// A Pagination provides paginating of SDK API operations which are paginatable.
|
||||
// Generally you should not use this type directly, but use the "Pages" API
|
||||
// operations method to automatically perform pagination for you. Such as,
|
||||
// "S3.ListObjectsPages", and "S3.ListObjectsPagesWithContext" methods.
|
||||
//
|
||||
// Pagination differs from a Paginator type in that pagination is the type that
|
||||
// does the pagination between API operations, and Paginator defines the
|
||||
// configuration that will be used per page request.
|
||||
//
|
||||
// cont := true
|
||||
// for p.Next() && cont {
|
||||
// data := p.Page().(*s3.ListObjectsOutput)
|
||||
// // process the page's data
|
||||
// }
|
||||
// return p.Err()
|
||||
//
|
||||
// See service client API operation Pages methods for examples how the SDK will
|
||||
// use the Pagination type.
|
||||
type Pagination struct {
|
||||
// Function to return a Request value for each pagination request.
|
||||
// Any configuration or handlers that need to be applied to the request
|
||||
// prior to getting the next page should be done here before the request
|
||||
// returned.
|
||||
//
|
||||
// NewRequest should always be built from the same API operations. It is
|
||||
// undefined if different API operations are returned on subsequent calls.
|
||||
NewRequest func() (*Request, error)
|
||||
// EndPageOnSameToken, when enabled, will allow the paginator to stop on
|
||||
// token that are the same as its previous tokens.
|
||||
EndPageOnSameToken bool
|
||||
|
||||
started bool
|
||||
prevTokens []interface{}
|
||||
nextTokens []interface{}
|
||||
|
||||
err error
|
||||
curPage interface{}
|
||||
}
|
||||
|
||||
// HasNextPage will return true if Pagination is able to determine that the API
|
||||
// operation has additional pages. False will be returned if there are no more
|
||||
// pages remaining.
|
||||
//
|
||||
// Will always return true if Next has not been called yet.
|
||||
func (p *Pagination) HasNextPage() bool {
|
||||
if !p.started {
|
||||
return true
|
||||
}
|
||||
|
||||
hasNextPage := len(p.nextTokens) != 0
|
||||
if p.EndPageOnSameToken {
|
||||
return hasNextPage && !awsutil.DeepEqual(p.nextTokens, p.prevTokens)
|
||||
}
|
||||
return hasNextPage
|
||||
}
|
||||
|
||||
// Err returns the error Pagination encountered when retrieving the next page.
|
||||
func (p *Pagination) Err() error {
|
||||
return p.err
|
||||
}
|
||||
|
||||
// Page returns the current page. Page should only be called after a successful
|
||||
// call to Next. It is undefined what Page will return if Page is called after
|
||||
// Next returns false.
|
||||
func (p *Pagination) Page() interface{} {
|
||||
return p.curPage
|
||||
}
|
||||
|
||||
// Next will attempt to retrieve the next page for the API operation. When a page
|
||||
// is retrieved true will be returned. If the page cannot be retrieved, or there
|
||||
// are no more pages false will be returned.
|
||||
//
|
||||
// Use the Page method to retrieve the current page data. The data will need
|
||||
// to be cast to the API operation's output type.
|
||||
//
|
||||
// Use the Err method to determine if an error occurred if Page returns false.
|
||||
func (p *Pagination) Next() bool {
|
||||
if !p.HasNextPage() {
|
||||
return false
|
||||
}
|
||||
|
||||
req, err := p.NewRequest()
|
||||
if err != nil {
|
||||
p.err = err
|
||||
return false
|
||||
}
|
||||
|
||||
if p.started {
|
||||
for i, intok := range req.Operation.InputTokens {
|
||||
awsutil.SetValueAtPath(req.Params, intok, p.nextTokens[i])
|
||||
}
|
||||
}
|
||||
p.started = true
|
||||
|
||||
err = req.Send()
|
||||
if err != nil {
|
||||
p.err = err
|
||||
return false
|
||||
}
|
||||
|
||||
p.prevTokens = p.nextTokens
|
||||
p.nextTokens = req.nextPageTokens()
|
||||
p.curPage = req.Data
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// A Paginator is the configuration data that defines how an API operation
|
||||
// should be paginated. This type is used by the API service models to define
|
||||
// the generated pagination config for service APIs.
|
||||
//
|
||||
// The Pagination type is what provides iterating between pages of an API. It
|
||||
// is only used to store the token metadata the SDK should use for performing
|
||||
// pagination.
|
||||
type Paginator struct {
|
||||
InputTokens []string
|
||||
OutputTokens []string
|
||||
LimitToken string
|
||||
TruncationToken string
|
||||
}
|
||||
|
||||
// nextPageTokens returns the tokens to use when asking for the next page of data.
|
||||
func (r *Request) nextPageTokens() []interface{} {
|
||||
if r.Operation.Paginator == nil {
|
||||
return nil
|
||||
}
|
||||
if r.Operation.TruncationToken != "" {
|
||||
tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken)
|
||||
if len(tr) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch v := tr[0].(type) {
|
||||
case *bool:
|
||||
if !aws.BoolValue(v) {
|
||||
return nil
|
||||
}
|
||||
case bool:
|
||||
if v == false {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokens := []interface{}{}
|
||||
tokenAdded := false
|
||||
for _, outToken := range r.Operation.OutputTokens {
|
||||
vs, _ := awsutil.ValuesAtPath(r.Data, outToken)
|
||||
if len(vs) == 0 {
|
||||
tokens = append(tokens, nil)
|
||||
continue
|
||||
}
|
||||
v := vs[0]
|
||||
|
||||
switch tv := v.(type) {
|
||||
case *string:
|
||||
if len(aws.StringValue(tv)) == 0 {
|
||||
tokens = append(tokens, nil)
|
||||
continue
|
||||
}
|
||||
case string:
|
||||
if len(tv) == 0 {
|
||||
tokens = append(tokens, nil)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
tokenAdded = true
|
||||
tokens = append(tokens, v)
|
||||
}
|
||||
if !tokenAdded {
|
||||
return nil
|
||||
}
|
||||
|
||||
return tokens
|
||||
}
|
||||
|
||||
// Ensure a deprecated item is only logged once instead of each time its used.
|
||||
func logDeprecatedf(logger aws.Logger, flag *int32, msg string) {
|
||||
if logger == nil {
|
||||
return
|
||||
}
|
||||
if atomic.CompareAndSwapInt32(flag, 0, 1) {
|
||||
logger.Log(msg)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
logDeprecatedHasNextPage int32
|
||||
logDeprecatedNextPage int32
|
||||
logDeprecatedEachPage int32
|
||||
)
|
||||
|
||||
// HasNextPage returns true if this request has more pages of data available.
|
||||
//
|
||||
// Deprecated Use Pagination type for configurable pagination of API operations
|
||||
func (r *Request) HasNextPage() bool {
|
||||
logDeprecatedf(r.Config.Logger, &logDeprecatedHasNextPage,
|
||||
"Request.HasNextPage deprecated. Use Pagination type for configurable pagination of API operations")
|
||||
|
||||
return len(r.nextPageTokens()) > 0
|
||||
}
|
||||
|
||||
// NextPage returns a new Request that can be executed to return the next
|
||||
// page of result data. Call .Send() on this request to execute it.
|
||||
//
|
||||
// Deprecated Use Pagination type for configurable pagination of API operations
|
||||
func (r *Request) NextPage() *Request {
|
||||
logDeprecatedf(r.Config.Logger, &logDeprecatedNextPage,
|
||||
"Request.NextPage deprecated. Use Pagination type for configurable pagination of API operations")
|
||||
|
||||
tokens := r.nextPageTokens()
|
||||
if len(tokens) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface()
|
||||
nr := New(r.Config, r.ClientInfo, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data)
|
||||
for i, intok := range nr.Operation.InputTokens {
|
||||
awsutil.SetValueAtPath(nr.Params, intok, tokens[i])
|
||||
}
|
||||
return nr
|
||||
}
|
||||
|
||||
// EachPage iterates over each page of a paginated request object. The fn
|
||||
// parameter should be a function with the following sample signature:
|
||||
//
|
||||
// func(page *T, lastPage bool) bool {
|
||||
// return true // return false to stop iterating
|
||||
// }
|
||||
//
|
||||
// Where "T" is the structure type matching the output structure of the given
|
||||
// operation. For example, a request object generated by
|
||||
// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput
|
||||
// as the structure "T". The lastPage value represents whether the page is
|
||||
// the last page of data or not. The return value of this function should
|
||||
// return true to keep iterating or false to stop.
|
||||
//
|
||||
// Deprecated Use Pagination type for configurable pagination of API operations
|
||||
func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
|
||||
logDeprecatedf(r.Config.Logger, &logDeprecatedEachPage,
|
||||
"Request.EachPage deprecated. Use Pagination type for configurable pagination of API operations")
|
||||
|
||||
for page := r; page != nil; page = page.NextPage() {
|
||||
if err := page.Send(); err != nil {
|
||||
return err
|
||||
}
|
||||
if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage {
|
||||
return page.Error
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
163
vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
generated
vendored
Executable file
163
vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
generated
vendored
Executable file
@@ -0,0 +1,163 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
)
|
||||
|
||||
// Retryer is an interface to control retry logic for a given service.
|
||||
// The default implementation used by most services is the client.DefaultRetryer
|
||||
// structure, which contains basic retry logic using exponential backoff.
|
||||
type Retryer interface {
|
||||
RetryRules(*Request) time.Duration
|
||||
ShouldRetry(*Request) bool
|
||||
MaxRetries() int
|
||||
}
|
||||
|
||||
// WithRetryer sets a config Retryer value to the given Config returning it
|
||||
// for chaining.
|
||||
func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config {
|
||||
cfg.Retryer = retryer
|
||||
return cfg
|
||||
}
|
||||
|
||||
// retryableCodes is a collection of service response codes which are retry-able
|
||||
// without any further action.
|
||||
var retryableCodes = map[string]struct{}{
|
||||
"RequestError": {},
|
||||
"RequestTimeout": {},
|
||||
ErrCodeResponseTimeout: {},
|
||||
"RequestTimeoutException": {}, // Glacier's flavor of RequestTimeout
|
||||
}
|
||||
|
||||
var throttleCodes = map[string]struct{}{
|
||||
"ProvisionedThroughputExceededException": {},
|
||||
"Throttling": {},
|
||||
"ThrottlingException": {},
|
||||
"RequestLimitExceeded": {},
|
||||
"RequestThrottled": {},
|
||||
"RequestThrottledException": {},
|
||||
"TooManyRequestsException": {}, // Lambda functions
|
||||
"PriorRequestNotComplete": {}, // Route53
|
||||
"TransactionInProgressException": {},
|
||||
}
|
||||
|
||||
// credsExpiredCodes is a collection of error codes which signify the credentials
|
||||
// need to be refreshed. Expired tokens require refreshing of credentials, and
|
||||
// resigning before the request can be retried.
|
||||
var credsExpiredCodes = map[string]struct{}{
|
||||
"ExpiredToken": {},
|
||||
"ExpiredTokenException": {},
|
||||
"RequestExpired": {}, // EC2 Only
|
||||
}
|
||||
|
||||
func isCodeThrottle(code string) bool {
|
||||
_, ok := throttleCodes[code]
|
||||
return ok
|
||||
}
|
||||
|
||||
func isCodeRetryable(code string) bool {
|
||||
if _, ok := retryableCodes[code]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
return isCodeExpiredCreds(code)
|
||||
}
|
||||
|
||||
func isCodeExpiredCreds(code string) bool {
|
||||
_, ok := credsExpiredCodes[code]
|
||||
return ok
|
||||
}
|
||||
|
||||
var validParentCodes = map[string]struct{}{
|
||||
ErrCodeSerialization: {},
|
||||
ErrCodeRead: {},
|
||||
}
|
||||
|
||||
type temporaryError interface {
|
||||
Temporary() bool
|
||||
}
|
||||
|
||||
func isNestedErrorRetryable(parentErr awserr.Error) bool {
|
||||
if parentErr == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if _, ok := validParentCodes[parentErr.Code()]; !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
err := parentErr.OrigErr()
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if aerr, ok := err.(awserr.Error); ok {
|
||||
return isCodeRetryable(aerr.Code())
|
||||
}
|
||||
|
||||
if t, ok := err.(temporaryError); ok {
|
||||
return t.Temporary() || isErrConnectionReset(err)
|
||||
}
|
||||
|
||||
return isErrConnectionReset(err)
|
||||
}
|
||||
|
||||
// IsErrorRetryable returns whether the error is retryable, based on its Code.
|
||||
// Returns false if error is nil.
|
||||
func IsErrorRetryable(err error) bool {
|
||||
if err != nil {
|
||||
if aerr, ok := err.(awserr.Error); ok {
|
||||
return isCodeRetryable(aerr.Code()) || isNestedErrorRetryable(aerr)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsErrorThrottle returns whether the error is to be throttled based on its code.
|
||||
// Returns false if error is nil.
|
||||
func IsErrorThrottle(err error) bool {
|
||||
if err != nil {
|
||||
if aerr, ok := err.(awserr.Error); ok {
|
||||
return isCodeThrottle(aerr.Code())
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsErrorExpiredCreds returns whether the error code is a credential expiry error.
|
||||
// Returns false if error is nil.
|
||||
func IsErrorExpiredCreds(err error) bool {
|
||||
if err != nil {
|
||||
if aerr, ok := err.(awserr.Error); ok {
|
||||
return isCodeExpiredCreds(aerr.Code())
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsErrorRetryable returns whether the error is retryable, based on its Code.
|
||||
// Returns false if the request has no Error set.
|
||||
//
|
||||
// Alias for the utility function IsErrorRetryable
|
||||
func (r *Request) IsErrorRetryable() bool {
|
||||
return IsErrorRetryable(r.Error)
|
||||
}
|
||||
|
||||
// IsErrorThrottle returns whether the error is to be throttled based on its code.
|
||||
// Returns false if the request has no Error set
|
||||
//
|
||||
// Alias for the utility function IsErrorThrottle
|
||||
func (r *Request) IsErrorThrottle() bool {
|
||||
return IsErrorThrottle(r.Error)
|
||||
}
|
||||
|
||||
// IsErrorExpired returns whether the error code is a credential expiry error.
|
||||
// Returns false if the request has no Error set.
|
||||
//
|
||||
// Alias for the utility function IsErrorExpiredCreds
|
||||
func (r *Request) IsErrorExpired() bool {
|
||||
return IsErrorExpiredCreds(r.Error)
|
||||
}
|
||||
94
vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go
generated
vendored
Executable file
94
vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go
generated
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
)
|
||||
|
||||
var timeoutErr = awserr.New(
|
||||
ErrCodeResponseTimeout,
|
||||
"read on body has reached the timeout limit",
|
||||
nil,
|
||||
)
|
||||
|
||||
type readResult struct {
|
||||
n int
|
||||
err error
|
||||
}
|
||||
|
||||
// timeoutReadCloser will handle body reads that take too long.
|
||||
// We will return a ErrReadTimeout error if a timeout occurs.
|
||||
type timeoutReadCloser struct {
|
||||
reader io.ReadCloser
|
||||
duration time.Duration
|
||||
}
|
||||
|
||||
// Read will spin off a goroutine to call the reader's Read method. We will
|
||||
// select on the timer's channel or the read's channel. Whoever completes first
|
||||
// will be returned.
|
||||
func (r *timeoutReadCloser) Read(b []byte) (int, error) {
|
||||
timer := time.NewTimer(r.duration)
|
||||
c := make(chan readResult, 1)
|
||||
|
||||
go func() {
|
||||
n, err := r.reader.Read(b)
|
||||
timer.Stop()
|
||||
c <- readResult{n: n, err: err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case data := <-c:
|
||||
return data.n, data.err
|
||||
case <-timer.C:
|
||||
return 0, timeoutErr
|
||||
}
|
||||
}
|
||||
|
||||
func (r *timeoutReadCloser) Close() error {
|
||||
return r.reader.Close()
|
||||
}
|
||||
|
||||
const (
|
||||
// HandlerResponseTimeout is what we use to signify the name of the
|
||||
// response timeout handler.
|
||||
HandlerResponseTimeout = "ResponseTimeoutHandler"
|
||||
)
|
||||
|
||||
// adaptToResponseTimeoutError is a handler that will replace any top level error
|
||||
// to a ErrCodeResponseTimeout, if its child is that.
|
||||
func adaptToResponseTimeoutError(req *Request) {
|
||||
if err, ok := req.Error.(awserr.Error); ok {
|
||||
aerr, ok := err.OrigErr().(awserr.Error)
|
||||
if ok && aerr.Code() == ErrCodeResponseTimeout {
|
||||
req.Error = aerr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithResponseReadTimeout is a request option that will wrap the body in a timeout read closer.
|
||||
// This will allow for per read timeouts. If a timeout occurred, we will return the
|
||||
// ErrCodeResponseTimeout.
|
||||
//
|
||||
// svc.PutObjectWithContext(ctx, params, request.WithTimeoutReadCloser(30 * time.Second)
|
||||
func WithResponseReadTimeout(duration time.Duration) Option {
|
||||
return func(r *Request) {
|
||||
|
||||
var timeoutHandler = NamedHandler{
|
||||
HandlerResponseTimeout,
|
||||
func(req *Request) {
|
||||
req.HTTPResponse.Body = &timeoutReadCloser{
|
||||
reader: req.HTTPResponse.Body,
|
||||
duration: duration,
|
||||
}
|
||||
}}
|
||||
|
||||
// remove the handler so we are not stomping over any new durations.
|
||||
r.Handlers.Send.RemoveByName(HandlerResponseTimeout)
|
||||
r.Handlers.Send.PushBackNamed(timeoutHandler)
|
||||
|
||||
r.Handlers.Unmarshal.PushBack(adaptToResponseTimeoutError)
|
||||
r.Handlers.UnmarshalError.PushBack(adaptToResponseTimeoutError)
|
||||
}
|
||||
}
|
||||
286
vendor/github.com/aws/aws-sdk-go/aws/request/validation.go
generated
vendored
Executable file
286
vendor/github.com/aws/aws-sdk-go/aws/request/validation.go
generated
vendored
Executable file
@@ -0,0 +1,286 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
)
|
||||
|
||||
const (
|
||||
// InvalidParameterErrCode is the error code for invalid parameters errors
|
||||
InvalidParameterErrCode = "InvalidParameter"
|
||||
// ParamRequiredErrCode is the error code for required parameter errors
|
||||
ParamRequiredErrCode = "ParamRequiredError"
|
||||
// ParamMinValueErrCode is the error code for fields with too low of a
|
||||
// number value.
|
||||
ParamMinValueErrCode = "ParamMinValueError"
|
||||
// ParamMinLenErrCode is the error code for fields without enough elements.
|
||||
ParamMinLenErrCode = "ParamMinLenError"
|
||||
// ParamMaxLenErrCode is the error code for value being too long.
|
||||
ParamMaxLenErrCode = "ParamMaxLenError"
|
||||
|
||||
// ParamFormatErrCode is the error code for a field with invalid
|
||||
// format or characters.
|
||||
ParamFormatErrCode = "ParamFormatInvalidError"
|
||||
)
|
||||
|
||||
// Validator provides a way for types to perform validation logic on their
|
||||
// input values that external code can use to determine if a type's values
|
||||
// are valid.
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
|
||||
// An ErrInvalidParams provides wrapping of invalid parameter errors found when
|
||||
// validating API operation input parameters.
|
||||
type ErrInvalidParams struct {
|
||||
// Context is the base context of the invalid parameter group.
|
||||
Context string
|
||||
errs []ErrInvalidParam
|
||||
}
|
||||
|
||||
// Add adds a new invalid parameter error to the collection of invalid
|
||||
// parameters. The context of the invalid parameter will be updated to reflect
|
||||
// this collection.
|
||||
func (e *ErrInvalidParams) Add(err ErrInvalidParam) {
|
||||
err.SetContext(e.Context)
|
||||
e.errs = append(e.errs, err)
|
||||
}
|
||||
|
||||
// AddNested adds the invalid parameter errors from another ErrInvalidParams
|
||||
// value into this collection. The nested errors will have their nested context
|
||||
// updated and base context to reflect the merging.
|
||||
//
|
||||
// Use for nested validations errors.
|
||||
func (e *ErrInvalidParams) AddNested(nestedCtx string, nested ErrInvalidParams) {
|
||||
for _, err := range nested.errs {
|
||||
err.SetContext(e.Context)
|
||||
err.AddNestedContext(nestedCtx)
|
||||
e.errs = append(e.errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Len returns the number of invalid parameter errors
|
||||
func (e ErrInvalidParams) Len() int {
|
||||
return len(e.errs)
|
||||
}
|
||||
|
||||
// Code returns the code of the error
|
||||
func (e ErrInvalidParams) Code() string {
|
||||
return InvalidParameterErrCode
|
||||
}
|
||||
|
||||
// Message returns the message of the error
|
||||
func (e ErrInvalidParams) Message() string {
|
||||
return fmt.Sprintf("%d validation error(s) found.", len(e.errs))
|
||||
}
|
||||
|
||||
// Error returns the string formatted form of the invalid parameters.
|
||||
func (e ErrInvalidParams) Error() string {
|
||||
w := &bytes.Buffer{}
|
||||
fmt.Fprintf(w, "%s: %s\n", e.Code(), e.Message())
|
||||
|
||||
for _, err := range e.errs {
|
||||
fmt.Fprintf(w, "- %s\n", err.Message())
|
||||
}
|
||||
|
||||
return w.String()
|
||||
}
|
||||
|
||||
// OrigErr returns the invalid parameters as a awserr.BatchedErrors value
|
||||
func (e ErrInvalidParams) OrigErr() error {
|
||||
return awserr.NewBatchError(
|
||||
InvalidParameterErrCode, e.Message(), e.OrigErrs())
|
||||
}
|
||||
|
||||
// OrigErrs returns a slice of the invalid parameters
|
||||
func (e ErrInvalidParams) OrigErrs() []error {
|
||||
errs := make([]error, len(e.errs))
|
||||
for i := 0; i < len(errs); i++ {
|
||||
errs[i] = e.errs[i]
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// An ErrInvalidParam represents an invalid parameter error type.
|
||||
type ErrInvalidParam interface {
|
||||
awserr.Error
|
||||
|
||||
// Field name the error occurred on.
|
||||
Field() string
|
||||
|
||||
// SetContext updates the context of the error.
|
||||
SetContext(string)
|
||||
|
||||
// AddNestedContext updates the error's context to include a nested level.
|
||||
AddNestedContext(string)
|
||||
}
|
||||
|
||||
type errInvalidParam struct {
|
||||
context string
|
||||
nestedContext string
|
||||
field string
|
||||
code string
|
||||
msg string
|
||||
}
|
||||
|
||||
// Code returns the error code for the type of invalid parameter.
|
||||
func (e *errInvalidParam) Code() string {
|
||||
return e.code
|
||||
}
|
||||
|
||||
// Message returns the reason the parameter was invalid, and its context.
|
||||
func (e *errInvalidParam) Message() string {
|
||||
return fmt.Sprintf("%s, %s.", e.msg, e.Field())
|
||||
}
|
||||
|
||||
// Error returns the string version of the invalid parameter error.
|
||||
func (e *errInvalidParam) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.code, e.Message())
|
||||
}
|
||||
|
||||
// OrigErr returns nil, Implemented for awserr.Error interface.
|
||||
func (e *errInvalidParam) OrigErr() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Field Returns the field and context the error occurred.
|
||||
func (e *errInvalidParam) Field() string {
|
||||
field := e.context
|
||||
if len(field) > 0 {
|
||||
field += "."
|
||||
}
|
||||
if len(e.nestedContext) > 0 {
|
||||
field += fmt.Sprintf("%s.", e.nestedContext)
|
||||
}
|
||||
field += e.field
|
||||
|
||||
return field
|
||||
}
|
||||
|
||||
// SetContext updates the base context of the error.
|
||||
func (e *errInvalidParam) SetContext(ctx string) {
|
||||
e.context = ctx
|
||||
}
|
||||
|
||||
// AddNestedContext prepends a context to the field's path.
|
||||
func (e *errInvalidParam) AddNestedContext(ctx string) {
|
||||
if len(e.nestedContext) == 0 {
|
||||
e.nestedContext = ctx
|
||||
} else {
|
||||
e.nestedContext = fmt.Sprintf("%s.%s", ctx, e.nestedContext)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// An ErrParamRequired represents an required parameter error.
|
||||
type ErrParamRequired struct {
|
||||
errInvalidParam
|
||||
}
|
||||
|
||||
// NewErrParamRequired creates a new required parameter error.
|
||||
func NewErrParamRequired(field string) *ErrParamRequired {
|
||||
return &ErrParamRequired{
|
||||
errInvalidParam{
|
||||
code: ParamRequiredErrCode,
|
||||
field: field,
|
||||
msg: fmt.Sprintf("missing required field"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// An ErrParamMinValue represents a minimum value parameter error.
|
||||
type ErrParamMinValue struct {
|
||||
errInvalidParam
|
||||
min float64
|
||||
}
|
||||
|
||||
// NewErrParamMinValue creates a new minimum value parameter error.
|
||||
func NewErrParamMinValue(field string, min float64) *ErrParamMinValue {
|
||||
return &ErrParamMinValue{
|
||||
errInvalidParam: errInvalidParam{
|
||||
code: ParamMinValueErrCode,
|
||||
field: field,
|
||||
msg: fmt.Sprintf("minimum field value of %v", min),
|
||||
},
|
||||
min: min,
|
||||
}
|
||||
}
|
||||
|
||||
// MinValue returns the field's require minimum value.
|
||||
//
|
||||
// float64 is returned for both int and float min values.
|
||||
func (e *ErrParamMinValue) MinValue() float64 {
|
||||
return e.min
|
||||
}
|
||||
|
||||
// An ErrParamMinLen represents a minimum length parameter error.
|
||||
type ErrParamMinLen struct {
|
||||
errInvalidParam
|
||||
min int
|
||||
}
|
||||
|
||||
// NewErrParamMinLen creates a new minimum length parameter error.
|
||||
func NewErrParamMinLen(field string, min int) *ErrParamMinLen {
|
||||
return &ErrParamMinLen{
|
||||
errInvalidParam: errInvalidParam{
|
||||
code: ParamMinLenErrCode,
|
||||
field: field,
|
||||
msg: fmt.Sprintf("minimum field size of %v", min),
|
||||
},
|
||||
min: min,
|
||||
}
|
||||
}
|
||||
|
||||
// MinLen returns the field's required minimum length.
|
||||
func (e *ErrParamMinLen) MinLen() int {
|
||||
return e.min
|
||||
}
|
||||
|
||||
// An ErrParamMaxLen represents a maximum length parameter error.
|
||||
type ErrParamMaxLen struct {
|
||||
errInvalidParam
|
||||
max int
|
||||
}
|
||||
|
||||
// NewErrParamMaxLen creates a new maximum length parameter error.
|
||||
func NewErrParamMaxLen(field string, max int, value string) *ErrParamMaxLen {
|
||||
return &ErrParamMaxLen{
|
||||
errInvalidParam: errInvalidParam{
|
||||
code: ParamMaxLenErrCode,
|
||||
field: field,
|
||||
msg: fmt.Sprintf("maximum size of %v, %v", max, value),
|
||||
},
|
||||
max: max,
|
||||
}
|
||||
}
|
||||
|
||||
// MaxLen returns the field's required minimum length.
|
||||
func (e *ErrParamMaxLen) MaxLen() int {
|
||||
return e.max
|
||||
}
|
||||
|
||||
// An ErrParamFormat represents a invalid format parameter error.
|
||||
type ErrParamFormat struct {
|
||||
errInvalidParam
|
||||
format string
|
||||
}
|
||||
|
||||
// NewErrParamFormat creates a new invalid format parameter error.
|
||||
func NewErrParamFormat(field string, format, value string) *ErrParamFormat {
|
||||
return &ErrParamFormat{
|
||||
errInvalidParam: errInvalidParam{
|
||||
code: ParamFormatErrCode,
|
||||
field: field,
|
||||
msg: fmt.Sprintf("format %v, %v", format, value),
|
||||
},
|
||||
format: format,
|
||||
}
|
||||
}
|
||||
|
||||
// Format returns the field's required format.
|
||||
func (e *ErrParamFormat) Format() string {
|
||||
return e.format
|
||||
}
|
||||
295
vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go
generated
vendored
Executable file
295
vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go
generated
vendored
Executable file
@@ -0,0 +1,295 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
)
|
||||
|
||||
// WaiterResourceNotReadyErrorCode is the error code returned by a waiter when
|
||||
// the waiter's max attempts have been exhausted.
|
||||
const WaiterResourceNotReadyErrorCode = "ResourceNotReady"
|
||||
|
||||
// A WaiterOption is a function that will update the Waiter value's fields to
|
||||
// configure the waiter.
|
||||
type WaiterOption func(*Waiter)
|
||||
|
||||
// WithWaiterMaxAttempts returns the maximum number of times the waiter should
|
||||
// attempt to check the resource for the target state.
|
||||
func WithWaiterMaxAttempts(max int) WaiterOption {
|
||||
return func(w *Waiter) {
|
||||
w.MaxAttempts = max
|
||||
}
|
||||
}
|
||||
|
||||
// WaiterDelay will return a delay the waiter should pause between attempts to
|
||||
// check the resource state. The passed in attempt is the number of times the
|
||||
// Waiter has checked the resource state.
|
||||
//
|
||||
// Attempt is the number of attempts the Waiter has made checking the resource
|
||||
// state.
|
||||
type WaiterDelay func(attempt int) time.Duration
|
||||
|
||||
// ConstantWaiterDelay returns a WaiterDelay that will always return a constant
|
||||
// delay the waiter should use between attempts. It ignores the number of
|
||||
// attempts made.
|
||||
func ConstantWaiterDelay(delay time.Duration) WaiterDelay {
|
||||
return func(attempt int) time.Duration {
|
||||
return delay
|
||||
}
|
||||
}
|
||||
|
||||
// WithWaiterDelay will set the Waiter to use the WaiterDelay passed in.
|
||||
func WithWaiterDelay(delayer WaiterDelay) WaiterOption {
|
||||
return func(w *Waiter) {
|
||||
w.Delay = delayer
|
||||
}
|
||||
}
|
||||
|
||||
// WithWaiterLogger returns a waiter option to set the logger a waiter
|
||||
// should use to log warnings and errors to.
|
||||
func WithWaiterLogger(logger aws.Logger) WaiterOption {
|
||||
return func(w *Waiter) {
|
||||
w.Logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
// WithWaiterRequestOptions returns a waiter option setting the request
|
||||
// options for each request the waiter makes. Appends to waiter's request
|
||||
// options already set.
|
||||
func WithWaiterRequestOptions(opts ...Option) WaiterOption {
|
||||
return func(w *Waiter) {
|
||||
w.RequestOptions = append(w.RequestOptions, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// A Waiter provides the functionality to perform a blocking call which will
|
||||
// wait for a resource state to be satisfied by a service.
|
||||
//
|
||||
// This type should not be used directly. The API operations provided in the
|
||||
// service packages prefixed with "WaitUntil" should be used instead.
|
||||
type Waiter struct {
|
||||
Name string
|
||||
Acceptors []WaiterAcceptor
|
||||
Logger aws.Logger
|
||||
|
||||
MaxAttempts int
|
||||
Delay WaiterDelay
|
||||
|
||||
RequestOptions []Option
|
||||
NewRequest func([]Option) (*Request, error)
|
||||
SleepWithContext func(aws.Context, time.Duration) error
|
||||
}
|
||||
|
||||
// ApplyOptions updates the waiter with the list of waiter options provided.
|
||||
func (w *Waiter) ApplyOptions(opts ...WaiterOption) {
|
||||
for _, fn := range opts {
|
||||
fn(w)
|
||||
}
|
||||
}
|
||||
|
||||
// WaiterState are states the waiter uses based on WaiterAcceptor definitions
|
||||
// to identify if the resource state the waiter is waiting on has occurred.
|
||||
type WaiterState int
|
||||
|
||||
// String returns the string representation of the waiter state.
|
||||
func (s WaiterState) String() string {
|
||||
switch s {
|
||||
case SuccessWaiterState:
|
||||
return "success"
|
||||
case FailureWaiterState:
|
||||
return "failure"
|
||||
case RetryWaiterState:
|
||||
return "retry"
|
||||
default:
|
||||
return "unknown waiter state"
|
||||
}
|
||||
}
|
||||
|
||||
// States the waiter acceptors will use to identify target resource states.
|
||||
const (
|
||||
SuccessWaiterState WaiterState = iota // waiter successful
|
||||
FailureWaiterState // waiter failed
|
||||
RetryWaiterState // waiter needs to be retried
|
||||
)
|
||||
|
||||
// WaiterMatchMode is the mode that the waiter will use to match the WaiterAcceptor
|
||||
// definition's Expected attribute.
|
||||
type WaiterMatchMode int
|
||||
|
||||
// Modes the waiter will use when inspecting API response to identify target
|
||||
// resource states.
|
||||
const (
|
||||
PathAllWaiterMatch WaiterMatchMode = iota // match on all paths
|
||||
PathWaiterMatch // match on specific path
|
||||
PathAnyWaiterMatch // match on any path
|
||||
PathListWaiterMatch // match on list of paths
|
||||
StatusWaiterMatch // match on status code
|
||||
ErrorWaiterMatch // match on error
|
||||
)
|
||||
|
||||
// String returns the string representation of the waiter match mode.
|
||||
func (m WaiterMatchMode) String() string {
|
||||
switch m {
|
||||
case PathAllWaiterMatch:
|
||||
return "pathAll"
|
||||
case PathWaiterMatch:
|
||||
return "path"
|
||||
case PathAnyWaiterMatch:
|
||||
return "pathAny"
|
||||
case PathListWaiterMatch:
|
||||
return "pathList"
|
||||
case StatusWaiterMatch:
|
||||
return "status"
|
||||
case ErrorWaiterMatch:
|
||||
return "error"
|
||||
default:
|
||||
return "unknown waiter match mode"
|
||||
}
|
||||
}
|
||||
|
||||
// WaitWithContext will make requests for the API operation using NewRequest to
|
||||
// build API requests. The request's response will be compared against the
|
||||
// Waiter's Acceptors to determine the successful state of the resource the
|
||||
// waiter is inspecting.
|
||||
//
|
||||
// The passed in context must not be nil. If it is nil a panic will occur. The
|
||||
// Context will be used to cancel the waiter's pending requests and retry delays.
|
||||
// Use aws.BackgroundContext if no context is available.
|
||||
//
|
||||
// The waiter will continue until the target state defined by the Acceptors,
|
||||
// or the max attempts expires.
|
||||
//
|
||||
// Will return the WaiterResourceNotReadyErrorCode error code if the waiter's
|
||||
// retryer ShouldRetry returns false. This normally will happen when the max
|
||||
// wait attempts expires.
|
||||
func (w Waiter) WaitWithContext(ctx aws.Context) error {
|
||||
|
||||
for attempt := 1; ; attempt++ {
|
||||
req, err := w.NewRequest(w.RequestOptions)
|
||||
if err != nil {
|
||||
waiterLogf(w.Logger, "unable to create request %v", err)
|
||||
return err
|
||||
}
|
||||
req.Handlers.Build.PushBack(MakeAddToUserAgentFreeFormHandler("Waiter"))
|
||||
err = req.Send()
|
||||
|
||||
// See if any of the acceptors match the request's response, or error
|
||||
for _, a := range w.Acceptors {
|
||||
if matched, matchErr := a.match(w.Name, w.Logger, req, err); matched {
|
||||
return matchErr
|
||||
}
|
||||
}
|
||||
|
||||
// The Waiter should only check the resource state MaxAttempts times
|
||||
// This is here instead of in the for loop above to prevent delaying
|
||||
// unnecessary when the waiter will not retry.
|
||||
if attempt == w.MaxAttempts {
|
||||
break
|
||||
}
|
||||
|
||||
// Delay to wait before inspecting the resource again
|
||||
delay := w.Delay(attempt)
|
||||
if sleepFn := req.Config.SleepDelay; sleepFn != nil {
|
||||
// Support SleepDelay for backwards compatibility and testing
|
||||
sleepFn(delay)
|
||||
} else {
|
||||
sleepCtxFn := w.SleepWithContext
|
||||
if sleepCtxFn == nil {
|
||||
sleepCtxFn = aws.SleepWithContext
|
||||
}
|
||||
|
||||
if err := sleepCtxFn(ctx, delay); err != nil {
|
||||
return awserr.New(CanceledErrorCode, "waiter context canceled", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return awserr.New(WaiterResourceNotReadyErrorCode, "exceeded wait attempts", nil)
|
||||
}
|
||||
|
||||
// A WaiterAcceptor provides the information needed to wait for an API operation
|
||||
// to complete.
|
||||
type WaiterAcceptor struct {
|
||||
State WaiterState
|
||||
Matcher WaiterMatchMode
|
||||
Argument string
|
||||
Expected interface{}
|
||||
}
|
||||
|
||||
// match returns if the acceptor found a match with the passed in request
|
||||
// or error. True is returned if the acceptor made a match, error is returned
|
||||
// if there was an error attempting to perform the match.
|
||||
func (a *WaiterAcceptor) match(name string, l aws.Logger, req *Request, err error) (bool, error) {
|
||||
result := false
|
||||
var vals []interface{}
|
||||
|
||||
switch a.Matcher {
|
||||
case PathAllWaiterMatch, PathWaiterMatch:
|
||||
// Require all matches to be equal for result to match
|
||||
vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
|
||||
if len(vals) == 0 {
|
||||
break
|
||||
}
|
||||
result = true
|
||||
for _, val := range vals {
|
||||
if !awsutil.DeepEqual(val, a.Expected) {
|
||||
result = false
|
||||
break
|
||||
}
|
||||
}
|
||||
case PathAnyWaiterMatch:
|
||||
// Only a single match needs to equal for the result to match
|
||||
vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
|
||||
for _, val := range vals {
|
||||
if awsutil.DeepEqual(val, a.Expected) {
|
||||
result = true
|
||||
break
|
||||
}
|
||||
}
|
||||
case PathListWaiterMatch:
|
||||
// ignored matcher
|
||||
case StatusWaiterMatch:
|
||||
s := a.Expected.(int)
|
||||
result = s == req.HTTPResponse.StatusCode
|
||||
case ErrorWaiterMatch:
|
||||
if aerr, ok := err.(awserr.Error); ok {
|
||||
result = aerr.Code() == a.Expected.(string)
|
||||
}
|
||||
default:
|
||||
waiterLogf(l, "WARNING: Waiter %s encountered unexpected matcher: %s",
|
||||
name, a.Matcher)
|
||||
}
|
||||
|
||||
if !result {
|
||||
// If there was no matching result found there is nothing more to do
|
||||
// for this response, retry the request.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
switch a.State {
|
||||
case SuccessWaiterState:
|
||||
// waiter completed
|
||||
return true, nil
|
||||
case FailureWaiterState:
|
||||
// Waiter failure state triggered
|
||||
return true, awserr.New(WaiterResourceNotReadyErrorCode,
|
||||
"failed waiting for successful resource state", err)
|
||||
case RetryWaiterState:
|
||||
// clear the error and retry the operation
|
||||
return false, nil
|
||||
default:
|
||||
waiterLogf(l, "WARNING: Waiter %s encountered unexpected state: %s",
|
||||
name, a.State)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waiterLogf(logger aws.Logger, msg string, args ...interface{}) {
|
||||
if logger != nil {
|
||||
logger.Log(fmt.Sprintf(msg, args...))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user