diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws/request')
15 files changed, 1975 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go new file mode 100644 index 0000000..10fc8cb --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go | |||
@@ -0,0 +1,19 @@ | |||
1 | // +build !appengine | ||
2 | |||
3 | package request | ||
4 | |||
5 | import ( | ||
6 | "net" | ||
7 | "os" | ||
8 | "syscall" | ||
9 | ) | ||
10 | |||
11 | func isErrConnectionReset(err error) bool { | ||
12 | if opErr, ok := err.(*net.OpError); ok { | ||
13 | if sysErr, ok := opErr.Err.(*os.SyscallError); ok { | ||
14 | return sysErr.Err == syscall.ECONNRESET | ||
15 | } | ||
16 | } | ||
17 | |||
18 | return false | ||
19 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go new file mode 100644 index 0000000..996196e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go | |||
@@ -0,0 +1,11 @@ | |||
1 | // +build appengine | ||
2 | |||
3 | package request | ||
4 | |||
5 | import ( | ||
6 | "strings" | ||
7 | ) | ||
8 | |||
9 | func isErrConnectionReset(err error) bool { | ||
10 | return strings.Contains(err.Error(), "connection reset") | ||
11 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go new file mode 100644 index 0000000..6c14336 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go | |||
@@ -0,0 +1,225 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strings" | ||
6 | ) | ||
7 | |||
8 | // A Handlers provides a collection of request handlers for various | ||
9 | // stages of handling requests. | ||
10 | type Handlers struct { | ||
11 | Validate HandlerList | ||
12 | Build HandlerList | ||
13 | Sign HandlerList | ||
14 | Send HandlerList | ||
15 | ValidateResponse HandlerList | ||
16 | Unmarshal HandlerList | ||
17 | UnmarshalMeta HandlerList | ||
18 | UnmarshalError HandlerList | ||
19 | Retry HandlerList | ||
20 | AfterRetry HandlerList | ||
21 | Complete HandlerList | ||
22 | } | ||
23 | |||
24 | // Copy returns of this handler's lists. | ||
25 | func (h *Handlers) Copy() Handlers { | ||
26 | return Handlers{ | ||
27 | Validate: h.Validate.copy(), | ||
28 | Build: h.Build.copy(), | ||
29 | Sign: h.Sign.copy(), | ||
30 | Send: h.Send.copy(), | ||
31 | ValidateResponse: h.ValidateResponse.copy(), | ||
32 | Unmarshal: h.Unmarshal.copy(), | ||
33 | UnmarshalError: h.UnmarshalError.copy(), | ||
34 | UnmarshalMeta: h.UnmarshalMeta.copy(), | ||
35 | Retry: h.Retry.copy(), | ||
36 | AfterRetry: h.AfterRetry.copy(), | ||
37 | Complete: h.Complete.copy(), | ||
38 | } | ||
39 | } | ||
40 | |||
41 | // Clear removes callback functions for all handlers | ||
42 | func (h *Handlers) Clear() { | ||
43 | h.Validate.Clear() | ||
44 | h.Build.Clear() | ||
45 | h.Send.Clear() | ||
46 | h.Sign.Clear() | ||
47 | h.Unmarshal.Clear() | ||
48 | h.UnmarshalMeta.Clear() | ||
49 | h.UnmarshalError.Clear() | ||
50 | h.ValidateResponse.Clear() | ||
51 | h.Retry.Clear() | ||
52 | h.AfterRetry.Clear() | ||
53 | h.Complete.Clear() | ||
54 | } | ||
55 | |||
56 | // A HandlerListRunItem represents an entry in the HandlerList which | ||
57 | // is being run. | ||
58 | type HandlerListRunItem struct { | ||
59 | Index int | ||
60 | Handler NamedHandler | ||
61 | Request *Request | ||
62 | } | ||
63 | |||
64 | // A HandlerList manages zero or more handlers in a list. | ||
65 | type HandlerList struct { | ||
66 | list []NamedHandler | ||
67 | |||
68 | // Called after each request handler in the list is called. If set | ||
69 | // and the func returns true the HandlerList will continue to iterate | ||
70 | // over the request handlers. If false is returned the HandlerList | ||
71 | // will stop iterating. | ||
72 | // | ||
73 | // Should be used if extra logic to be performed between each handler | ||
74 | // in the list. This can be used to terminate a list's iteration | ||
75 | // based on a condition such as error like, HandlerListStopOnError. | ||
76 | // Or for logging like HandlerListLogItem. | ||
77 | AfterEachFn func(item HandlerListRunItem) bool | ||
78 | } | ||
79 | |||
80 | // A NamedHandler is a struct that contains a name and function callback. | ||
81 | type NamedHandler struct { | ||
82 | Name string | ||
83 | Fn func(*Request) | ||
84 | } | ||
85 | |||
86 | // copy creates a copy of the handler list. | ||
87 | func (l *HandlerList) copy() HandlerList { | ||
88 | n := HandlerList{ | ||
89 | AfterEachFn: l.AfterEachFn, | ||
90 | } | ||
91 | if len(l.list) == 0 { | ||
92 | return n | ||
93 | } | ||
94 | |||
95 | n.list = append(make([]NamedHandler, 0, len(l.list)), l.list...) | ||
96 | return n | ||
97 | } | ||
98 | |||
99 | // Clear clears the handler list. | ||
100 | func (l *HandlerList) Clear() { | ||
101 | l.list = l.list[0:0] | ||
102 | } | ||
103 | |||
104 | // Len returns the number of handlers in the list. | ||
105 | func (l *HandlerList) Len() int { | ||
106 | return len(l.list) | ||
107 | } | ||
108 | |||
109 | // PushBack pushes handler f to the back of the handler list. | ||
110 | func (l *HandlerList) PushBack(f func(*Request)) { | ||
111 | l.PushBackNamed(NamedHandler{"__anonymous", f}) | ||
112 | } | ||
113 | |||
114 | // PushBackNamed pushes named handler f to the back of the handler list. | ||
115 | func (l *HandlerList) PushBackNamed(n NamedHandler) { | ||
116 | if cap(l.list) == 0 { | ||
117 | l.list = make([]NamedHandler, 0, 5) | ||
118 | } | ||
119 | l.list = append(l.list, n) | ||
120 | } | ||
121 | |||
122 | // PushFront pushes handler f to the front of the handler list. | ||
123 | func (l *HandlerList) PushFront(f func(*Request)) { | ||
124 | l.PushFrontNamed(NamedHandler{"__anonymous", f}) | ||
125 | } | ||
126 | |||
127 | // PushFrontNamed pushes named handler f to the front of the handler list. | ||
128 | func (l *HandlerList) PushFrontNamed(n NamedHandler) { | ||
129 | if cap(l.list) == len(l.list) { | ||
130 | // Allocating new list required | ||
131 | l.list = append([]NamedHandler{n}, l.list...) | ||
132 | } else { | ||
133 | // Enough room to prepend into list. | ||
134 | l.list = append(l.list, NamedHandler{}) | ||
135 | copy(l.list[1:], l.list) | ||
136 | l.list[0] = n | ||
137 | } | ||
138 | } | ||
139 | |||
140 | // Remove removes a NamedHandler n | ||
141 | func (l *HandlerList) Remove(n NamedHandler) { | ||
142 | l.RemoveByName(n.Name) | ||
143 | } | ||
144 | |||
145 | // RemoveByName removes a NamedHandler by name. | ||
146 | func (l *HandlerList) RemoveByName(name string) { | ||
147 | for i := 0; i < len(l.list); i++ { | ||
148 | m := l.list[i] | ||
149 | if m.Name == name { | ||
150 | // Shift array preventing creating new arrays | ||
151 | copy(l.list[i:], l.list[i+1:]) | ||
152 | l.list[len(l.list)-1] = NamedHandler{} | ||
153 | l.list = l.list[:len(l.list)-1] | ||
154 | |||
155 | // decrement list so next check to length is correct | ||
156 | i-- | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | // Run executes all handlers in the list with a given request object. | ||
162 | func (l *HandlerList) Run(r *Request) { | ||
163 | for i, h := range l.list { | ||
164 | h.Fn(r) | ||
165 | item := HandlerListRunItem{ | ||
166 | Index: i, Handler: h, Request: r, | ||
167 | } | ||
168 | if l.AfterEachFn != nil && !l.AfterEachFn(item) { | ||
169 | return | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | |||
174 | // HandlerListLogItem logs the request handler and the state of the | ||
175 | // request's Error value. Always returns true to continue iterating | ||
176 | // request handlers in a HandlerList. | ||
177 | func HandlerListLogItem(item HandlerListRunItem) bool { | ||
178 | if item.Request.Config.Logger == nil { | ||
179 | return true | ||
180 | } | ||
181 | item.Request.Config.Logger.Log("DEBUG: RequestHandler", | ||
182 | item.Index, item.Handler.Name, item.Request.Error) | ||
183 | |||
184 | return true | ||
185 | } | ||
186 | |||
187 | // HandlerListStopOnError returns false to stop the HandlerList iterating | ||
188 | // over request handlers if Request.Error is not nil. True otherwise | ||
189 | // to continue iterating. | ||
190 | func HandlerListStopOnError(item HandlerListRunItem) bool { | ||
191 | return item.Request.Error == nil | ||
192 | } | ||
193 | |||
194 | // WithAppendUserAgent will add a string to the user agent prefixed with a | ||
195 | // single white space. | ||
196 | func WithAppendUserAgent(s string) Option { | ||
197 | return func(r *Request) { | ||
198 | r.Handlers.Build.PushBack(func(r2 *Request) { | ||
199 | AddToUserAgent(r, s) | ||
200 | }) | ||
201 | } | ||
202 | } | ||
203 | |||
204 | // MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request | ||
205 | // header. If the extra parameters are provided they will be added as metadata to the | ||
206 | // name/version pair resulting in the following format. | ||
207 | // "name/version (extra0; extra1; ...)" | ||
208 | // The user agent part will be concatenated with this current request's user agent string. | ||
209 | func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) { | ||
210 | ua := fmt.Sprintf("%s/%s", name, version) | ||
211 | if len(extra) > 0 { | ||
212 | ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; ")) | ||
213 | } | ||
214 | return func(r *Request) { | ||
215 | AddToUserAgent(r, ua) | ||
216 | } | ||
217 | } | ||
218 | |||
219 | // MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header. | ||
220 | // The input string will be concatenated with the current request's user agent string. | ||
221 | func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) { | ||
222 | return func(r *Request) { | ||
223 | AddToUserAgent(r, s) | ||
224 | } | ||
225 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go new file mode 100644 index 0000000..79f7960 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go | |||
@@ -0,0 +1,24 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "io" | ||
5 | "net/http" | ||
6 | "net/url" | ||
7 | ) | ||
8 | |||
9 | func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request { | ||
10 | req := new(http.Request) | ||
11 | *req = *r | ||
12 | req.URL = &url.URL{} | ||
13 | *req.URL = *r.URL | ||
14 | req.Body = body | ||
15 | |||
16 | req.Header = http.Header{} | ||
17 | for k, v := range r.Header { | ||
18 | for _, vv := range v { | ||
19 | req.Header.Add(k, vv) | ||
20 | } | ||
21 | } | ||
22 | |||
23 | return req | ||
24 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go new file mode 100644 index 0000000..02f07f4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go | |||
@@ -0,0 +1,58 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "io" | ||
5 | "sync" | ||
6 | ) | ||
7 | |||
8 | // offsetReader is a thread-safe io.ReadCloser to prevent racing | ||
9 | // with retrying requests | ||
10 | type offsetReader struct { | ||
11 | buf io.ReadSeeker | ||
12 | lock sync.Mutex | ||
13 | closed bool | ||
14 | } | ||
15 | |||
16 | func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader { | ||
17 | reader := &offsetReader{} | ||
18 | buf.Seek(offset, 0) | ||
19 | |||
20 | reader.buf = buf | ||
21 | return reader | ||
22 | } | ||
23 | |||
24 | // Close will close the instance of the offset reader's access to | ||
25 | // the underlying io.ReadSeeker. | ||
26 | func (o *offsetReader) Close() error { | ||
27 | o.lock.Lock() | ||
28 | defer o.lock.Unlock() | ||
29 | o.closed = true | ||
30 | return nil | ||
31 | } | ||
32 | |||
33 | // Read is a thread-safe read of the underlying io.ReadSeeker | ||
34 | func (o *offsetReader) Read(p []byte) (int, error) { | ||
35 | o.lock.Lock() | ||
36 | defer o.lock.Unlock() | ||
37 | |||
38 | if o.closed { | ||
39 | return 0, io.EOF | ||
40 | } | ||
41 | |||
42 | return o.buf.Read(p) | ||
43 | } | ||
44 | |||
45 | // Seek is a thread-safe seeking operation. | ||
46 | func (o *offsetReader) Seek(offset int64, whence int) (int64, error) { | ||
47 | o.lock.Lock() | ||
48 | defer o.lock.Unlock() | ||
49 | |||
50 | return o.buf.Seek(offset, whence) | ||
51 | } | ||
52 | |||
53 | // CloseAndCopy will return a new offsetReader with a copy of the old buffer | ||
54 | // and close the old buffer. | ||
55 | func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader { | ||
56 | o.Close() | ||
57 | return newOffsetReader(o.buf, offset) | ||
58 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go new file mode 100644 index 0000000..4f4f112 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go | |||
@@ -0,0 +1,575 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "fmt" | ||
6 | "io" | ||
7 | "net" | ||
8 | "net/http" | ||
9 | "net/url" | ||
10 | "reflect" | ||
11 | "strings" | ||
12 | "time" | ||
13 | |||
14 | "github.com/aws/aws-sdk-go/aws" | ||
15 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
16 | "github.com/aws/aws-sdk-go/aws/client/metadata" | ||
17 | ) | ||
18 | |||
19 | const ( | ||
20 | // ErrCodeSerialization is the serialization error code that is received | ||
21 | // during protocol unmarshaling. | ||
22 | ErrCodeSerialization = "SerializationError" | ||
23 | |||
24 | // ErrCodeRead is an error that is returned during HTTP reads. | ||
25 | ErrCodeRead = "ReadError" | ||
26 | |||
27 | // ErrCodeResponseTimeout is the connection timeout error that is recieved | ||
28 | // during body reads. | ||
29 | ErrCodeResponseTimeout = "ResponseTimeout" | ||
30 | |||
31 | // CanceledErrorCode is the error code that will be returned by an | ||
32 | // API request that was canceled. Requests given a aws.Context may | ||
33 | // return this error when canceled. | ||
34 | CanceledErrorCode = "RequestCanceled" | ||
35 | ) | ||
36 | |||
37 | // A Request is the service request to be made. | ||
38 | type Request struct { | ||
39 | Config aws.Config | ||
40 | ClientInfo metadata.ClientInfo | ||
41 | Handlers Handlers | ||
42 | |||
43 | Retryer | ||
44 | Time time.Time | ||
45 | ExpireTime time.Duration | ||
46 | Operation *Operation | ||
47 | HTTPRequest *http.Request | ||
48 | HTTPResponse *http.Response | ||
49 | Body io.ReadSeeker | ||
50 | BodyStart int64 // offset from beginning of Body that the request body starts | ||
51 | Params interface{} | ||
52 | Error error | ||
53 | Data interface{} | ||
54 | RequestID string | ||
55 | RetryCount int | ||
56 | Retryable *bool | ||
57 | RetryDelay time.Duration | ||
58 | NotHoist bool | ||
59 | SignedHeaderVals http.Header | ||
60 | LastSignedAt time.Time | ||
61 | DisableFollowRedirects bool | ||
62 | |||
63 | context aws.Context | ||
64 | |||
65 | built bool | ||
66 | |||
67 | // Need to persist an intermediate body between the input Body and HTTP | ||
68 | // request body because the HTTP Client's transport can maintain a reference | ||
69 | // to the HTTP request's body after the client has returned. This value is | ||
70 | // safe to use concurrently and wrap the input Body for each HTTP request. | ||
71 | safeBody *offsetReader | ||
72 | } | ||
73 | |||
74 | // An Operation is the service API operation to be made. | ||
75 | type Operation struct { | ||
76 | Name string | ||
77 | HTTPMethod string | ||
78 | HTTPPath string | ||
79 | *Paginator | ||
80 | |||
81 | BeforePresignFn func(r *Request) error | ||
82 | } | ||
83 | |||
84 | // New returns a new Request pointer for the service API | ||
85 | // operation and parameters. | ||
86 | // | ||
87 | // Params is any value of input parameters to be the request payload. | ||
88 | // Data is pointer value to an object which the request's response | ||
89 | // payload will be deserialized to. | ||
90 | func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers, | ||
91 | retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request { | ||
92 | |||
93 | method := operation.HTTPMethod | ||
94 | if method == "" { | ||
95 | method = "POST" | ||
96 | } | ||
97 | |||
98 | httpReq, _ := http.NewRequest(method, "", nil) | ||
99 | |||
100 | var err error | ||
101 | httpReq.URL, err = url.Parse(clientInfo.Endpoint + operation.HTTPPath) | ||
102 | if err != nil { | ||
103 | httpReq.URL = &url.URL{} | ||
104 | err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err) | ||
105 | } | ||
106 | |||
107 | r := &Request{ | ||
108 | Config: cfg, | ||
109 | ClientInfo: clientInfo, | ||
110 | Handlers: handlers.Copy(), | ||
111 | |||
112 | Retryer: retryer, | ||
113 | Time: time.Now(), | ||
114 | ExpireTime: 0, | ||
115 | Operation: operation, | ||
116 | HTTPRequest: httpReq, | ||
117 | Body: nil, | ||
118 | Params: params, | ||
119 | Error: err, | ||
120 | Data: data, | ||
121 | } | ||
122 | r.SetBufferBody([]byte{}) | ||
123 | |||
124 | return r | ||
125 | } | ||
126 | |||
127 | // A Option is a functional option that can augment or modify a request when | ||
128 | // using a WithContext API operation method. | ||
129 | type Option func(*Request) | ||
130 | |||
131 | // WithGetResponseHeader builds a request Option which will retrieve a single | ||
132 | // header value from the HTTP Response. If there are multiple values for the | ||
133 | // header key use WithGetResponseHeaders instead to access the http.Header | ||
134 | // map directly. The passed in val pointer must be non-nil. | ||
135 | // | ||
136 | // This Option can be used multiple times with a single API operation. | ||
137 | // | ||
138 | // var id2, versionID string | ||
139 | // svc.PutObjectWithContext(ctx, params, | ||
140 | // request.WithGetResponseHeader("x-amz-id-2", &id2), | ||
141 | // request.WithGetResponseHeader("x-amz-version-id", &versionID), | ||
142 | // ) | ||
143 | func WithGetResponseHeader(key string, val *string) Option { | ||
144 | return func(r *Request) { | ||
145 | r.Handlers.Complete.PushBack(func(req *Request) { | ||
146 | *val = req.HTTPResponse.Header.Get(key) | ||
147 | }) | ||
148 | } | ||
149 | } | ||
150 | |||
151 | // WithGetResponseHeaders builds a request Option which will retrieve the | ||
152 | // headers from the HTTP response and assign them to the passed in headers | ||
153 | // variable. The passed in headers pointer must be non-nil. | ||
154 | // | ||
155 | // var headers http.Header | ||
156 | // svc.PutObjectWithContext(ctx, params, request.WithGetResponseHeaders(&headers)) | ||
157 | func WithGetResponseHeaders(headers *http.Header) Option { | ||
158 | return func(r *Request) { | ||
159 | r.Handlers.Complete.PushBack(func(req *Request) { | ||
160 | *headers = req.HTTPResponse.Header | ||
161 | }) | ||
162 | } | ||
163 | } | ||
164 | |||
165 | // WithLogLevel is a request option that will set the request to use a specific | ||
166 | // log level when the request is made. | ||
167 | // | ||
168 | // svc.PutObjectWithContext(ctx, params, request.WithLogLevel(aws.LogDebugWithHTTPBody) | ||
169 | func WithLogLevel(l aws.LogLevelType) Option { | ||
170 | return func(r *Request) { | ||
171 | r.Config.LogLevel = aws.LogLevel(l) | ||
172 | } | ||
173 | } | ||
174 | |||
175 | // ApplyOptions will apply each option to the request calling them in the order | ||
176 | // the were provided. | ||
177 | func (r *Request) ApplyOptions(opts ...Option) { | ||
178 | for _, opt := range opts { | ||
179 | opt(r) | ||
180 | } | ||
181 | } | ||
182 | |||
183 | // Context will always returns a non-nil context. If Request does not have a | ||
184 | // context aws.BackgroundContext will be returned. | ||
185 | func (r *Request) Context() aws.Context { | ||
186 | if r.context != nil { | ||
187 | return r.context | ||
188 | } | ||
189 | return aws.BackgroundContext() | ||
190 | } | ||
191 | |||
192 | // SetContext adds a Context to the current request that can be used to cancel | ||
193 | // a in-flight request. The Context value must not be nil, or this method will | ||
194 | // panic. | ||
195 | // | ||
196 | // Unlike http.Request.WithContext, SetContext does not return a copy of the | ||
197 | // Request. It is not safe to use use a single Request value for multiple | ||
198 | // requests. A new Request should be created for each API operation request. | ||
199 | // | ||
200 | // Go 1.6 and below: | ||
201 | // The http.Request's Cancel field will be set to the Done() value of | ||
202 | // the context. This will overwrite the Cancel field's value. | ||
203 | // | ||
204 | // Go 1.7 and above: | ||
205 | // The http.Request.WithContext will be used to set the context on the underlying | ||
206 | // http.Request. This will create a shallow copy of the http.Request. The SDK | ||
207 | // may create sub contexts in the future for nested requests such as retries. | ||
208 | func (r *Request) SetContext(ctx aws.Context) { | ||
209 | if ctx == nil { | ||
210 | panic("context cannot be nil") | ||
211 | } | ||
212 | setRequestContext(r, ctx) | ||
213 | } | ||
214 | |||
215 | // WillRetry returns if the request's can be retried. | ||
216 | func (r *Request) WillRetry() bool { | ||
217 | return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries() | ||
218 | } | ||
219 | |||
220 | // ParamsFilled returns if the request's parameters have been populated | ||
221 | // and the parameters are valid. False is returned if no parameters are | ||
222 | // provided or invalid. | ||
223 | func (r *Request) ParamsFilled() bool { | ||
224 | return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid() | ||
225 | } | ||
226 | |||
227 | // DataFilled returns true if the request's data for response deserialization | ||
228 | // target has been set and is a valid. False is returned if data is not | ||
229 | // set, or is invalid. | ||
230 | func (r *Request) DataFilled() bool { | ||
231 | return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid() | ||
232 | } | ||
233 | |||
234 | // SetBufferBody will set the request's body bytes that will be sent to | ||
235 | // the service API. | ||
236 | func (r *Request) SetBufferBody(buf []byte) { | ||
237 | r.SetReaderBody(bytes.NewReader(buf)) | ||
238 | } | ||
239 | |||
240 | // SetStringBody sets the body of the request to be backed by a string. | ||
241 | func (r *Request) SetStringBody(s string) { | ||
242 | r.SetReaderBody(strings.NewReader(s)) | ||
243 | } | ||
244 | |||
245 | // SetReaderBody will set the request's body reader. | ||
246 | func (r *Request) SetReaderBody(reader io.ReadSeeker) { | ||
247 | r.Body = reader | ||
248 | r.ResetBody() | ||
249 | } | ||
250 | |||
251 | // Presign returns the request's signed URL. Error will be returned | ||
252 | // if the signing fails. | ||
253 | func (r *Request) Presign(expireTime time.Duration) (string, error) { | ||
254 | r.ExpireTime = expireTime | ||
255 | r.NotHoist = false | ||
256 | |||
257 | if r.Operation.BeforePresignFn != nil { | ||
258 | r = r.copy() | ||
259 | err := r.Operation.BeforePresignFn(r) | ||
260 | if err != nil { | ||
261 | return "", err | ||
262 | } | ||
263 | } | ||
264 | |||
265 | r.Sign() | ||
266 | if r.Error != nil { | ||
267 | return "", r.Error | ||
268 | } | ||
269 | return r.HTTPRequest.URL.String(), nil | ||
270 | } | ||
271 | |||
272 | // PresignRequest behaves just like presign, but hoists all headers and signs them. | ||
273 | // Also returns the signed hash back to the user | ||
274 | func (r *Request) PresignRequest(expireTime time.Duration) (string, http.Header, error) { | ||
275 | r.ExpireTime = expireTime | ||
276 | r.NotHoist = true | ||
277 | r.Sign() | ||
278 | if r.Error != nil { | ||
279 | return "", nil, r.Error | ||
280 | } | ||
281 | return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil | ||
282 | } | ||
283 | |||
284 | func debugLogReqError(r *Request, stage string, retrying bool, err error) { | ||
285 | if !r.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) { | ||
286 | return | ||
287 | } | ||
288 | |||
289 | retryStr := "not retrying" | ||
290 | if retrying { | ||
291 | retryStr = "will retry" | ||
292 | } | ||
293 | |||
294 | r.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v", | ||
295 | stage, r.ClientInfo.ServiceName, r.Operation.Name, retryStr, err)) | ||
296 | } | ||
297 | |||
298 | // Build will build the request's object so it can be signed and sent | ||
299 | // to the service. Build will also validate all the request's parameters. | ||
300 | // Anny additional build Handlers set on this request will be run | ||
301 | // in the order they were set. | ||
302 | // | ||
303 | // The request will only be built once. Multiple calls to build will have | ||
304 | // no effect. | ||
305 | // | ||
306 | // If any Validate or Build errors occur the build will stop and the error | ||
307 | // which occurred will be returned. | ||
308 | func (r *Request) Build() error { | ||
309 | if !r.built { | ||
310 | r.Handlers.Validate.Run(r) | ||
311 | if r.Error != nil { | ||
312 | debugLogReqError(r, "Validate Request", false, r.Error) | ||
313 | return r.Error | ||
314 | } | ||
315 | r.Handlers.Build.Run(r) | ||
316 | if r.Error != nil { | ||
317 | debugLogReqError(r, "Build Request", false, r.Error) | ||
318 | return r.Error | ||
319 | } | ||
320 | r.built = true | ||
321 | } | ||
322 | |||
323 | return r.Error | ||
324 | } | ||
325 | |||
326 | // Sign will sign the request returning error if errors are encountered. | ||
327 | // | ||
328 | // Send will build the request prior to signing. All Sign Handlers will | ||
329 | // be executed in the order they were set. | ||
330 | func (r *Request) Sign() error { | ||
331 | r.Build() | ||
332 | if r.Error != nil { | ||
333 | debugLogReqError(r, "Build Request", false, r.Error) | ||
334 | return r.Error | ||
335 | } | ||
336 | |||
337 | r.Handlers.Sign.Run(r) | ||
338 | return r.Error | ||
339 | } | ||
340 | |||
341 | // ResetBody rewinds the request body backto its starting position, and | ||
342 | // set's the HTTP Request body reference. When the body is read prior | ||
343 | // to being sent in the HTTP request it will need to be rewound. | ||
344 | func (r *Request) ResetBody() { | ||
345 | if r.safeBody != nil { | ||
346 | r.safeBody.Close() | ||
347 | } | ||
348 | |||
349 | r.safeBody = newOffsetReader(r.Body, r.BodyStart) | ||
350 | |||
351 | // Go 1.8 tightened and clarified the rules code needs to use when building | ||
352 | // requests with the http package. Go 1.8 removed the automatic detection | ||
353 | // of if the Request.Body was empty, or actually had bytes in it. The SDK | ||
354 | // always sets the Request.Body even if it is empty and should not actually | ||
355 | // be sent. This is incorrect. | ||
356 | // | ||
357 | // Go 1.8 did add a http.NoBody value that the SDK can use to tell the http | ||
358 | // client that the request really should be sent without a body. The | ||
359 | // Request.Body cannot be set to nil, which is preferable, because the | ||
360 | // field is exported and could introduce nil pointer dereferences for users | ||
361 | // of the SDK if they used that field. | ||
362 | // | ||
363 | // Related golang/go#18257 | ||
364 | l, err := computeBodyLength(r.Body) | ||
365 | if err != nil { | ||
366 | r.Error = awserr.New(ErrCodeSerialization, "failed to compute request body size", err) | ||
367 | return | ||
368 | } | ||
369 | |||
370 | if l == 0 { | ||
371 | r.HTTPRequest.Body = noBodyReader | ||
372 | } else if l > 0 { | ||
373 | r.HTTPRequest.Body = r.safeBody | ||
374 | } else { | ||
375 | // Hack to prevent sending bodies for methods where the body | ||
376 | // should be ignored by the server. Sending bodies on these | ||
377 | // methods without an associated ContentLength will cause the | ||
378 | // request to socket timeout because the server does not handle | ||
379 | // Transfer-Encoding: chunked bodies for these methods. | ||
380 | // | ||
381 | // This would only happen if a aws.ReaderSeekerCloser was used with | ||
382 | // a io.Reader that was not also an io.Seeker. | ||
383 | switch r.Operation.HTTPMethod { | ||
384 | case "GET", "HEAD", "DELETE": | ||
385 | r.HTTPRequest.Body = noBodyReader | ||
386 | default: | ||
387 | r.HTTPRequest.Body = r.safeBody | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | |||
392 | // Attempts to compute the length of the body of the reader using the | ||
393 | // io.Seeker interface. If the value is not seekable because of being | ||
394 | // a ReaderSeekerCloser without an unerlying Seeker -1 will be returned. | ||
395 | // If no error occurs the length of the body will be returned. | ||
396 | func computeBodyLength(r io.ReadSeeker) (int64, error) { | ||
397 | seekable := true | ||
398 | // Determine if the seeker is actually seekable. ReaderSeekerCloser | ||
399 | // hides the fact that a io.Readers might not actually be seekable. | ||
400 | switch v := r.(type) { | ||
401 | case aws.ReaderSeekerCloser: | ||
402 | seekable = v.IsSeeker() | ||
403 | case *aws.ReaderSeekerCloser: | ||
404 | seekable = v.IsSeeker() | ||
405 | } | ||
406 | if !seekable { | ||
407 | return -1, nil | ||
408 | } | ||
409 | |||
410 | curOffset, err := r.Seek(0, 1) | ||
411 | if err != nil { | ||
412 | return 0, err | ||
413 | } | ||
414 | |||
415 | endOffset, err := r.Seek(0, 2) | ||
416 | if err != nil { | ||
417 | return 0, err | ||
418 | } | ||
419 | |||
420 | _, err = r.Seek(curOffset, 0) | ||
421 | if err != nil { | ||
422 | return 0, err | ||
423 | } | ||
424 | |||
425 | return endOffset - curOffset, nil | ||
426 | } | ||
427 | |||
428 | // GetBody will return an io.ReadSeeker of the Request's underlying | ||
429 | // input body with a concurrency safe wrapper. | ||
430 | func (r *Request) GetBody() io.ReadSeeker { | ||
431 | return r.safeBody | ||
432 | } | ||
433 | |||
434 | // Send will send the request returning error if errors are encountered. | ||
435 | // | ||
436 | // Send will sign the request prior to sending. All Send Handlers will | ||
437 | // be executed in the order they were set. | ||
438 | // | ||
439 | // Canceling a request is non-deterministic. If a request has been canceled, | ||
440 | // then the transport will choose, randomly, one of the state channels during | ||
441 | // reads or getting the connection. | ||
442 | // | ||
443 | // readLoop() and getConn(req *Request, cm connectMethod) | ||
444 | // https://github.com/golang/go/blob/master/src/net/http/transport.go | ||
445 | // | ||
446 | // Send will not close the request.Request's body. | ||
447 | func (r *Request) Send() error { | ||
448 | defer func() { | ||
449 | // Regardless of success or failure of the request trigger the Complete | ||
450 | // request handlers. | ||
451 | r.Handlers.Complete.Run(r) | ||
452 | }() | ||
453 | |||
454 | for { | ||
455 | if aws.BoolValue(r.Retryable) { | ||
456 | if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) { | ||
457 | r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d", | ||
458 | r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount)) | ||
459 | } | ||
460 | |||
461 | // The previous http.Request will have a reference to the r.Body | ||
462 | // and the HTTP Client's Transport may still be reading from | ||
463 | // the request's body even though the Client's Do returned. | ||
464 | r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil) | ||
465 | r.ResetBody() | ||
466 | |||
467 | // Closing response body to ensure that no response body is leaked | ||
468 | // between retry attempts. | ||
469 | if r.HTTPResponse != nil && r.HTTPResponse.Body != nil { | ||
470 | r.HTTPResponse.Body.Close() | ||
471 | } | ||
472 | } | ||
473 | |||
474 | r.Sign() | ||
475 | if r.Error != nil { | ||
476 | return r.Error | ||
477 | } | ||
478 | |||
479 | r.Retryable = nil | ||
480 | |||
481 | r.Handlers.Send.Run(r) | ||
482 | if r.Error != nil { | ||
483 | if !shouldRetryCancel(r) { | ||
484 | return r.Error | ||
485 | } | ||
486 | |||
487 | err := r.Error | ||
488 | r.Handlers.Retry.Run(r) | ||
489 | r.Handlers.AfterRetry.Run(r) | ||
490 | if r.Error != nil { | ||
491 | debugLogReqError(r, "Send Request", false, r.Error) | ||
492 | return r.Error | ||
493 | } | ||
494 | debugLogReqError(r, "Send Request", true, err) | ||
495 | continue | ||
496 | } | ||
497 | r.Handlers.UnmarshalMeta.Run(r) | ||
498 | r.Handlers.ValidateResponse.Run(r) | ||
499 | if r.Error != nil { | ||
500 | err := r.Error | ||
501 | r.Handlers.UnmarshalError.Run(r) | ||
502 | r.Handlers.Retry.Run(r) | ||
503 | r.Handlers.AfterRetry.Run(r) | ||
504 | if r.Error != nil { | ||
505 | debugLogReqError(r, "Validate Response", false, r.Error) | ||
506 | return r.Error | ||
507 | } | ||
508 | debugLogReqError(r, "Validate Response", true, err) | ||
509 | continue | ||
510 | } | ||
511 | |||
512 | r.Handlers.Unmarshal.Run(r) | ||
513 | if r.Error != nil { | ||
514 | err := r.Error | ||
515 | r.Handlers.Retry.Run(r) | ||
516 | r.Handlers.AfterRetry.Run(r) | ||
517 | if r.Error != nil { | ||
518 | debugLogReqError(r, "Unmarshal Response", false, r.Error) | ||
519 | return r.Error | ||
520 | } | ||
521 | debugLogReqError(r, "Unmarshal Response", true, err) | ||
522 | continue | ||
523 | } | ||
524 | |||
525 | break | ||
526 | } | ||
527 | |||
528 | return nil | ||
529 | } | ||
530 | |||
531 | // copy will copy a request which will allow for local manipulation of the | ||
532 | // request. | ||
533 | func (r *Request) copy() *Request { | ||
534 | req := &Request{} | ||
535 | *req = *r | ||
536 | req.Handlers = r.Handlers.Copy() | ||
537 | op := *r.Operation | ||
538 | req.Operation = &op | ||
539 | return req | ||
540 | } | ||
541 | |||
542 | // AddToUserAgent adds the string to the end of the request's current user agent. | ||
543 | func AddToUserAgent(r *Request, s string) { | ||
544 | curUA := r.HTTPRequest.Header.Get("User-Agent") | ||
545 | if len(curUA) > 0 { | ||
546 | s = curUA + " " + s | ||
547 | } | ||
548 | r.HTTPRequest.Header.Set("User-Agent", s) | ||
549 | } | ||
550 | |||
551 | func shouldRetryCancel(r *Request) bool { | ||
552 | awsErr, ok := r.Error.(awserr.Error) | ||
553 | timeoutErr := false | ||
554 | errStr := r.Error.Error() | ||
555 | if ok { | ||
556 | if awsErr.Code() == CanceledErrorCode { | ||
557 | return false | ||
558 | } | ||
559 | err := awsErr.OrigErr() | ||
560 | netErr, netOK := err.(net.Error) | ||
561 | timeoutErr = netOK && netErr.Temporary() | ||
562 | if urlErr, ok := err.(*url.Error); !timeoutErr && ok { | ||
563 | errStr = urlErr.Err.Error() | ||
564 | } | ||
565 | } | ||
566 | |||
567 | // There can be two types of canceled errors here. | ||
568 | // The first being a net.Error and the other being an error. | ||
569 | // If the request was timed out, we want to continue the retry | ||
570 | // process. Otherwise, return the canceled error. | ||
571 | return timeoutErr || | ||
572 | (errStr != "net/http: request canceled" && | ||
573 | errStr != "net/http: request canceled while waiting for connection") | ||
574 | |||
575 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go new file mode 100644 index 0000000..1323af9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go | |||
@@ -0,0 +1,21 @@ | |||
1 | // +build !go1.8 | ||
2 | |||
3 | package request | ||
4 | |||
5 | import "io" | ||
6 | |||
7 | // NoBody is an io.ReadCloser with no bytes. Read always returns EOF | ||
8 | // and Close always returns nil. It can be used in an outgoing client | ||
9 | // request to explicitly signal that a request has zero bytes. | ||
10 | // An alternative, however, is to simply set Request.Body to nil. | ||
11 | // | ||
12 | // Copy of Go 1.8 NoBody type from net/http/http.go | ||
13 | type noBody struct{} | ||
14 | |||
15 | func (noBody) Read([]byte) (int, error) { return 0, io.EOF } | ||
16 | func (noBody) Close() error { return nil } | ||
17 | func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil } | ||
18 | |||
19 | // Is an empty reader that will trigger the Go HTTP client to not include | ||
20 | // and body in the HTTP request. | ||
21 | var noBodyReader = noBody{} | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go new file mode 100644 index 0000000..8b963f4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go | |||
@@ -0,0 +1,9 @@ | |||
1 | // +build go1.8 | ||
2 | |||
3 | package request | ||
4 | |||
5 | import "net/http" | ||
6 | |||
7 | // Is a http.NoBody reader instructing Go HTTP client to not include | ||
8 | // and body in the HTTP request. | ||
9 | var noBodyReader = http.NoBody | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go new file mode 100644 index 0000000..a7365cd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go | |||
@@ -0,0 +1,14 @@ | |||
1 | // +build go1.7 | ||
2 | |||
3 | package request | ||
4 | |||
5 | import "github.com/aws/aws-sdk-go/aws" | ||
6 | |||
7 | // setContext updates the Request to use the passed in context for cancellation. | ||
8 | // Context will also be used for request retry delay. | ||
9 | // | ||
10 | // Creates shallow copy of the http.Request with the WithContext method. | ||
11 | func setRequestContext(r *Request, ctx aws.Context) { | ||
12 | r.context = ctx | ||
13 | r.HTTPRequest = r.HTTPRequest.WithContext(ctx) | ||
14 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go new file mode 100644 index 0000000..307fa07 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go | |||
@@ -0,0 +1,14 @@ | |||
1 | // +build !go1.7 | ||
2 | |||
3 | package request | ||
4 | |||
5 | import "github.com/aws/aws-sdk-go/aws" | ||
6 | |||
7 | // setContext updates the Request to use the passed in context for cancellation. | ||
8 | // Context will also be used for request retry delay. | ||
9 | // | ||
10 | // Creates shallow copy of the http.Request with the WithContext method. | ||
11 | func setRequestContext(r *Request, ctx aws.Context) { | ||
12 | r.context = ctx | ||
13 | r.HTTPRequest.Cancel = ctx.Done() | ||
14 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go new file mode 100644 index 0000000..59de673 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go | |||
@@ -0,0 +1,236 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "reflect" | ||
5 | "sync/atomic" | ||
6 | |||
7 | "github.com/aws/aws-sdk-go/aws" | ||
8 | "github.com/aws/aws-sdk-go/aws/awsutil" | ||
9 | ) | ||
10 | |||
11 | // A Pagination provides paginating of SDK API operations which are paginatable. | ||
12 | // Generally you should not use this type directly, but use the "Pages" API | ||
13 | // operations method to automatically perform pagination for you. Such as, | ||
14 | // "S3.ListObjectsPages", and "S3.ListObjectsPagesWithContext" methods. | ||
15 | // | ||
16 | // Pagination differs from a Paginator type in that pagination is the type that | ||
17 | // does the pagination between API operations, and Paginator defines the | ||
18 | // configuration that will be used per page request. | ||
19 | // | ||
20 | // cont := true | ||
21 | // for p.Next() && cont { | ||
22 | // data := p.Page().(*s3.ListObjectsOutput) | ||
23 | // // process the page's data | ||
24 | // } | ||
25 | // return p.Err() | ||
26 | // | ||
27 | // See service client API operation Pages methods for examples how the SDK will | ||
28 | // use the Pagination type. | ||
29 | type Pagination struct { | ||
30 | // Function to return a Request value for each pagination request. | ||
31 | // Any configuration or handlers that need to be applied to the request | ||
32 | // prior to getting the next page should be done here before the request | ||
33 | // returned. | ||
34 | // | ||
35 | // NewRequest should always be built from the same API operations. It is | ||
36 | // undefined if different API operations are returned on subsequent calls. | ||
37 | NewRequest func() (*Request, error) | ||
38 | |||
39 | started bool | ||
40 | nextTokens []interface{} | ||
41 | |||
42 | err error | ||
43 | curPage interface{} | ||
44 | } | ||
45 | |||
46 | // HasNextPage will return true if Pagination is able to determine that the API | ||
47 | // operation has additional pages. False will be returned if there are no more | ||
48 | // pages remaining. | ||
49 | // | ||
50 | // Will always return true if Next has not been called yet. | ||
51 | func (p *Pagination) HasNextPage() bool { | ||
52 | return !(p.started && len(p.nextTokens) == 0) | ||
53 | } | ||
54 | |||
55 | // Err returns the error Pagination encountered when retrieving the next page. | ||
56 | func (p *Pagination) Err() error { | ||
57 | return p.err | ||
58 | } | ||
59 | |||
60 | // Page returns the current page. Page should only be called after a successful | ||
61 | // call to Next. It is undefined what Page will return if Page is called after | ||
62 | // Next returns false. | ||
63 | func (p *Pagination) Page() interface{} { | ||
64 | return p.curPage | ||
65 | } | ||
66 | |||
67 | // Next will attempt to retrieve the next page for the API operation. When a page | ||
68 | // is retrieved true will be returned. If the page cannot be retrieved, or there | ||
69 | // are no more pages false will be returned. | ||
70 | // | ||
71 | // Use the Page method to retrieve the current page data. The data will need | ||
72 | // to be cast to the API operation's output type. | ||
73 | // | ||
74 | // Use the Err method to determine if an error occurred if Page returns false. | ||
75 | func (p *Pagination) Next() bool { | ||
76 | if !p.HasNextPage() { | ||
77 | return false | ||
78 | } | ||
79 | |||
80 | req, err := p.NewRequest() | ||
81 | if err != nil { | ||
82 | p.err = err | ||
83 | return false | ||
84 | } | ||
85 | |||
86 | if p.started { | ||
87 | for i, intok := range req.Operation.InputTokens { | ||
88 | awsutil.SetValueAtPath(req.Params, intok, p.nextTokens[i]) | ||
89 | } | ||
90 | } | ||
91 | p.started = true | ||
92 | |||
93 | err = req.Send() | ||
94 | if err != nil { | ||
95 | p.err = err | ||
96 | return false | ||
97 | } | ||
98 | |||
99 | p.nextTokens = req.nextPageTokens() | ||
100 | p.curPage = req.Data | ||
101 | |||
102 | return true | ||
103 | } | ||
104 | |||
105 | // A Paginator is the configuration data that defines how an API operation | ||
106 | // should be paginated. This type is used by the API service models to define | ||
107 | // the generated pagination config for service APIs. | ||
108 | // | ||
109 | // The Pagination type is what provides iterating between pages of an API. It | ||
110 | // is only used to store the token metadata the SDK should use for performing | ||
111 | // pagination. | ||
112 | type Paginator struct { | ||
113 | InputTokens []string | ||
114 | OutputTokens []string | ||
115 | LimitToken string | ||
116 | TruncationToken string | ||
117 | } | ||
118 | |||
119 | // nextPageTokens returns the tokens to use when asking for the next page of data. | ||
120 | func (r *Request) nextPageTokens() []interface{} { | ||
121 | if r.Operation.Paginator == nil { | ||
122 | return nil | ||
123 | } | ||
124 | if r.Operation.TruncationToken != "" { | ||
125 | tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken) | ||
126 | if len(tr) == 0 { | ||
127 | return nil | ||
128 | } | ||
129 | |||
130 | switch v := tr[0].(type) { | ||
131 | case *bool: | ||
132 | if !aws.BoolValue(v) { | ||
133 | return nil | ||
134 | } | ||
135 | case bool: | ||
136 | if v == false { | ||
137 | return nil | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | tokens := []interface{}{} | ||
143 | tokenAdded := false | ||
144 | for _, outToken := range r.Operation.OutputTokens { | ||
145 | v, _ := awsutil.ValuesAtPath(r.Data, outToken) | ||
146 | if len(v) > 0 { | ||
147 | tokens = append(tokens, v[0]) | ||
148 | tokenAdded = true | ||
149 | } else { | ||
150 | tokens = append(tokens, nil) | ||
151 | } | ||
152 | } | ||
153 | if !tokenAdded { | ||
154 | return nil | ||
155 | } | ||
156 | |||
157 | return tokens | ||
158 | } | ||
159 | |||
160 | // Ensure a deprecated item is only logged once instead of each time its used. | ||
161 | func logDeprecatedf(logger aws.Logger, flag *int32, msg string) { | ||
162 | if logger == nil { | ||
163 | return | ||
164 | } | ||
165 | if atomic.CompareAndSwapInt32(flag, 0, 1) { | ||
166 | logger.Log(msg) | ||
167 | } | ||
168 | } | ||
169 | |||
170 | var ( | ||
171 | logDeprecatedHasNextPage int32 | ||
172 | logDeprecatedNextPage int32 | ||
173 | logDeprecatedEachPage int32 | ||
174 | ) | ||
175 | |||
176 | // HasNextPage returns true if this request has more pages of data available. | ||
177 | // | ||
178 | // Deprecated Use Pagination type for configurable pagination of API operations | ||
179 | func (r *Request) HasNextPage() bool { | ||
180 | logDeprecatedf(r.Config.Logger, &logDeprecatedHasNextPage, | ||
181 | "Request.HasNextPage deprecated. Use Pagination type for configurable pagination of API operations") | ||
182 | |||
183 | return len(r.nextPageTokens()) > 0 | ||
184 | } | ||
185 | |||
186 | // NextPage returns a new Request that can be executed to return the next | ||
187 | // page of result data. Call .Send() on this request to execute it. | ||
188 | // | ||
189 | // Deprecated Use Pagination type for configurable pagination of API operations | ||
190 | func (r *Request) NextPage() *Request { | ||
191 | logDeprecatedf(r.Config.Logger, &logDeprecatedNextPage, | ||
192 | "Request.NextPage deprecated. Use Pagination type for configurable pagination of API operations") | ||
193 | |||
194 | tokens := r.nextPageTokens() | ||
195 | if len(tokens) == 0 { | ||
196 | return nil | ||
197 | } | ||
198 | |||
199 | data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface() | ||
200 | nr := New(r.Config, r.ClientInfo, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data) | ||
201 | for i, intok := range nr.Operation.InputTokens { | ||
202 | awsutil.SetValueAtPath(nr.Params, intok, tokens[i]) | ||
203 | } | ||
204 | return nr | ||
205 | } | ||
206 | |||
207 | // EachPage iterates over each page of a paginated request object. The fn | ||
208 | // parameter should be a function with the following sample signature: | ||
209 | // | ||
210 | // func(page *T, lastPage bool) bool { | ||
211 | // return true // return false to stop iterating | ||
212 | // } | ||
213 | // | ||
214 | // Where "T" is the structure type matching the output structure of the given | ||
215 | // operation. For example, a request object generated by | ||
216 | // DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput | ||
217 | // as the structure "T". The lastPage value represents whether the page is | ||
218 | // the last page of data or not. The return value of this function should | ||
219 | // return true to keep iterating or false to stop. | ||
220 | // | ||
221 | // Deprecated Use Pagination type for configurable pagination of API operations | ||
222 | func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error { | ||
223 | logDeprecatedf(r.Config.Logger, &logDeprecatedEachPage, | ||
224 | "Request.EachPage deprecated. Use Pagination type for configurable pagination of API operations") | ||
225 | |||
226 | for page := r; page != nil; page = page.NextPage() { | ||
227 | if err := page.Send(); err != nil { | ||
228 | return err | ||
229 | } | ||
230 | if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage { | ||
231 | return page.Error | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return nil | ||
236 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go new file mode 100644 index 0000000..7af81de --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go | |||
@@ -0,0 +1,154 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "time" | ||
5 | |||
6 | "github.com/aws/aws-sdk-go/aws" | ||
7 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
8 | ) | ||
9 | |||
10 | // Retryer is an interface to control retry logic for a given service. | ||
11 | // The default implementation used by most services is the service.DefaultRetryer | ||
12 | // structure, which contains basic retry logic using exponential backoff. | ||
13 | type Retryer interface { | ||
14 | RetryRules(*Request) time.Duration | ||
15 | ShouldRetry(*Request) bool | ||
16 | MaxRetries() int | ||
17 | } | ||
18 | |||
19 | // WithRetryer sets a config Retryer value to the given Config returning it | ||
20 | // for chaining. | ||
21 | func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config { | ||
22 | cfg.Retryer = retryer | ||
23 | return cfg | ||
24 | } | ||
25 | |||
26 | // retryableCodes is a collection of service response codes which are retry-able | ||
27 | // without any further action. | ||
28 | var retryableCodes = map[string]struct{}{ | ||
29 | "RequestError": {}, | ||
30 | "RequestTimeout": {}, | ||
31 | ErrCodeResponseTimeout: {}, | ||
32 | "RequestTimeoutException": {}, // Glacier's flavor of RequestTimeout | ||
33 | } | ||
34 | |||
35 | var throttleCodes = map[string]struct{}{ | ||
36 | "ProvisionedThroughputExceededException": {}, | ||
37 | "Throttling": {}, | ||
38 | "ThrottlingException": {}, | ||
39 | "RequestLimitExceeded": {}, | ||
40 | "RequestThrottled": {}, | ||
41 | "LimitExceededException": {}, // Deleting 10+ DynamoDb tables at once | ||
42 | "TooManyRequestsException": {}, // Lambda functions | ||
43 | "PriorRequestNotComplete": {}, // Route53 | ||
44 | } | ||
45 | |||
46 | // credsExpiredCodes is a collection of error codes which signify the credentials | ||
47 | // need to be refreshed. Expired tokens require refreshing of credentials, and | ||
48 | // resigning before the request can be retried. | ||
49 | var credsExpiredCodes = map[string]struct{}{ | ||
50 | "ExpiredToken": {}, | ||
51 | "ExpiredTokenException": {}, | ||
52 | "RequestExpired": {}, // EC2 Only | ||
53 | } | ||
54 | |||
55 | func isCodeThrottle(code string) bool { | ||
56 | _, ok := throttleCodes[code] | ||
57 | return ok | ||
58 | } | ||
59 | |||
60 | func isCodeRetryable(code string) bool { | ||
61 | if _, ok := retryableCodes[code]; ok { | ||
62 | return true | ||
63 | } | ||
64 | |||
65 | return isCodeExpiredCreds(code) | ||
66 | } | ||
67 | |||
68 | func isCodeExpiredCreds(code string) bool { | ||
69 | _, ok := credsExpiredCodes[code] | ||
70 | return ok | ||
71 | } | ||
72 | |||
73 | var validParentCodes = map[string]struct{}{ | ||
74 | ErrCodeSerialization: struct{}{}, | ||
75 | ErrCodeRead: struct{}{}, | ||
76 | } | ||
77 | |||
78 | func isNestedErrorRetryable(parentErr awserr.Error) bool { | ||
79 | if parentErr == nil { | ||
80 | return false | ||
81 | } | ||
82 | |||
83 | if _, ok := validParentCodes[parentErr.Code()]; !ok { | ||
84 | return false | ||
85 | } | ||
86 | |||
87 | err := parentErr.OrigErr() | ||
88 | if err == nil { | ||
89 | return false | ||
90 | } | ||
91 | |||
92 | if aerr, ok := err.(awserr.Error); ok { | ||
93 | return isCodeRetryable(aerr.Code()) | ||
94 | } | ||
95 | |||
96 | return isErrConnectionReset(err) | ||
97 | } | ||
98 | |||
99 | // IsErrorRetryable returns whether the error is retryable, based on its Code. | ||
100 | // Returns false if error is nil. | ||
101 | func IsErrorRetryable(err error) bool { | ||
102 | if err != nil { | ||
103 | if aerr, ok := err.(awserr.Error); ok { | ||
104 | return isCodeRetryable(aerr.Code()) || isNestedErrorRetryable(aerr) | ||
105 | } | ||
106 | } | ||
107 | return false | ||
108 | } | ||
109 | |||
110 | // IsErrorThrottle returns whether the error is to be throttled based on its code. | ||
111 | // Returns false if error is nil. | ||
112 | func IsErrorThrottle(err error) bool { | ||
113 | if err != nil { | ||
114 | if aerr, ok := err.(awserr.Error); ok { | ||
115 | return isCodeThrottle(aerr.Code()) | ||
116 | } | ||
117 | } | ||
118 | return false | ||
119 | } | ||
120 | |||
121 | // IsErrorExpiredCreds returns whether the error code is a credential expiry error. | ||
122 | // Returns false if error is nil. | ||
123 | func IsErrorExpiredCreds(err error) bool { | ||
124 | if err != nil { | ||
125 | if aerr, ok := err.(awserr.Error); ok { | ||
126 | return isCodeExpiredCreds(aerr.Code()) | ||
127 | } | ||
128 | } | ||
129 | return false | ||
130 | } | ||
131 | |||
132 | // IsErrorRetryable returns whether the error is retryable, based on its Code. | ||
133 | // Returns false if the request has no Error set. | ||
134 | // | ||
135 | // Alias for the utility function IsErrorRetryable | ||
136 | func (r *Request) IsErrorRetryable() bool { | ||
137 | return IsErrorRetryable(r.Error) | ||
138 | } | ||
139 | |||
140 | // IsErrorThrottle returns whether the error is to be throttled based on its code. | ||
141 | // Returns false if the request has no Error set | ||
142 | // | ||
143 | // Alias for the utility function IsErrorThrottle | ||
144 | func (r *Request) IsErrorThrottle() bool { | ||
145 | return IsErrorThrottle(r.Error) | ||
146 | } | ||
147 | |||
148 | // IsErrorExpired returns whether the error code is a credential expiry error. | ||
149 | // Returns false if the request has no Error set. | ||
150 | // | ||
151 | // Alias for the utility function IsErrorExpiredCreds | ||
152 | func (r *Request) IsErrorExpired() bool { | ||
153 | return IsErrorExpiredCreds(r.Error) | ||
154 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go new file mode 100644 index 0000000..09a44eb --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go | |||
@@ -0,0 +1,94 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "io" | ||
5 | "time" | ||
6 | |||
7 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
8 | ) | ||
9 | |||
10 | var timeoutErr = awserr.New( | ||
11 | ErrCodeResponseTimeout, | ||
12 | "read on body has reached the timeout limit", | ||
13 | nil, | ||
14 | ) | ||
15 | |||
16 | type readResult struct { | ||
17 | n int | ||
18 | err error | ||
19 | } | ||
20 | |||
21 | // timeoutReadCloser will handle body reads that take too long. | ||
22 | // We will return a ErrReadTimeout error if a timeout occurs. | ||
23 | type timeoutReadCloser struct { | ||
24 | reader io.ReadCloser | ||
25 | duration time.Duration | ||
26 | } | ||
27 | |||
28 | // Read will spin off a goroutine to call the reader's Read method. We will | ||
29 | // select on the timer's channel or the read's channel. Whoever completes first | ||
30 | // will be returned. | ||
31 | func (r *timeoutReadCloser) Read(b []byte) (int, error) { | ||
32 | timer := time.NewTimer(r.duration) | ||
33 | c := make(chan readResult, 1) | ||
34 | |||
35 | go func() { | ||
36 | n, err := r.reader.Read(b) | ||
37 | timer.Stop() | ||
38 | c <- readResult{n: n, err: err} | ||
39 | }() | ||
40 | |||
41 | select { | ||
42 | case data := <-c: | ||
43 | return data.n, data.err | ||
44 | case <-timer.C: | ||
45 | return 0, timeoutErr | ||
46 | } | ||
47 | } | ||
48 | |||
49 | func (r *timeoutReadCloser) Close() error { | ||
50 | return r.reader.Close() | ||
51 | } | ||
52 | |||
53 | const ( | ||
54 | // HandlerResponseTimeout is what we use to signify the name of the | ||
55 | // response timeout handler. | ||
56 | HandlerResponseTimeout = "ResponseTimeoutHandler" | ||
57 | ) | ||
58 | |||
59 | // adaptToResponseTimeoutError is a handler that will replace any top level error | ||
60 | // to a ErrCodeResponseTimeout, if its child is that. | ||
61 | func adaptToResponseTimeoutError(req *Request) { | ||
62 | if err, ok := req.Error.(awserr.Error); ok { | ||
63 | aerr, ok := err.OrigErr().(awserr.Error) | ||
64 | if ok && aerr.Code() == ErrCodeResponseTimeout { | ||
65 | req.Error = aerr | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | // WithResponseReadTimeout is a request option that will wrap the body in a timeout read closer. | ||
71 | // This will allow for per read timeouts. If a timeout occurred, we will return the | ||
72 | // ErrCodeResponseTimeout. | ||
73 | // | ||
74 | // svc.PutObjectWithContext(ctx, params, request.WithTimeoutReadCloser(30 * time.Second) | ||
75 | func WithResponseReadTimeout(duration time.Duration) Option { | ||
76 | return func(r *Request) { | ||
77 | |||
78 | var timeoutHandler = NamedHandler{ | ||
79 | HandlerResponseTimeout, | ||
80 | func(req *Request) { | ||
81 | req.HTTPResponse.Body = &timeoutReadCloser{ | ||
82 | reader: req.HTTPResponse.Body, | ||
83 | duration: duration, | ||
84 | } | ||
85 | }} | ||
86 | |||
87 | // remove the handler so we are not stomping over any new durations. | ||
88 | r.Handlers.Send.RemoveByName(HandlerResponseTimeout) | ||
89 | r.Handlers.Send.PushBackNamed(timeoutHandler) | ||
90 | |||
91 | r.Handlers.Unmarshal.PushBack(adaptToResponseTimeoutError) | ||
92 | r.Handlers.UnmarshalError.PushBack(adaptToResponseTimeoutError) | ||
93 | } | ||
94 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go b/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go new file mode 100644 index 0000000..2520286 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go | |||
@@ -0,0 +1,234 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "fmt" | ||
6 | |||
7 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
8 | ) | ||
9 | |||
10 | const ( | ||
11 | // InvalidParameterErrCode is the error code for invalid parameters errors | ||
12 | InvalidParameterErrCode = "InvalidParameter" | ||
13 | // ParamRequiredErrCode is the error code for required parameter errors | ||
14 | ParamRequiredErrCode = "ParamRequiredError" | ||
15 | // ParamMinValueErrCode is the error code for fields with too low of a | ||
16 | // number value. | ||
17 | ParamMinValueErrCode = "ParamMinValueError" | ||
18 | // ParamMinLenErrCode is the error code for fields without enough elements. | ||
19 | ParamMinLenErrCode = "ParamMinLenError" | ||
20 | ) | ||
21 | |||
22 | // Validator provides a way for types to perform validation logic on their | ||
23 | // input values that external code can use to determine if a type's values | ||
24 | // are valid. | ||
25 | type Validator interface { | ||
26 | Validate() error | ||
27 | } | ||
28 | |||
29 | // An ErrInvalidParams provides wrapping of invalid parameter errors found when | ||
30 | // validating API operation input parameters. | ||
31 | type ErrInvalidParams struct { | ||
32 | // Context is the base context of the invalid parameter group. | ||
33 | Context string | ||
34 | errs []ErrInvalidParam | ||
35 | } | ||
36 | |||
37 | // Add adds a new invalid parameter error to the collection of invalid | ||
38 | // parameters. The context of the invalid parameter will be updated to reflect | ||
39 | // this collection. | ||
40 | func (e *ErrInvalidParams) Add(err ErrInvalidParam) { | ||
41 | err.SetContext(e.Context) | ||
42 | e.errs = append(e.errs, err) | ||
43 | } | ||
44 | |||
45 | // AddNested adds the invalid parameter errors from another ErrInvalidParams | ||
46 | // value into this collection. The nested errors will have their nested context | ||
47 | // updated and base context to reflect the merging. | ||
48 | // | ||
49 | // Use for nested validations errors. | ||
50 | func (e *ErrInvalidParams) AddNested(nestedCtx string, nested ErrInvalidParams) { | ||
51 | for _, err := range nested.errs { | ||
52 | err.SetContext(e.Context) | ||
53 | err.AddNestedContext(nestedCtx) | ||
54 | e.errs = append(e.errs, err) | ||
55 | } | ||
56 | } | ||
57 | |||
58 | // Len returns the number of invalid parameter errors | ||
59 | func (e ErrInvalidParams) Len() int { | ||
60 | return len(e.errs) | ||
61 | } | ||
62 | |||
63 | // Code returns the code of the error | ||
64 | func (e ErrInvalidParams) Code() string { | ||
65 | return InvalidParameterErrCode | ||
66 | } | ||
67 | |||
68 | // Message returns the message of the error | ||
69 | func (e ErrInvalidParams) Message() string { | ||
70 | return fmt.Sprintf("%d validation error(s) found.", len(e.errs)) | ||
71 | } | ||
72 | |||
73 | // Error returns the string formatted form of the invalid parameters. | ||
74 | func (e ErrInvalidParams) Error() string { | ||
75 | w := &bytes.Buffer{} | ||
76 | fmt.Fprintf(w, "%s: %s\n", e.Code(), e.Message()) | ||
77 | |||
78 | for _, err := range e.errs { | ||
79 | fmt.Fprintf(w, "- %s\n", err.Message()) | ||
80 | } | ||
81 | |||
82 | return w.String() | ||
83 | } | ||
84 | |||
85 | // OrigErr returns the invalid parameters as a awserr.BatchedErrors value | ||
86 | func (e ErrInvalidParams) OrigErr() error { | ||
87 | return awserr.NewBatchError( | ||
88 | InvalidParameterErrCode, e.Message(), e.OrigErrs()) | ||
89 | } | ||
90 | |||
91 | // OrigErrs returns a slice of the invalid parameters | ||
92 | func (e ErrInvalidParams) OrigErrs() []error { | ||
93 | errs := make([]error, len(e.errs)) | ||
94 | for i := 0; i < len(errs); i++ { | ||
95 | errs[i] = e.errs[i] | ||
96 | } | ||
97 | |||
98 | return errs | ||
99 | } | ||
100 | |||
101 | // An ErrInvalidParam represents an invalid parameter error type. | ||
102 | type ErrInvalidParam interface { | ||
103 | awserr.Error | ||
104 | |||
105 | // Field name the error occurred on. | ||
106 | Field() string | ||
107 | |||
108 | // SetContext updates the context of the error. | ||
109 | SetContext(string) | ||
110 | |||
111 | // AddNestedContext updates the error's context to include a nested level. | ||
112 | AddNestedContext(string) | ||
113 | } | ||
114 | |||
115 | type errInvalidParam struct { | ||
116 | context string | ||
117 | nestedContext string | ||
118 | field string | ||
119 | code string | ||
120 | msg string | ||
121 | } | ||
122 | |||
123 | // Code returns the error code for the type of invalid parameter. | ||
124 | func (e *errInvalidParam) Code() string { | ||
125 | return e.code | ||
126 | } | ||
127 | |||
128 | // Message returns the reason the parameter was invalid, and its context. | ||
129 | func (e *errInvalidParam) Message() string { | ||
130 | return fmt.Sprintf("%s, %s.", e.msg, e.Field()) | ||
131 | } | ||
132 | |||
133 | // Error returns the string version of the invalid parameter error. | ||
134 | func (e *errInvalidParam) Error() string { | ||
135 | return fmt.Sprintf("%s: %s", e.code, e.Message()) | ||
136 | } | ||
137 | |||
138 | // OrigErr returns nil, Implemented for awserr.Error interface. | ||
139 | func (e *errInvalidParam) OrigErr() error { | ||
140 | return nil | ||
141 | } | ||
142 | |||
143 | // Field Returns the field and context the error occurred. | ||
144 | func (e *errInvalidParam) Field() string { | ||
145 | field := e.context | ||
146 | if len(field) > 0 { | ||
147 | field += "." | ||
148 | } | ||
149 | if len(e.nestedContext) > 0 { | ||
150 | field += fmt.Sprintf("%s.", e.nestedContext) | ||
151 | } | ||
152 | field += e.field | ||
153 | |||
154 | return field | ||
155 | } | ||
156 | |||
157 | // SetContext updates the base context of the error. | ||
158 | func (e *errInvalidParam) SetContext(ctx string) { | ||
159 | e.context = ctx | ||
160 | } | ||
161 | |||
162 | // AddNestedContext prepends a context to the field's path. | ||
163 | func (e *errInvalidParam) AddNestedContext(ctx string) { | ||
164 | if len(e.nestedContext) == 0 { | ||
165 | e.nestedContext = ctx | ||
166 | } else { | ||
167 | e.nestedContext = fmt.Sprintf("%s.%s", ctx, e.nestedContext) | ||
168 | } | ||
169 | |||
170 | } | ||
171 | |||
172 | // An ErrParamRequired represents an required parameter error. | ||
173 | type ErrParamRequired struct { | ||
174 | errInvalidParam | ||
175 | } | ||
176 | |||
177 | // NewErrParamRequired creates a new required parameter error. | ||
178 | func NewErrParamRequired(field string) *ErrParamRequired { | ||
179 | return &ErrParamRequired{ | ||
180 | errInvalidParam{ | ||
181 | code: ParamRequiredErrCode, | ||
182 | field: field, | ||
183 | msg: fmt.Sprintf("missing required field"), | ||
184 | }, | ||
185 | } | ||
186 | } | ||
187 | |||
188 | // An ErrParamMinValue represents a minimum value parameter error. | ||
189 | type ErrParamMinValue struct { | ||
190 | errInvalidParam | ||
191 | min float64 | ||
192 | } | ||
193 | |||
194 | // NewErrParamMinValue creates a new minimum value parameter error. | ||
195 | func NewErrParamMinValue(field string, min float64) *ErrParamMinValue { | ||
196 | return &ErrParamMinValue{ | ||
197 | errInvalidParam: errInvalidParam{ | ||
198 | code: ParamMinValueErrCode, | ||
199 | field: field, | ||
200 | msg: fmt.Sprintf("minimum field value of %v", min), | ||
201 | }, | ||
202 | min: min, | ||
203 | } | ||
204 | } | ||
205 | |||
206 | // MinValue returns the field's require minimum value. | ||
207 | // | ||
208 | // float64 is returned for both int and float min values. | ||
209 | func (e *ErrParamMinValue) MinValue() float64 { | ||
210 | return e.min | ||
211 | } | ||
212 | |||
213 | // An ErrParamMinLen represents a minimum length parameter error. | ||
214 | type ErrParamMinLen struct { | ||
215 | errInvalidParam | ||
216 | min int | ||
217 | } | ||
218 | |||
219 | // NewErrParamMinLen creates a new minimum length parameter error. | ||
220 | func NewErrParamMinLen(field string, min int) *ErrParamMinLen { | ||
221 | return &ErrParamMinLen{ | ||
222 | errInvalidParam: errInvalidParam{ | ||
223 | code: ParamMinValueErrCode, | ||
224 | field: field, | ||
225 | msg: fmt.Sprintf("minimum field size of %v", min), | ||
226 | }, | ||
227 | min: min, | ||
228 | } | ||
229 | } | ||
230 | |||
231 | // MinLen returns the field's required minimum length. | ||
232 | func (e *ErrParamMinLen) MinLen() int { | ||
233 | return e.min | ||
234 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go new file mode 100644 index 0000000..22d2f80 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go | |||
@@ -0,0 +1,287 @@ | |||
1 | package request | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "time" | ||
6 | |||
7 | "github.com/aws/aws-sdk-go/aws" | ||
8 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
9 | "github.com/aws/aws-sdk-go/aws/awsutil" | ||
10 | ) | ||
11 | |||
12 | // WaiterResourceNotReadyErrorCode is the error code returned by a waiter when | ||
13 | // the waiter's max attempts have been exhausted. | ||
14 | const WaiterResourceNotReadyErrorCode = "ResourceNotReady" | ||
15 | |||
16 | // A WaiterOption is a function that will update the Waiter value's fields to | ||
17 | // configure the waiter. | ||
18 | type WaiterOption func(*Waiter) | ||
19 | |||
20 | // WithWaiterMaxAttempts returns the maximum number of times the waiter should | ||
21 | // attempt to check the resource for the target state. | ||
22 | func WithWaiterMaxAttempts(max int) WaiterOption { | ||
23 | return func(w *Waiter) { | ||
24 | w.MaxAttempts = max | ||
25 | } | ||
26 | } | ||
27 | |||
28 | // WaiterDelay will return a delay the waiter should pause between attempts to | ||
29 | // check the resource state. The passed in attempt is the number of times the | ||
30 | // Waiter has checked the resource state. | ||
31 | // | ||
32 | // Attempt is the number of attempts the Waiter has made checking the resource | ||
33 | // state. | ||
34 | type WaiterDelay func(attempt int) time.Duration | ||
35 | |||
36 | // ConstantWaiterDelay returns a WaiterDelay that will always return a constant | ||
37 | // delay the waiter should use between attempts. It ignores the number of | ||
38 | // attempts made. | ||
39 | func ConstantWaiterDelay(delay time.Duration) WaiterDelay { | ||
40 | return func(attempt int) time.Duration { | ||
41 | return delay | ||
42 | } | ||
43 | } | ||
44 | |||
45 | // WithWaiterDelay will set the Waiter to use the WaiterDelay passed in. | ||
46 | func WithWaiterDelay(delayer WaiterDelay) WaiterOption { | ||
47 | return func(w *Waiter) { | ||
48 | w.Delay = delayer | ||
49 | } | ||
50 | } | ||
51 | |||
52 | // WithWaiterLogger returns a waiter option to set the logger a waiter | ||
53 | // should use to log warnings and errors to. | ||
54 | func WithWaiterLogger(logger aws.Logger) WaiterOption { | ||
55 | return func(w *Waiter) { | ||
56 | w.Logger = logger | ||
57 | } | ||
58 | } | ||
59 | |||
60 | // WithWaiterRequestOptions returns a waiter option setting the request | ||
61 | // options for each request the waiter makes. Appends to waiter's request | ||
62 | // options already set. | ||
63 | func WithWaiterRequestOptions(opts ...Option) WaiterOption { | ||
64 | return func(w *Waiter) { | ||
65 | w.RequestOptions = append(w.RequestOptions, opts...) | ||
66 | } | ||
67 | } | ||
68 | |||
69 | // A Waiter provides the functionality to perform a blocking call which will | ||
70 | // wait for a resource state to be satisfied by a service. | ||
71 | // | ||
72 | // This type should not be used directly. The API operations provided in the | ||
73 | // service packages prefixed with "WaitUntil" should be used instead. | ||
74 | type Waiter struct { | ||
75 | Name string | ||
76 | Acceptors []WaiterAcceptor | ||
77 | Logger aws.Logger | ||
78 | |||
79 | MaxAttempts int | ||
80 | Delay WaiterDelay | ||
81 | |||
82 | RequestOptions []Option | ||
83 | NewRequest func([]Option) (*Request, error) | ||
84 | } | ||
85 | |||
86 | // ApplyOptions updates the waiter with the list of waiter options provided. | ||
87 | func (w *Waiter) ApplyOptions(opts ...WaiterOption) { | ||
88 | for _, fn := range opts { | ||
89 | fn(w) | ||
90 | } | ||
91 | } | ||
92 | |||
93 | // WaiterState are states the waiter uses based on WaiterAcceptor definitions | ||
94 | // to identify if the resource state the waiter is waiting on has occurred. | ||
95 | type WaiterState int | ||
96 | |||
97 | // String returns the string representation of the waiter state. | ||
98 | func (s WaiterState) String() string { | ||
99 | switch s { | ||
100 | case SuccessWaiterState: | ||
101 | return "success" | ||
102 | case FailureWaiterState: | ||
103 | return "failure" | ||
104 | case RetryWaiterState: | ||
105 | return "retry" | ||
106 | default: | ||
107 | return "unknown waiter state" | ||
108 | } | ||
109 | } | ||
110 | |||
111 | // States the waiter acceptors will use to identify target resource states. | ||
112 | const ( | ||
113 | SuccessWaiterState WaiterState = iota // waiter successful | ||
114 | FailureWaiterState // waiter failed | ||
115 | RetryWaiterState // waiter needs to be retried | ||
116 | ) | ||
117 | |||
118 | // WaiterMatchMode is the mode that the waiter will use to match the WaiterAcceptor | ||
119 | // definition's Expected attribute. | ||
120 | type WaiterMatchMode int | ||
121 | |||
122 | // Modes the waiter will use when inspecting API response to identify target | ||
123 | // resource states. | ||
124 | const ( | ||
125 | PathAllWaiterMatch WaiterMatchMode = iota // match on all paths | ||
126 | PathWaiterMatch // match on specific path | ||
127 | PathAnyWaiterMatch // match on any path | ||
128 | PathListWaiterMatch // match on list of paths | ||
129 | StatusWaiterMatch // match on status code | ||
130 | ErrorWaiterMatch // match on error | ||
131 | ) | ||
132 | |||
133 | // String returns the string representation of the waiter match mode. | ||
134 | func (m WaiterMatchMode) String() string { | ||
135 | switch m { | ||
136 | case PathAllWaiterMatch: | ||
137 | return "pathAll" | ||
138 | case PathWaiterMatch: | ||
139 | return "path" | ||
140 | case PathAnyWaiterMatch: | ||
141 | return "pathAny" | ||
142 | case PathListWaiterMatch: | ||
143 | return "pathList" | ||
144 | case StatusWaiterMatch: | ||
145 | return "status" | ||
146 | case ErrorWaiterMatch: | ||
147 | return "error" | ||
148 | default: | ||
149 | return "unknown waiter match mode" | ||
150 | } | ||
151 | } | ||
152 | |||
153 | // WaitWithContext will make requests for the API operation using NewRequest to | ||
154 | // build API requests. The request's response will be compared against the | ||
155 | // Waiter's Acceptors to determine the successful state of the resource the | ||
156 | // waiter is inspecting. | ||
157 | // | ||
158 | // The passed in context must not be nil. If it is nil a panic will occur. The | ||
159 | // Context will be used to cancel the waiter's pending requests and retry delays. | ||
160 | // Use aws.BackgroundContext if no context is available. | ||
161 | // | ||
162 | // The waiter will continue until the target state defined by the Acceptors, | ||
163 | // or the max attempts expires. | ||
164 | // | ||
165 | // Will return the WaiterResourceNotReadyErrorCode error code if the waiter's | ||
166 | // retryer ShouldRetry returns false. This normally will happen when the max | ||
167 | // wait attempts expires. | ||
168 | func (w Waiter) WaitWithContext(ctx aws.Context) error { | ||
169 | |||
170 | for attempt := 1; ; attempt++ { | ||
171 | req, err := w.NewRequest(w.RequestOptions) | ||
172 | if err != nil { | ||
173 | waiterLogf(w.Logger, "unable to create request %v", err) | ||
174 | return err | ||
175 | } | ||
176 | req.Handlers.Build.PushBack(MakeAddToUserAgentFreeFormHandler("Waiter")) | ||
177 | err = req.Send() | ||
178 | |||
179 | // See if any of the acceptors match the request's response, or error | ||
180 | for _, a := range w.Acceptors { | ||
181 | if matched, matchErr := a.match(w.Name, w.Logger, req, err); matched { | ||
182 | return matchErr | ||
183 | } | ||
184 | } | ||
185 | |||
186 | // The Waiter should only check the resource state MaxAttempts times | ||
187 | // This is here instead of in the for loop above to prevent delaying | ||
188 | // unnecessary when the waiter will not retry. | ||
189 | if attempt == w.MaxAttempts { | ||
190 | break | ||
191 | } | ||
192 | |||
193 | // Delay to wait before inspecting the resource again | ||
194 | delay := w.Delay(attempt) | ||
195 | if sleepFn := req.Config.SleepDelay; sleepFn != nil { | ||
196 | // Support SleepDelay for backwards compatibility and testing | ||
197 | sleepFn(delay) | ||
198 | } else if err := aws.SleepWithContext(ctx, delay); err != nil { | ||
199 | return awserr.New(CanceledErrorCode, "waiter context canceled", err) | ||
200 | } | ||
201 | } | ||
202 | |||
203 | return awserr.New(WaiterResourceNotReadyErrorCode, "exceeded wait attempts", nil) | ||
204 | } | ||
205 | |||
206 | // A WaiterAcceptor provides the information needed to wait for an API operation | ||
207 | // to complete. | ||
208 | type WaiterAcceptor struct { | ||
209 | State WaiterState | ||
210 | Matcher WaiterMatchMode | ||
211 | Argument string | ||
212 | Expected interface{} | ||
213 | } | ||
214 | |||
215 | // match returns if the acceptor found a match with the passed in request | ||
216 | // or error. True is returned if the acceptor made a match, error is returned | ||
217 | // if there was an error attempting to perform the match. | ||
218 | func (a *WaiterAcceptor) match(name string, l aws.Logger, req *Request, err error) (bool, error) { | ||
219 | result := false | ||
220 | var vals []interface{} | ||
221 | |||
222 | switch a.Matcher { | ||
223 | case PathAllWaiterMatch, PathWaiterMatch: | ||
224 | // Require all matches to be equal for result to match | ||
225 | vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) | ||
226 | if len(vals) == 0 { | ||
227 | break | ||
228 | } | ||
229 | result = true | ||
230 | for _, val := range vals { | ||
231 | if !awsutil.DeepEqual(val, a.Expected) { | ||
232 | result = false | ||
233 | break | ||
234 | } | ||
235 | } | ||
236 | case PathAnyWaiterMatch: | ||
237 | // Only a single match needs to equal for the result to match | ||
238 | vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) | ||
239 | for _, val := range vals { | ||
240 | if awsutil.DeepEqual(val, a.Expected) { | ||
241 | result = true | ||
242 | break | ||
243 | } | ||
244 | } | ||
245 | case PathListWaiterMatch: | ||
246 | // ignored matcher | ||
247 | case StatusWaiterMatch: | ||
248 | s := a.Expected.(int) | ||
249 | result = s == req.HTTPResponse.StatusCode | ||
250 | case ErrorWaiterMatch: | ||
251 | if aerr, ok := err.(awserr.Error); ok { | ||
252 | result = aerr.Code() == a.Expected.(string) | ||
253 | } | ||
254 | default: | ||
255 | waiterLogf(l, "WARNING: Waiter %s encountered unexpected matcher: %s", | ||
256 | name, a.Matcher) | ||
257 | } | ||
258 | |||
259 | if !result { | ||
260 | // If there was no matching result found there is nothing more to do | ||
261 | // for this response, retry the request. | ||
262 | return false, nil | ||
263 | } | ||
264 | |||
265 | switch a.State { | ||
266 | case SuccessWaiterState: | ||
267 | // waiter completed | ||
268 | return true, nil | ||
269 | case FailureWaiterState: | ||
270 | // Waiter failure state triggered | ||
271 | return true, awserr.New(WaiterResourceNotReadyErrorCode, | ||
272 | "failed waiting for successful resource state", err) | ||
273 | case RetryWaiterState: | ||
274 | // clear the error and retry the operation | ||
275 | return false, nil | ||
276 | default: | ||
277 | waiterLogf(l, "WARNING: Waiter %s encountered unexpected state: %s", | ||
278 | name, a.State) | ||
279 | return false, nil | ||
280 | } | ||
281 | } | ||
282 | |||
283 | func waiterLogf(logger aws.Logger, msg string, args ...interface{}) { | ||
284 | if logger != nil { | ||
285 | logger.Log(fmt.Sprintf(msg, args...)) | ||
286 | } | ||
287 | } | ||