Update vendored aws-sdk-go
Signed-off-by: Samuel Karp <skarp@amazon.com>
This commit is contained in:
parent
b96e076af9
commit
70083e6fc3
32 changed files with 1519 additions and 611 deletions
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/Sirupsen/logrus"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/defaults"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
)
|
||||
|
@ -57,7 +58,7 @@ type byTimestamp []*cloudwatchlogs.InputLogEvent
|
|||
// init registers the awslogs driver and sets the default region, if provided
|
||||
func init() {
|
||||
if os.Getenv(regionEnvKey) != "" {
|
||||
aws.DefaultConfig.Region = aws.String(os.Getenv(regionEnvKey))
|
||||
defaults.DefaultConfig.Region = aws.String(os.Getenv(regionEnvKey))
|
||||
}
|
||||
if err := logger.RegisterLogDriver(name, New); err != nil {
|
||||
logrus.Fatal(err)
|
||||
|
@ -79,9 +80,9 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
|||
if ctx.Config[logStreamKey] != "" {
|
||||
logStreamName = ctx.Config[logStreamKey]
|
||||
}
|
||||
config := aws.DefaultConfig
|
||||
config := defaults.DefaultConfig
|
||||
if ctx.Config[regionKey] != "" {
|
||||
config = aws.DefaultConfig.Merge(&aws.Config{
|
||||
config = defaults.DefaultConfig.Merge(&aws.Config{
|
||||
Region: aws.String(ctx.Config[regionKey]),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ clone git github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c
|
|||
clone git gopkg.in/fsnotify.v1 v1.2.0
|
||||
|
||||
# awslogs deps
|
||||
clone git github.com/aws/aws-sdk-go v0.7.1
|
||||
clone git github.com/aws/aws-sdk-go v0.9.9
|
||||
clone git github.com/vaughan0/go-ini a98ad7ee00ec53921f08832bc06ecf7fd600e6a1
|
||||
|
||||
clean
|
||||
|
|
|
@ -113,7 +113,7 @@ func newRequestError(err Error, statusCode int, requestID string) *requestError
|
|||
// Error returns the string representation of the error.
|
||||
// Satisfies the error interface.
|
||||
func (r requestError) Error() string {
|
||||
extra := fmt.Sprintf("status code: %d, request id: [%s]",
|
||||
extra := fmt.Sprintf("status code: %d, request id: %s",
|
||||
r.statusCode, r.requestID)
|
||||
return SprintError(r.Code(), r.Message(), extra, r.OrigErr())
|
||||
}
|
||||
|
|
|
@ -2,48 +2,20 @@ package aws
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
)
|
||||
|
||||
// DefaultChainCredentials is a Credentials which will find the first available
|
||||
// credentials Value from the list of Providers.
|
||||
//
|
||||
// This should be used in the default case. Once the type of credentials are
|
||||
// known switching to the specific Credentials will be more efficient.
|
||||
var DefaultChainCredentials = credentials.NewChainCredentials(
|
||||
[]credentials.Provider{
|
||||
&credentials.EnvProvider{},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
|
||||
&credentials.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
|
||||
})
|
||||
|
||||
// The default number of retries for a service. The value of -1 indicates that
|
||||
// the service specific retry default will be used.
|
||||
const DefaultRetries = -1
|
||||
|
||||
// DefaultConfig is the default all service configuration will be based off of.
|
||||
// By default, all clients use this structure for initialization options unless
|
||||
// a custom configuration object is passed in.
|
||||
//
|
||||
// You may modify this global structure to change all default configuration
|
||||
// in the SDK. Note that configuration options are copied by value, so any
|
||||
// modifications must happen before constructing a client.
|
||||
var DefaultConfig = NewConfig().
|
||||
WithCredentials(DefaultChainCredentials).
|
||||
WithRegion(os.Getenv("AWS_REGION")).
|
||||
WithHTTPClient(http.DefaultClient).
|
||||
WithMaxRetries(DefaultRetries).
|
||||
WithLogger(NewDefaultLogger()).
|
||||
WithLogLevel(LogOff)
|
||||
|
||||
// A Config provides service configuration for service clients. By default,
|
||||
// all clients will use the {DefaultConfig} structure.
|
||||
// all clients will use the {defaults.DefaultConfig} structure.
|
||||
type Config struct {
|
||||
// The credentials object to use when signing requests. Defaults to
|
||||
// {DefaultChainCredentials}.
|
||||
// {defaults.DefaultChainCredentials}.
|
||||
Credentials *credentials.Credentials
|
||||
|
||||
// An optional endpoint URL (hostname only or fully qualified URI)
|
||||
|
@ -102,6 +74,8 @@ type Config struct {
|
|||
// @see http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html
|
||||
// Amazon S3: Virtual Hosting of Buckets
|
||||
S3ForcePathStyle *bool
|
||||
|
||||
SleepDelay func(time.Duration)
|
||||
}
|
||||
|
||||
// NewConfig returns a new Config pointer that can be chained with builder methods to
|
||||
|
@ -190,6 +164,13 @@ func (c *Config) WithS3ForcePathStyle(force bool) *Config {
|
|||
return c
|
||||
}
|
||||
|
||||
// WithSleepDelay overrides the function used to sleep while waiting for the
|
||||
// next retry. Defaults to time.Sleep.
|
||||
func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
|
||||
c.SleepDelay = fn
|
||||
return c
|
||||
}
|
||||
|
||||
// Merge returns a new Config with the other Config's attribute values merged into
|
||||
// this Config. If the other Config's attribute is nil it will not be merged into
|
||||
// the new Config to be returned.
|
||||
|
@ -244,6 +225,10 @@ func (c Config) Merge(other *Config) *Config {
|
|||
dst.S3ForcePathStyle = other.S3ForcePathStyle
|
||||
}
|
||||
|
||||
if other.SleepDelay != nil {
|
||||
dst.SleepDelay = other.SleepDelay
|
||||
}
|
||||
|
||||
return &dst
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package aws
|
||||
package corehandlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -9,15 +9,12 @@ import (
|
|||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
var sleepDelay = func(delay time.Duration) {
|
||||
time.Sleep(delay)
|
||||
}
|
||||
|
||||
// Interface for matching types which also have a Len method.
|
||||
type lener interface {
|
||||
Len() int
|
||||
|
@ -26,7 +23,7 @@ type lener interface {
|
|||
// BuildContentLength builds the content length of a request based on the body,
|
||||
// or will use the HTTPRequest.Header's "Content-Length" if defined. If unable
|
||||
// to determine request body length and no "Content-Length" was specified it will panic.
|
||||
func BuildContentLength(r *Request) {
|
||||
var BuildContentLengthHandler = request.NamedHandler{"core.BuildContentLengthHandler", func(r *request.Request) {
|
||||
if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
|
||||
length, _ := strconv.ParseInt(slength, 10, 64)
|
||||
r.HTTPRequest.ContentLength = length
|
||||
|
@ -40,27 +37,27 @@ func BuildContentLength(r *Request) {
|
|||
case lener:
|
||||
length = int64(body.Len())
|
||||
case io.Seeker:
|
||||
r.bodyStart, _ = body.Seek(0, 1)
|
||||
r.BodyStart, _ = body.Seek(0, 1)
|
||||
end, _ := body.Seek(0, 2)
|
||||
body.Seek(r.bodyStart, 0) // make sure to seek back to original location
|
||||
length = end - r.bodyStart
|
||||
body.Seek(r.BodyStart, 0) // make sure to seek back to original location
|
||||
length = end - r.BodyStart
|
||||
default:
|
||||
panic("Cannot get length of body, must provide `ContentLength`")
|
||||
}
|
||||
|
||||
r.HTTPRequest.ContentLength = length
|
||||
r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
|
||||
}
|
||||
}}
|
||||
|
||||
// UserAgentHandler is a request handler for injecting User agent into requests.
|
||||
func UserAgentHandler(r *Request) {
|
||||
r.HTTPRequest.Header.Set("User-Agent", SDKName+"/"+SDKVersion)
|
||||
}
|
||||
var UserAgentHandler = request.NamedHandler{"core.UserAgentHandler", func(r *request.Request) {
|
||||
r.HTTPRequest.Header.Set("User-Agent", aws.SDKName+"/"+aws.SDKVersion)
|
||||
}}
|
||||
|
||||
var reStatusCode = regexp.MustCompile(`^(\d+)`)
|
||||
var reStatusCode = regexp.MustCompile(`^(\d{3})`)
|
||||
|
||||
// SendHandler is a request handler to send service request using HTTP client.
|
||||
func SendHandler(r *Request) {
|
||||
var SendHandler = request.NamedHandler{"core.SendHandler", func(r *request.Request) {
|
||||
var err error
|
||||
r.HTTPResponse, err = r.Service.Config.HTTPClient.Do(r.HTTPRequest)
|
||||
if err != nil {
|
||||
|
@ -68,8 +65,8 @@ func SendHandler(r *Request) {
|
|||
// response. e.g. 301 without location header comes back as string
|
||||
// error and r.HTTPResponse is nil. Other url redirect errors will
|
||||
// comeback in a similar method.
|
||||
if e, ok := err.(*url.Error); ok {
|
||||
if s := reStatusCode.FindStringSubmatch(e.Error()); s != nil {
|
||||
if e, ok := err.(*url.Error); ok && e.Err != nil {
|
||||
if s := reStatusCode.FindStringSubmatch(e.Err.Error()); s != nil {
|
||||
code, _ := strconv.ParseInt(s[1], 10, 64)
|
||||
r.HTTPResponse = &http.Response{
|
||||
StatusCode: int(code),
|
||||
|
@ -79,7 +76,7 @@ func SendHandler(r *Request) {
|
|||
return
|
||||
}
|
||||
}
|
||||
if r.HTTPRequest == nil {
|
||||
if r.HTTPResponse == nil {
|
||||
// Add a dummy request response object to ensure the HTTPResponse
|
||||
// value is consistent.
|
||||
r.HTTPResponse = &http.Response{
|
||||
|
@ -90,68 +87,50 @@ func SendHandler(r *Request) {
|
|||
}
|
||||
// Catch all other request errors.
|
||||
r.Error = awserr.New("RequestError", "send request failed", err)
|
||||
r.Retryable = Bool(true) // network errors are retryable
|
||||
r.Retryable = aws.Bool(true) // network errors are retryable
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
// ValidateResponseHandler is a request handler to validate service response.
|
||||
func ValidateResponseHandler(r *Request) {
|
||||
var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler", func(r *request.Request) {
|
||||
if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 {
|
||||
// this may be replaced by an UnmarshalError handler
|
||||
r.Error = awserr.New("UnknownError", "unknown error", nil)
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
// AfterRetryHandler performs final checks to determine if the request should
|
||||
// be retried and how long to delay.
|
||||
func AfterRetryHandler(r *Request) {
|
||||
var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *request.Request) {
|
||||
// If one of the other handlers already set the retry state
|
||||
// we don't want to override it based on the service's state
|
||||
if r.Retryable == nil {
|
||||
r.Retryable = Bool(r.Service.ShouldRetry(r))
|
||||
r.Retryable = aws.Bool(r.ShouldRetry(r))
|
||||
}
|
||||
|
||||
if r.WillRetry() {
|
||||
r.RetryDelay = r.Service.RetryRules(r)
|
||||
sleepDelay(r.RetryDelay)
|
||||
r.RetryDelay = r.RetryRules(r)
|
||||
r.Service.Config.SleepDelay(r.RetryDelay)
|
||||
|
||||
// when the expired token exception occurs the credentials
|
||||
// need to be expired locally so that the next request to
|
||||
// get credentials will trigger a credentials refresh.
|
||||
if r.Error != nil {
|
||||
if err, ok := r.Error.(awserr.Error); ok {
|
||||
if isCodeExpiredCreds(err.Code()) {
|
||||
r.Config.Credentials.Expire()
|
||||
}
|
||||
}
|
||||
if r.IsErrorExpired() {
|
||||
r.Service.Config.Credentials.Expire()
|
||||
}
|
||||
|
||||
r.RetryCount++
|
||||
r.Error = nil
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrMissingRegion is an error that is returned if region configuration is
|
||||
// not found.
|
||||
//
|
||||
// @readonly
|
||||
ErrMissingRegion error = awserr.New("MissingRegion", "could not find region configuration", nil)
|
||||
|
||||
// ErrMissingEndpoint is an error that is returned if an endpoint cannot be
|
||||
// resolved for a service.
|
||||
//
|
||||
// @readonly
|
||||
ErrMissingEndpoint error = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil)
|
||||
)
|
||||
}}
|
||||
|
||||
// ValidateEndpointHandler is a request handler to validate a request had the
|
||||
// appropriate Region and Endpoint set. Will set r.Error if the endpoint or
|
||||
// region is not valid.
|
||||
func ValidateEndpointHandler(r *Request) {
|
||||
if r.Service.SigningRegion == "" && StringValue(r.Service.Config.Region) == "" {
|
||||
r.Error = ErrMissingRegion
|
||||
var ValidateEndpointHandler = request.NamedHandler{"core.ValidateEndpointHandler", func(r *request.Request) {
|
||||
if r.Service.SigningRegion == "" && aws.StringValue(r.Service.Config.Region) == "" {
|
||||
r.Error = aws.ErrMissingRegion
|
||||
} else if r.Service.Endpoint == "" {
|
||||
r.Error = ErrMissingEndpoint
|
||||
r.Error = aws.ErrMissingEndpoint
|
||||
}
|
||||
}
|
||||
}}
|
144
vendor/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
vendored
Normal file
144
vendor/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
package corehandlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// ValidateParameters is a request handler to validate the input parameters.
|
||||
// Validating parameters only has meaning if done prior to the request being sent.
|
||||
var ValidateParametersHandler = request.NamedHandler{"core.ValidateParametersHandler", func(r *request.Request) {
|
||||
if r.ParamsFilled() {
|
||||
v := validator{errors: []string{}}
|
||||
v.validateAny(reflect.ValueOf(r.Params), "")
|
||||
|
||||
if count := len(v.errors); count > 0 {
|
||||
format := "%d validation errors:\n- %s"
|
||||
msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- "))
|
||||
r.Error = awserr.New("InvalidParameter", msg, nil)
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
// A validator validates values. Collects validations errors which occurs.
|
||||
type validator struct {
|
||||
errors []string
|
||||
}
|
||||
|
||||
// validateAny will validate any struct, slice or map type. All validations
|
||||
// are also performed recursively for nested types.
|
||||
func (v *validator) validateAny(value reflect.Value, path string) {
|
||||
value = reflect.Indirect(value)
|
||||
if !value.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Struct:
|
||||
v.validateStruct(value, path)
|
||||
case reflect.Slice:
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i))
|
||||
}
|
||||
case reflect.Map:
|
||||
for _, n := range value.MapKeys() {
|
||||
v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validateStruct will validate the struct value's fields. If the structure has
|
||||
// nested types those types will be validated also.
|
||||
func (v *validator) validateStruct(value reflect.Value, path string) {
|
||||
prefix := "."
|
||||
if path == "" {
|
||||
prefix = ""
|
||||
}
|
||||
|
||||
for i := 0; i < value.Type().NumField(); i++ {
|
||||
f := value.Type().Field(i)
|
||||
if strings.ToLower(f.Name[0:1]) == f.Name[0:1] {
|
||||
continue
|
||||
}
|
||||
fvalue := value.FieldByName(f.Name)
|
||||
|
||||
err := validateField(f, fvalue, validateFieldRequired, validateFieldMin)
|
||||
if err != nil {
|
||||
v.errors = append(v.errors, fmt.Sprintf("%s: %s", err.Error(), path+prefix+f.Name))
|
||||
continue
|
||||
}
|
||||
|
||||
v.validateAny(fvalue, path+prefix+f.Name)
|
||||
}
|
||||
}
|
||||
|
||||
type validatorFunc func(f reflect.StructField, fvalue reflect.Value) error
|
||||
|
||||
func validateField(f reflect.StructField, fvalue reflect.Value, funcs ...validatorFunc) error {
|
||||
for _, fn := range funcs {
|
||||
if err := fn(f, fvalue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validates that a field has a valid value provided for required fields.
|
||||
func validateFieldRequired(f reflect.StructField, fvalue reflect.Value) error {
|
||||
if f.Tag.Get("required") == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch fvalue.Kind() {
|
||||
case reflect.Ptr, reflect.Slice, reflect.Map:
|
||||
if fvalue.IsNil() {
|
||||
return fmt.Errorf("missing required parameter")
|
||||
}
|
||||
default:
|
||||
if !fvalue.IsValid() {
|
||||
return fmt.Errorf("missing required parameter")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validates that if a value is provided for a field, that value must be at
|
||||
// least a minimum length.
|
||||
func validateFieldMin(f reflect.StructField, fvalue reflect.Value) error {
|
||||
minStr := f.Tag.Get("min")
|
||||
if minStr == "" {
|
||||
return nil
|
||||
}
|
||||
min, _ := strconv.ParseInt(minStr, 10, 64)
|
||||
|
||||
kind := fvalue.Kind()
|
||||
if kind == reflect.Ptr {
|
||||
if fvalue.IsNil() {
|
||||
return nil
|
||||
}
|
||||
fvalue = fvalue.Elem()
|
||||
}
|
||||
|
||||
switch fvalue.Kind() {
|
||||
case reflect.String:
|
||||
if int64(fvalue.Len()) < min {
|
||||
return fmt.Errorf("field too short, minimum length %d", min)
|
||||
}
|
||||
case reflect.Slice, reflect.Map:
|
||||
if fvalue.IsNil() {
|
||||
return nil
|
||||
}
|
||||
if int64(fvalue.Len()) < min {
|
||||
return fmt.Errorf("field too short, minimum length %d", min)
|
||||
}
|
||||
|
||||
// TODO min can also apply to number minimum value.
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,24 +1,25 @@
|
|||
package credentials
|
||||
package ec2rolecreds
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||
)
|
||||
|
||||
const metadataCredentialsEndpoint = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
|
||||
|
||||
// A EC2RoleProvider retrieves credentials from the EC2 service, and keeps track if
|
||||
// those credentials are expired.
|
||||
//
|
||||
// Example how to configure the EC2RoleProvider with custom http Client, Endpoint
|
||||
// or ExpiryWindow
|
||||
//
|
||||
// p := &credentials.EC2RoleProvider{
|
||||
// p := &ec2rolecreds.EC2RoleProvider{
|
||||
// // Pass in a custom timeout to be used when requesting
|
||||
// // IAM EC2 Role credentials.
|
||||
// Client: &http.Client{
|
||||
|
@ -32,13 +33,10 @@ const metadataCredentialsEndpoint = "http://169.254.169.254/latest/meta-data/iam
|
|||
// ExpiryWindow: 0,
|
||||
// }
|
||||
type EC2RoleProvider struct {
|
||||
Expiry
|
||||
credentials.Expiry
|
||||
|
||||
// Endpoint must be fully quantified URL
|
||||
Endpoint string
|
||||
|
||||
// HTTP client to use when connecting to EC2 service
|
||||
Client *http.Client
|
||||
// EC2Metadata client to use when connecting to EC2 metadata service
|
||||
Client *ec2metadata.Client
|
||||
|
||||
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
||||
// the credentials actually expiring. This is beneficial so race conditions
|
||||
|
@ -52,7 +50,7 @@ type EC2RoleProvider struct {
|
|||
ExpiryWindow time.Duration
|
||||
}
|
||||
|
||||
// NewEC2RoleCredentials returns a pointer to a new Credentials object
|
||||
// NewCredentials returns a pointer to a new Credentials object
|
||||
// wrapping the EC2RoleProvider.
|
||||
//
|
||||
// Takes a custom http.Client which can be configured for custom handling of
|
||||
|
@ -64,9 +62,8 @@ type EC2RoleProvider struct {
|
|||
// Window is the expiry window that will be subtracted from the expiry returned
|
||||
// by the role credential request. This is done so that the credentials will
|
||||
// expire sooner than their actual lifespan.
|
||||
func NewEC2RoleCredentials(client *http.Client, endpoint string, window time.Duration) *Credentials {
|
||||
return NewCredentials(&EC2RoleProvider{
|
||||
Endpoint: endpoint,
|
||||
func NewCredentials(client *ec2metadata.Client, window time.Duration) *credentials.Credentials {
|
||||
return credentials.NewCredentials(&EC2RoleProvider{
|
||||
Client: client,
|
||||
ExpiryWindow: window,
|
||||
})
|
||||
|
@ -75,32 +72,29 @@ func NewEC2RoleCredentials(client *http.Client, endpoint string, window time.Dur
|
|||
// Retrieve retrieves credentials from the EC2 service.
|
||||
// Error will be returned if the request fails, or unable to extract
|
||||
// the desired credentials.
|
||||
func (m *EC2RoleProvider) Retrieve() (Value, error) {
|
||||
func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
|
||||
if m.Client == nil {
|
||||
m.Client = http.DefaultClient
|
||||
}
|
||||
if m.Endpoint == "" {
|
||||
m.Endpoint = metadataCredentialsEndpoint
|
||||
m.Client = ec2metadata.New(nil)
|
||||
}
|
||||
|
||||
credsList, err := requestCredList(m.Client, m.Endpoint)
|
||||
credsList, err := requestCredList(m.Client)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
return credentials.Value{}, err
|
||||
}
|
||||
|
||||
if len(credsList) == 0 {
|
||||
return Value{}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil)
|
||||
return credentials.Value{}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil)
|
||||
}
|
||||
credsName := credsList[0]
|
||||
|
||||
roleCreds, err := requestCred(m.Client, m.Endpoint, credsName)
|
||||
roleCreds, err := requestCred(m.Client, credsName)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
return credentials.Value{}, err
|
||||
}
|
||||
|
||||
m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow)
|
||||
|
||||
return Value{
|
||||
return credentials.Value{
|
||||
AccessKeyID: roleCreds.AccessKeyID,
|
||||
SecretAccessKey: roleCreds.SecretAccessKey,
|
||||
SessionToken: roleCreds.Token,
|
||||
|
@ -110,29 +104,35 @@ func (m *EC2RoleProvider) Retrieve() (Value, error) {
|
|||
// A ec2RoleCredRespBody provides the shape for deserializing credential
|
||||
// request responses.
|
||||
type ec2RoleCredRespBody struct {
|
||||
// Success State
|
||||
Expiration time.Time
|
||||
AccessKeyID string
|
||||
SecretAccessKey string
|
||||
Token string
|
||||
|
||||
// Error state
|
||||
Code string
|
||||
Message string
|
||||
}
|
||||
|
||||
const iamSecurityCredsPath = "/iam/security-credentials"
|
||||
|
||||
// requestCredList requests a list of credentials from the EC2 service.
|
||||
// If there are no credentials, or there is an error making or receiving the request
|
||||
func requestCredList(client *http.Client, endpoint string) ([]string, error) {
|
||||
resp, err := client.Get(endpoint)
|
||||
func requestCredList(client *ec2metadata.Client) ([]string, error) {
|
||||
resp, err := client.GetMetadata(iamSecurityCredsPath)
|
||||
if err != nil {
|
||||
return nil, awserr.New("ListEC2Role", "failed to list EC2 Roles", err)
|
||||
return nil, awserr.New("EC2RoleRequestError", "failed to list EC2 Roles", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
credsList := []string{}
|
||||
s := bufio.NewScanner(resp.Body)
|
||||
s := bufio.NewScanner(strings.NewReader(resp))
|
||||
for s.Scan() {
|
||||
credsList = append(credsList, s.Text())
|
||||
}
|
||||
|
||||
if err := s.Err(); err != nil {
|
||||
return nil, awserr.New("ReadEC2Role", "failed to read list of EC2 Roles", err)
|
||||
return nil, awserr.New("SerializationError", "failed to read list of EC2 Roles", err)
|
||||
}
|
||||
|
||||
return credsList, nil
|
||||
|
@ -142,20 +142,26 @@ func requestCredList(client *http.Client, endpoint string) ([]string, error) {
|
|||
//
|
||||
// If the credentials cannot be found, or there is an error reading the response
|
||||
// and error will be returned.
|
||||
func requestCred(client *http.Client, endpoint, credsName string) (*ec2RoleCredRespBody, error) {
|
||||
resp, err := client.Get(endpoint + credsName)
|
||||
func requestCred(client *ec2metadata.Client, credsName string) (ec2RoleCredRespBody, error) {
|
||||
resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName))
|
||||
if err != nil {
|
||||
return nil, awserr.New("GetEC2RoleCredentials",
|
||||
fmt.Sprintf("failed to get %s EC2 Role credentials", credsName),
|
||||
err)
|
||||
return ec2RoleCredRespBody{},
|
||||
awserr.New("EC2RoleRequestError",
|
||||
fmt.Sprintf("failed to get %s EC2 Role credentials", credsName),
|
||||
err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respCreds := &ec2RoleCredRespBody{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(respCreds); err != nil {
|
||||
return nil, awserr.New("DecodeEC2RoleCredentials",
|
||||
fmt.Sprintf("failed to decode %s EC2 Role credentials", credsName),
|
||||
err)
|
||||
respCreds := ec2RoleCredRespBody{}
|
||||
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil {
|
||||
return ec2RoleCredRespBody{},
|
||||
awserr.New("SerializationError",
|
||||
fmt.Sprintf("failed to decode %s EC2 Role credentials", credsName),
|
||||
err)
|
||||
}
|
||||
|
||||
if respCreds.Code != "Success" {
|
||||
// If an error code was returned something failed requesting the role.
|
||||
return ec2RoleCredRespBody{}, awserr.New(respCreds.Code, respCreds.Message, nil)
|
||||
}
|
||||
|
||||
return respCreds, nil
|
|
@ -22,8 +22,12 @@ var (
|
|||
//
|
||||
// Profile ini file example: $HOME/.aws/credentials
|
||||
type SharedCredentialsProvider struct {
|
||||
// Path to the shared credentials file. If empty will default to current user's
|
||||
// home directory.
|
||||
// Path to the shared credentials file.
|
||||
//
|
||||
// If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the
|
||||
// env value is empty will default to current user's home directory.
|
||||
// Linux/OSX: "$HOME/.aws/credentials"
|
||||
// Windows: "%USERPROFILE%\.aws\credentials"
|
||||
Filename string
|
||||
|
||||
// AWS Profile to extract credentials from the shared credentials file. If empty
|
||||
|
@ -106,6 +110,10 @@ func loadProfile(filename, profile string) (Value, error) {
|
|||
// Will return an error if the user's home directory path cannot be found.
|
||||
func (p *SharedCredentialsProvider) filename() (string, error) {
|
||||
if p.Filename == "" {
|
||||
if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); p.Filename != "" {
|
||||
return p.Filename, nil
|
||||
}
|
||||
|
||||
homeDir := os.Getenv("HOME") // *nix
|
||||
if homeDir == "" { // Windows
|
||||
homeDir = os.Getenv("USERPROFILE")
|
||||
|
|
39
vendor/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
vendored
Normal file
39
vendor/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package defaults
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||
)
|
||||
|
||||
// DefaultChainCredentials is a Credentials which will find the first available
|
||||
// credentials Value from the list of Providers.
|
||||
//
|
||||
// This should be used in the default case. Once the type of credentials are
|
||||
// known switching to the specific Credentials will be more efficient.
|
||||
var DefaultChainCredentials = credentials.NewChainCredentials(
|
||||
[]credentials.Provider{
|
||||
&credentials.EnvProvider{},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
|
||||
&ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
|
||||
})
|
||||
|
||||
// DefaultConfig is the default all service configuration will be based off of.
|
||||
// By default, all clients use this structure for initialization options unless
|
||||
// a custom configuration object is passed in.
|
||||
//
|
||||
// You may modify this global structure to change all default configuration
|
||||
// in the SDK. Note that configuration options are copied by value, so any
|
||||
// modifications must happen before constructing a client.
|
||||
var DefaultConfig = aws.NewConfig().
|
||||
WithCredentials(DefaultChainCredentials).
|
||||
WithRegion(os.Getenv("AWS_REGION")).
|
||||
WithHTTPClient(http.DefaultClient).
|
||||
WithMaxRetries(aws.DefaultRetries).
|
||||
WithLogger(aws.NewDefaultLogger()).
|
||||
WithLogLevel(aws.LogOff).
|
||||
WithSleepDelay(time.Sleep)
|
43
vendor/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
vendored
Normal file
43
vendor/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package ec2metadata
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// GetMetadata uses the path provided to request
|
||||
func (c *Client) GetMetadata(p string) (string, error) {
|
||||
op := &request.Operation{
|
||||
Name: "GetMetadata",
|
||||
HTTPMethod: "GET",
|
||||
HTTPPath: path.Join("/", "meta-data", p),
|
||||
}
|
||||
|
||||
output := &metadataOutput{}
|
||||
req := request.New(c.Service.ServiceInfo, c.Service.Handlers, c.Service.Retryer, op, nil, output)
|
||||
|
||||
return output.Content, req.Send()
|
||||
}
|
||||
|
||||
// Region returns the region the instance is running in.
|
||||
func (c *Client) Region() (string, error) {
|
||||
resp, err := c.GetMetadata("placement/availability-zone")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// returns region without the suffix. Eg: us-west-2a becomes us-west-2
|
||||
return resp[:len(resp)-1], nil
|
||||
}
|
||||
|
||||
// Available returns if the application has access to the EC2 Metadata service.
|
||||
// Can be used to determine if application is running within an EC2 Instance and
|
||||
// the metadata service is available.
|
||||
func (c *Client) Available() bool {
|
||||
if _, err := c.GetMetadata("instance-id"); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
135
vendor/src/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
vendored
Normal file
135
vendor/src/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
package ec2metadata
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/service"
|
||||
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||
)
|
||||
|
||||
// DefaultRetries states the default number of times the service client will
|
||||
// attempt to retry a failed request before failing.
|
||||
const DefaultRetries = 3
|
||||
|
||||
// A Config provides the configuration for the EC2 Metadata service.
|
||||
type Config struct {
|
||||
// An optional endpoint URL (hostname only or fully qualified URI)
|
||||
// that overrides the default service endpoint for a client. Set this
|
||||
// to nil, or `""` to use the default service endpoint.
|
||||
Endpoint *string
|
||||
|
||||
// The HTTP client to use when sending requests. Defaults to
|
||||
// `http.DefaultClient`.
|
||||
HTTPClient *http.Client
|
||||
|
||||
// An integer value representing the logging level. The default log level
|
||||
// is zero (LogOff), which represents no logging. To enable logging set
|
||||
// to a LogLevel Value.
|
||||
Logger aws.Logger
|
||||
|
||||
// The logger writer interface to write logging messages to. Defaults to
|
||||
// standard out.
|
||||
LogLevel *aws.LogLevelType
|
||||
|
||||
// The maximum number of times that a request will be retried for failures.
|
||||
// Defaults to DefaultRetries for the number of retries to be performed
|
||||
// per request.
|
||||
MaxRetries *int
|
||||
}
|
||||
|
||||
// A Client is an EC2 Metadata service Client.
|
||||
type Client struct {
|
||||
*service.Service
|
||||
}
|
||||
|
||||
// New creates a new instance of the EC2 Metadata service client.
|
||||
//
|
||||
// In the general use case the configuration for this service client should not
|
||||
// be needed and `nil` can be provided. Configuration is only needed if the
|
||||
// `ec2metadata.Config` defaults need to be overridden. Eg. Setting LogLevel.
|
||||
//
|
||||
// @note This configuration will NOT be merged with the default AWS service
|
||||
// client configuration `defaults.DefaultConfig`. Due to circular dependencies
|
||||
// with the defaults package and credentials EC2 Role Provider.
|
||||
func New(config *Config) *Client {
|
||||
service := &service.Service{
|
||||
ServiceInfo: serviceinfo.ServiceInfo{
|
||||
Config: copyConfig(config),
|
||||
ServiceName: "Client",
|
||||
Endpoint: "http://169.254.169.254/latest",
|
||||
APIVersion: "latest",
|
||||
},
|
||||
}
|
||||
service.Initialize()
|
||||
service.Handlers.Unmarshal.PushBack(unmarshalHandler)
|
||||
service.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||
service.Handlers.Validate.Clear()
|
||||
service.Handlers.Validate.PushBack(validateEndpointHandler)
|
||||
|
||||
return &Client{service}
|
||||
}
|
||||
|
||||
func copyConfig(config *Config) *aws.Config {
|
||||
if config == nil {
|
||||
config = &Config{}
|
||||
}
|
||||
c := &aws.Config{
|
||||
Credentials: credentials.AnonymousCredentials,
|
||||
Endpoint: config.Endpoint,
|
||||
HTTPClient: config.HTTPClient,
|
||||
Logger: config.Logger,
|
||||
LogLevel: config.LogLevel,
|
||||
MaxRetries: config.MaxRetries,
|
||||
}
|
||||
|
||||
if c.HTTPClient == nil {
|
||||
c.HTTPClient = http.DefaultClient
|
||||
}
|
||||
if c.Logger == nil {
|
||||
c.Logger = aws.NewDefaultLogger()
|
||||
}
|
||||
if c.LogLevel == nil {
|
||||
c.LogLevel = aws.LogLevel(aws.LogOff)
|
||||
}
|
||||
if c.MaxRetries == nil {
|
||||
c.MaxRetries = aws.Int(DefaultRetries)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type metadataOutput struct {
|
||||
Content string
|
||||
}
|
||||
|
||||
func unmarshalHandler(r *request.Request) {
|
||||
defer r.HTTPResponse.Body.Close()
|
||||
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
||||
if err != nil {
|
||||
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err)
|
||||
}
|
||||
|
||||
data := r.Data.(*metadataOutput)
|
||||
data.Content = string(b)
|
||||
}
|
||||
|
||||
func unmarshalError(r *request.Request) {
|
||||
defer r.HTTPResponse.Body.Close()
|
||||
_, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
||||
if err != nil {
|
||||
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err)
|
||||
}
|
||||
|
||||
// TODO extract the error...
|
||||
}
|
||||
|
||||
func validateEndpointHandler(r *request.Request) {
|
||||
if r.Service.Endpoint == "" {
|
||||
r.Error = aws.ErrMissingEndpoint
|
||||
}
|
||||
}
|
17
vendor/src/github.com/aws/aws-sdk-go/aws/errors.go
vendored
Normal file
17
vendor/src/github.com/aws/aws-sdk-go/aws/errors.go
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
package aws
|
||||
|
||||
import "github.com/aws/aws-sdk-go/aws/awserr"
|
||||
|
||||
var (
|
||||
// ErrMissingRegion is an error that is returned if region configuration is
|
||||
// not found.
|
||||
//
|
||||
// @readonly
|
||||
ErrMissingRegion error = awserr.New("MissingRegion", "could not find region configuration", nil)
|
||||
|
||||
// ErrMissingEndpoint is an error that is returned if an endpoint cannot be
|
||||
// resolved for a service.
|
||||
//
|
||||
// @readonly
|
||||
ErrMissingEndpoint error = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil)
|
||||
)
|
|
@ -62,6 +62,15 @@ const (
|
|||
// see the body content of requests and responses made while using the SDK
|
||||
// Will also enable LogDebug.
|
||||
LogDebugWithHTTPBody
|
||||
|
||||
// LogDebugWithRequestRetries states the SDK should log when service requests will
|
||||
// be retried. This should be used to log when you want to log when service
|
||||
// requests are being retried. Will also enable LogDebug.
|
||||
LogDebugWithRequestRetries
|
||||
|
||||
// LogDebugWithRequestErrors states the SDK should log when service requests fail
|
||||
// to build, send, validate, or unmarshal.
|
||||
LogDebugWithRequestErrors
|
||||
)
|
||||
|
||||
// A Logger is a minimalistic interface for the SDK to log messages to. Should
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
)
|
||||
|
||||
// ValidateParameters is a request handler to validate the input parameters.
|
||||
// Validating parameters only has meaning if done prior to the request being sent.
|
||||
func ValidateParameters(r *Request) {
|
||||
if r.ParamsFilled() {
|
||||
v := validator{errors: []string{}}
|
||||
v.validateAny(reflect.ValueOf(r.Params), "")
|
||||
|
||||
if count := len(v.errors); count > 0 {
|
||||
format := "%d validation errors:\n- %s"
|
||||
msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- "))
|
||||
r.Error = awserr.New("InvalidParameter", msg, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A validator validates values. Collects validations errors which occurs.
|
||||
type validator struct {
|
||||
errors []string
|
||||
}
|
||||
|
||||
// validateAny will validate any struct, slice or map type. All validations
|
||||
// are also performed recursively for nested types.
|
||||
func (v *validator) validateAny(value reflect.Value, path string) {
|
||||
value = reflect.Indirect(value)
|
||||
if !value.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Struct:
|
||||
v.validateStruct(value, path)
|
||||
case reflect.Slice:
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i))
|
||||
}
|
||||
case reflect.Map:
|
||||
for _, n := range value.MapKeys() {
|
||||
v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validateStruct will validate the struct value's fields. If the structure has
|
||||
// nested types those types will be validated also.
|
||||
func (v *validator) validateStruct(value reflect.Value, path string) {
|
||||
prefix := "."
|
||||
if path == "" {
|
||||
prefix = ""
|
||||
}
|
||||
|
||||
for i := 0; i < value.Type().NumField(); i++ {
|
||||
f := value.Type().Field(i)
|
||||
if strings.ToLower(f.Name[0:1]) == f.Name[0:1] {
|
||||
continue
|
||||
}
|
||||
fvalue := value.FieldByName(f.Name)
|
||||
|
||||
notset := false
|
||||
if f.Tag.Get("required") != "" {
|
||||
switch fvalue.Kind() {
|
||||
case reflect.Ptr, reflect.Slice, reflect.Map:
|
||||
if fvalue.IsNil() {
|
||||
notset = true
|
||||
}
|
||||
default:
|
||||
if !fvalue.IsValid() {
|
||||
notset = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if notset {
|
||||
msg := "missing required parameter: " + path + prefix + f.Name
|
||||
v.errors = append(v.errors, msg)
|
||||
} else {
|
||||
v.validateAny(fvalue, path+prefix+f.Name)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package aws
|
||||
package request
|
||||
|
||||
// A Handlers provides a collection of request handlers for various
|
||||
// stages of handling requests.
|
||||
|
@ -15,8 +15,8 @@ type Handlers struct {
|
|||
AfterRetry HandlerList
|
||||
}
|
||||
|
||||
// copy returns of this handler's lists.
|
||||
func (h *Handlers) copy() Handlers {
|
||||
// Copy returns of this handler's lists.
|
||||
func (h *Handlers) Copy() Handlers {
|
||||
return Handlers{
|
||||
Validate: h.Validate.copy(),
|
||||
Build: h.Build.copy(),
|
||||
|
@ -47,19 +47,25 @@ func (h *Handlers) Clear() {
|
|||
|
||||
// A HandlerList manages zero or more handlers in a list.
|
||||
type HandlerList struct {
|
||||
list []func(*Request)
|
||||
list []NamedHandler
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var n HandlerList
|
||||
n.list = append([]func(*Request){}, l.list...)
|
||||
n.list = append([]NamedHandler{}, l.list...)
|
||||
return n
|
||||
}
|
||||
|
||||
// Clear clears the handler list.
|
||||
func (l *HandlerList) Clear() {
|
||||
l.list = []func(*Request){}
|
||||
l.list = []NamedHandler{}
|
||||
}
|
||||
|
||||
// Len returns the number of handlers in the list.
|
||||
|
@ -67,19 +73,40 @@ func (l *HandlerList) Len() int {
|
|||
return len(l.list)
|
||||
}
|
||||
|
||||
// PushBack pushes handlers f to the back of the handler list.
|
||||
func (l *HandlerList) PushBack(f ...func(*Request)) {
|
||||
l.list = append(l.list, f...)
|
||||
// PushBack pushes handler f to the back of the handler list.
|
||||
func (l *HandlerList) PushBack(f func(*Request)) {
|
||||
l.list = append(l.list, NamedHandler{"__anonymous", f})
|
||||
}
|
||||
|
||||
// PushFront pushes handlers f to the front of the handler list.
|
||||
func (l *HandlerList) PushFront(f ...func(*Request)) {
|
||||
l.list = append(f, l.list...)
|
||||
// PushFront pushes handler f to the front of the handler list.
|
||||
func (l *HandlerList) PushFront(f func(*Request)) {
|
||||
l.list = append([]NamedHandler{{"__anonymous", f}}, l.list...)
|
||||
}
|
||||
|
||||
// PushBackNamed pushes named handler f to the back of the handler list.
|
||||
func (l *HandlerList) PushBackNamed(n NamedHandler) {
|
||||
l.list = append(l.list, n)
|
||||
}
|
||||
|
||||
// PushFrontNamed pushes named handler f to the front of the handler list.
|
||||
func (l *HandlerList) PushFrontNamed(n NamedHandler) {
|
||||
l.list = append([]NamedHandler{n}, l.list...)
|
||||
}
|
||||
|
||||
// Remove removes a NamedHandler n
|
||||
func (l *HandlerList) Remove(n NamedHandler) {
|
||||
newlist := []NamedHandler{}
|
||||
for _, m := range l.list {
|
||||
if m.Name != n.Name {
|
||||
newlist = append(newlist, m)
|
||||
}
|
||||
}
|
||||
l.list = newlist
|
||||
}
|
||||
|
||||
// Run executes all handlers in the list with a given request object.
|
||||
func (l *HandlerList) Run(r *Request) {
|
||||
for _, f := range l.list {
|
||||
f(r)
|
||||
f.Fn(r)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package aws
|
||||
package request
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -10,12 +11,15 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||
)
|
||||
|
||||
// A Request is the service request to be made.
|
||||
type Request struct {
|
||||
*Service
|
||||
Retryer
|
||||
Service serviceinfo.ServiceInfo
|
||||
Handlers Handlers
|
||||
Time time.Time
|
||||
ExpireTime time.Duration
|
||||
|
@ -23,7 +27,7 @@ type Request struct {
|
|||
HTTPRequest *http.Request
|
||||
HTTPResponse *http.Response
|
||||
Body io.ReadSeeker
|
||||
bodyStart int64 // offset from beginning of Body that the request body starts
|
||||
BodyStart int64 // offset from beginning of Body that the request body starts
|
||||
Params interface{}
|
||||
Error error
|
||||
Data interface{}
|
||||
|
@ -51,13 +55,13 @@ type Paginator struct {
|
|||
TruncationToken string
|
||||
}
|
||||
|
||||
// NewRequest returns a new Request pointer for the service API
|
||||
// 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 NewRequest(service *Service, operation *Operation, params interface{}, data interface{}) *Request {
|
||||
func New(service serviceinfo.ServiceInfo, handlers Handlers, retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request {
|
||||
method := operation.HTTPMethod
|
||||
if method == "" {
|
||||
method = "POST"
|
||||
|
@ -71,8 +75,9 @@ func NewRequest(service *Service, operation *Operation, params interface{}, data
|
|||
httpReq.URL, _ = url.Parse(service.Endpoint + p)
|
||||
|
||||
r := &Request{
|
||||
Retryer: retryer,
|
||||
Service: service,
|
||||
Handlers: service.Handlers.copy(),
|
||||
Handlers: handlers.Copy(),
|
||||
Time: time.Now(),
|
||||
ExpireTime: 0,
|
||||
Operation: operation,
|
||||
|
@ -89,7 +94,7 @@ func NewRequest(service *Service, operation *Operation, params interface{}, data
|
|||
|
||||
// WillRetry returns if the request's can be retried.
|
||||
func (r *Request) WillRetry() bool {
|
||||
return r.Error != nil && BoolValue(r.Retryable) && r.RetryCount < r.Service.MaxRetries()
|
||||
return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries()
|
||||
}
|
||||
|
||||
// ParamsFilled returns if the request's parameters have been populated
|
||||
|
@ -134,6 +139,20 @@ func (r *Request) Presign(expireTime time.Duration) (string, error) {
|
|||
return r.HTTPRequest.URL.String(), nil
|
||||
}
|
||||
|
||||
func debugLogReqError(r *Request, stage string, retrying bool, err error) {
|
||||
if !r.Service.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) {
|
||||
return
|
||||
}
|
||||
|
||||
retryStr := "not retrying"
|
||||
if retrying {
|
||||
retryStr = "will retry"
|
||||
}
|
||||
|
||||
r.Service.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v",
|
||||
stage, r.Service.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.
|
||||
// Anny additional build Handlers set on this request will be run
|
||||
|
@ -149,6 +168,7 @@ func (r *Request) Build() error {
|
|||
r.Error = nil
|
||||
r.Handlers.Validate.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Validate Request", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
r.Handlers.Build.Run(r)
|
||||
|
@ -165,6 +185,7 @@ func (r *Request) Build() error {
|
|||
func (r *Request) Sign() error {
|
||||
r.Build()
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Build Request", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
|
||||
|
@ -183,42 +204,57 @@ func (r *Request) Send() error {
|
|||
return r.Error
|
||||
}
|
||||
|
||||
if BoolValue(r.Retryable) {
|
||||
if aws.BoolValue(r.Retryable) {
|
||||
if r.Service.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
|
||||
r.Service.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
|
||||
r.Service.ServiceName, r.Operation.Name, r.RetryCount))
|
||||
}
|
||||
|
||||
// Re-seek the body back to the original point in for a retry so that
|
||||
// send will send the body's contents again in the upcoming request.
|
||||
r.Body.Seek(r.bodyStart, 0)
|
||||
r.Body.Seek(r.BodyStart, 0)
|
||||
r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
|
||||
}
|
||||
r.Retryable = nil
|
||||
|
||||
r.Handlers.Send.Run(r)
|
||||
if r.Error != nil {
|
||||
err := r.Error
|
||||
r.Handlers.Retry.Run(r)
|
||||
r.Handlers.AfterRetry.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Send Request", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
debugLogReqError(r, "Send Request", true, err)
|
||||
continue
|
||||
}
|
||||
|
||||
r.Handlers.UnmarshalMeta.Run(r)
|
||||
r.Handlers.ValidateResponse.Run(r)
|
||||
if r.Error != nil {
|
||||
err := r.Error
|
||||
r.Handlers.UnmarshalError.Run(r)
|
||||
r.Handlers.Retry.Run(r)
|
||||
r.Handlers.AfterRetry.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Validate Response", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
debugLogReqError(r, "Validate Response", true, err)
|
||||
continue
|
||||
}
|
||||
|
||||
r.Handlers.Unmarshal.Run(r)
|
||||
if r.Error != nil {
|
||||
err := r.Error
|
||||
r.Handlers.Retry.Run(r)
|
||||
r.Handlers.AfterRetry.Run(r)
|
||||
if r.Error != nil {
|
||||
debugLogReqError(r, "Unmarshal Response", false, r.Error)
|
||||
return r.Error
|
||||
}
|
||||
debugLogReqError(r, "Unmarshal Response", true, err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -279,7 +315,7 @@ func (r *Request) NextPage() *Request {
|
|||
}
|
||||
|
||||
data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface()
|
||||
nr := NewRequest(r.Service, r.Operation, awsutil.CopyOf(r.Params), data)
|
||||
nr := New(r.Service, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data)
|
||||
for i, intok := range nr.Operation.InputTokens {
|
||||
awsutil.SetValueAtAnyPath(nr.Params, intok, tokens[i])
|
||||
}
|
71
vendor/src/github.com/aws/aws-sdk-go/aws/request/retryer.go
vendored
Normal file
71
vendor/src/github.com/aws/aws-sdk-go/aws/request/retryer.go
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"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 service.DefaultRetryer
|
||||
// structure, which contains basic retry logic using exponential backoff.
|
||||
type Retryer interface {
|
||||
RetryRules(*Request) time.Duration
|
||||
ShouldRetry(*Request) bool
|
||||
MaxRetries() uint
|
||||
}
|
||||
|
||||
// retryableCodes is a collection of service response codes which are retry-able
|
||||
// without any further action.
|
||||
var retryableCodes = map[string]struct{}{
|
||||
"RequestError": {},
|
||||
"ProvisionedThroughputExceededException": {},
|
||||
"Throttling": {},
|
||||
"ThrottlingException": {},
|
||||
"RequestLimitExceeded": {},
|
||||
"RequestThrottled": {},
|
||||
}
|
||||
|
||||
// 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 isCodeRetryable(code string) bool {
|
||||
if _, ok := retryableCodes[code]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
return isCodeExpiredCreds(code)
|
||||
}
|
||||
|
||||
func isCodeExpiredCreds(code string) bool {
|
||||
_, ok := credsExpiredCodes[code]
|
||||
return ok
|
||||
}
|
||||
|
||||
// IsErrorRetryable returns whether the error is retryable, based on its Code.
|
||||
// Returns false if the request has no Error set.
|
||||
func (r *Request) IsErrorRetryable() bool {
|
||||
if r.Error != nil {
|
||||
if err, ok := r.Error.(awserr.Error); ok {
|
||||
return isCodeRetryable(err.Code())
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsErrorExpired returns whether the error code is a credential expiry error.
|
||||
// Returns false if the request has no Error set.
|
||||
func (r *Request) IsErrorExpired() bool {
|
||||
if r.Error != nil {
|
||||
if err, ok := r.Error.(awserr.Error); ok {
|
||||
return isCodeExpiredCreds(err.Code())
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
194
vendor/src/github.com/aws/aws-sdk-go/aws/service.go
vendored
194
vendor/src/github.com/aws/aws-sdk-go/aws/service.go
vendored
|
@ -1,194 +0,0 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/internal/endpoints"
|
||||
)
|
||||
|
||||
// A Service implements the base service request and response handling
|
||||
// used by all services.
|
||||
type Service struct {
|
||||
Config *Config
|
||||
Handlers Handlers
|
||||
ServiceName string
|
||||
APIVersion string
|
||||
Endpoint string
|
||||
SigningName string
|
||||
SigningRegion string
|
||||
JSONVersion string
|
||||
TargetPrefix string
|
||||
RetryRules func(*Request) time.Duration
|
||||
ShouldRetry func(*Request) bool
|
||||
DefaultMaxRetries uint
|
||||
}
|
||||
|
||||
var schemeRE = regexp.MustCompile("^([^:]+)://")
|
||||
|
||||
// NewService will return a pointer to a new Server object initialized.
|
||||
func NewService(config *Config) *Service {
|
||||
svc := &Service{Config: config}
|
||||
svc.Initialize()
|
||||
return svc
|
||||
}
|
||||
|
||||
// Initialize initializes the service.
|
||||
func (s *Service) Initialize() {
|
||||
if s.Config == nil {
|
||||
s.Config = &Config{}
|
||||
}
|
||||
if s.Config.HTTPClient == nil {
|
||||
s.Config.HTTPClient = http.DefaultClient
|
||||
}
|
||||
|
||||
if s.RetryRules == nil {
|
||||
s.RetryRules = retryRules
|
||||
}
|
||||
|
||||
if s.ShouldRetry == nil {
|
||||
s.ShouldRetry = shouldRetry
|
||||
}
|
||||
|
||||
s.DefaultMaxRetries = 3
|
||||
s.Handlers.Validate.PushBack(ValidateEndpointHandler)
|
||||
s.Handlers.Build.PushBack(UserAgentHandler)
|
||||
s.Handlers.Sign.PushBack(BuildContentLength)
|
||||
s.Handlers.Send.PushBack(SendHandler)
|
||||
s.Handlers.AfterRetry.PushBack(AfterRetryHandler)
|
||||
s.Handlers.ValidateResponse.PushBack(ValidateResponseHandler)
|
||||
s.AddDebugHandlers()
|
||||
s.buildEndpoint()
|
||||
|
||||
if !BoolValue(s.Config.DisableParamValidation) {
|
||||
s.Handlers.Validate.PushBack(ValidateParameters)
|
||||
}
|
||||
}
|
||||
|
||||
// buildEndpoint builds the endpoint values the service will use to make requests with.
|
||||
func (s *Service) buildEndpoint() {
|
||||
if StringValue(s.Config.Endpoint) != "" {
|
||||
s.Endpoint = *s.Config.Endpoint
|
||||
} else {
|
||||
s.Endpoint, s.SigningRegion =
|
||||
endpoints.EndpointForRegion(s.ServiceName, StringValue(s.Config.Region))
|
||||
}
|
||||
|
||||
if s.Endpoint != "" && !schemeRE.MatchString(s.Endpoint) {
|
||||
scheme := "https"
|
||||
if BoolValue(s.Config.DisableSSL) {
|
||||
scheme = "http"
|
||||
}
|
||||
s.Endpoint = scheme + "://" + s.Endpoint
|
||||
}
|
||||
}
|
||||
|
||||
// AddDebugHandlers injects debug logging handlers into the service to log request
|
||||
// debug information.
|
||||
func (s *Service) AddDebugHandlers() {
|
||||
if !s.Config.LogLevel.AtLeast(LogDebug) {
|
||||
return
|
||||
}
|
||||
|
||||
s.Handlers.Send.PushFront(logRequest)
|
||||
s.Handlers.Send.PushBack(logResponse)
|
||||
}
|
||||
|
||||
const logReqMsg = `DEBUG: Request %s/%s Details:
|
||||
---[ REQUEST POST-SIGN ]-----------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logRequest(r *Request) {
|
||||
logBody := r.Config.LogLevel.Matches(LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
|
||||
|
||||
r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ServiceName, r.Operation.Name, string(dumpedBody)))
|
||||
}
|
||||
|
||||
const logRespMsg = `DEBUG: Response %s/%s Details:
|
||||
---[ RESPONSE ]--------------------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logResponse(r *Request) {
|
||||
var msg = "no reponse data"
|
||||
if r.HTTPResponse != nil {
|
||||
logBody := r.Config.LogLevel.Matches(LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
|
||||
msg = string(dumpedBody)
|
||||
} else if r.Error != nil {
|
||||
msg = r.Error.Error()
|
||||
}
|
||||
r.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.ServiceName, r.Operation.Name, msg))
|
||||
}
|
||||
|
||||
// MaxRetries returns the number of maximum returns the service will use to make
|
||||
// an individual API request.
|
||||
func (s *Service) MaxRetries() uint {
|
||||
if IntValue(s.Config.MaxRetries) < 0 {
|
||||
return s.DefaultMaxRetries
|
||||
}
|
||||
return uint(IntValue(s.Config.MaxRetries))
|
||||
}
|
||||
|
||||
var seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
// retryRules returns the delay duration before retrying this request again
|
||||
func retryRules(r *Request) time.Duration {
|
||||
|
||||
delay := int(math.Pow(2, float64(r.RetryCount))) * (seededRand.Intn(30) + 30)
|
||||
return time.Duration(delay) * time.Millisecond
|
||||
}
|
||||
|
||||
// retryableCodes is a collection of service response codes which are retry-able
|
||||
// without any further action.
|
||||
var retryableCodes = map[string]struct{}{
|
||||
"RequestError": {},
|
||||
"ProvisionedThroughputExceededException": {},
|
||||
"Throttling": {},
|
||||
"ThrottlingException": {},
|
||||
"RequestLimitExceeded": {},
|
||||
"RequestThrottled": {},
|
||||
}
|
||||
|
||||
// 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 isCodeRetryable(code string) bool {
|
||||
if _, ok := retryableCodes[code]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
return isCodeExpiredCreds(code)
|
||||
}
|
||||
|
||||
func isCodeExpiredCreds(code string) bool {
|
||||
_, ok := credsExpiredCodes[code]
|
||||
return ok
|
||||
}
|
||||
|
||||
// shouldRetry returns if the request should be retried.
|
||||
func shouldRetry(r *Request) bool {
|
||||
if r.HTTPResponse.StatusCode >= 500 {
|
||||
return true
|
||||
}
|
||||
if r.Error != nil {
|
||||
if err, ok := r.Error.(awserr.Error); ok {
|
||||
return isCodeRetryable(err.Code())
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
51
vendor/src/github.com/aws/aws-sdk-go/aws/service/default_retryer.go
vendored
Normal file
51
vendor/src/github.com/aws/aws-sdk-go/aws/service/default_retryer.go
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// DefaultRetryer implements basic retry logic using exponential backoff for
|
||||
// most services. If you want to implement custom retry logic, implement the
|
||||
// request.Retryer interface or create a structure type that composes this
|
||||
// struct and override the specific methods. For example, to override only
|
||||
// the MaxRetries method:
|
||||
//
|
||||
// type retryer struct {
|
||||
// service.DefaultRetryer
|
||||
// }
|
||||
//
|
||||
// // This implementation always has 100 max retries
|
||||
// func (d retryer) MaxRetries() uint { return 100 }
|
||||
type DefaultRetryer struct {
|
||||
*Service
|
||||
}
|
||||
|
||||
// MaxRetries returns the number of maximum returns the service will use to make
|
||||
// an individual API request.
|
||||
func (d DefaultRetryer) MaxRetries() uint {
|
||||
if aws.IntValue(d.Service.Config.MaxRetries) < 0 {
|
||||
return d.DefaultMaxRetries
|
||||
}
|
||||
return uint(aws.IntValue(d.Service.Config.MaxRetries))
|
||||
}
|
||||
|
||||
var seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
// RetryRules returns the delay duration before retrying this request again
|
||||
func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
|
||||
delay := int(math.Pow(2, float64(r.RetryCount))) * (seededRand.Intn(30) + 30)
|
||||
return time.Duration(delay) * time.Millisecond
|
||||
}
|
||||
|
||||
// ShouldRetry returns if the request should be retried.
|
||||
func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
|
||||
if r.HTTPResponse.StatusCode >= 500 {
|
||||
return true
|
||||
}
|
||||
return r.IsErrorRetryable()
|
||||
}
|
133
vendor/src/github.com/aws/aws-sdk-go/aws/service/service.go
vendored
Normal file
133
vendor/src/github.com/aws/aws-sdk-go/aws/service/service.go
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||
"github.com/aws/aws-sdk-go/internal/endpoints"
|
||||
)
|
||||
|
||||
// A Service implements the base service request and response handling
|
||||
// used by all services.
|
||||
type Service struct {
|
||||
serviceinfo.ServiceInfo
|
||||
request.Retryer
|
||||
DefaultMaxRetries uint
|
||||
Handlers request.Handlers
|
||||
}
|
||||
|
||||
var schemeRE = regexp.MustCompile("^([^:]+)://")
|
||||
|
||||
// New will return a pointer to a new Server object initialized.
|
||||
func New(config *aws.Config) *Service {
|
||||
svc := &Service{ServiceInfo: serviceinfo.ServiceInfo{Config: config}}
|
||||
svc.Initialize()
|
||||
return svc
|
||||
}
|
||||
|
||||
// Initialize initializes the service.
|
||||
func (s *Service) Initialize() {
|
||||
if s.Config == nil {
|
||||
s.Config = &aws.Config{}
|
||||
}
|
||||
if s.Config.HTTPClient == nil {
|
||||
s.Config.HTTPClient = http.DefaultClient
|
||||
}
|
||||
if s.Config.SleepDelay == nil {
|
||||
s.Config.SleepDelay = time.Sleep
|
||||
}
|
||||
|
||||
s.Retryer = DefaultRetryer{s}
|
||||
s.DefaultMaxRetries = 3
|
||||
s.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
|
||||
s.Handlers.Build.PushBackNamed(corehandlers.UserAgentHandler)
|
||||
s.Handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
|
||||
s.Handlers.Send.PushBackNamed(corehandlers.SendHandler)
|
||||
s.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
|
||||
s.Handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
|
||||
if !aws.BoolValue(s.Config.DisableParamValidation) {
|
||||
s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
|
||||
}
|
||||
s.AddDebugHandlers()
|
||||
s.buildEndpoint()
|
||||
}
|
||||
|
||||
// NewRequest returns a new Request pointer for the service API
|
||||
// operation and parameters.
|
||||
func (s *Service) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
|
||||
return request.New(s.ServiceInfo, s.Handlers, s.Retryer, operation, params, data)
|
||||
}
|
||||
|
||||
// buildEndpoint builds the endpoint values the service will use to make requests with.
|
||||
func (s *Service) buildEndpoint() {
|
||||
if aws.StringValue(s.Config.Endpoint) != "" {
|
||||
s.Endpoint = *s.Config.Endpoint
|
||||
} else if s.Endpoint == "" {
|
||||
s.Endpoint, s.SigningRegion =
|
||||
endpoints.EndpointForRegion(s.ServiceName, aws.StringValue(s.Config.Region))
|
||||
}
|
||||
|
||||
if s.Endpoint != "" && !schemeRE.MatchString(s.Endpoint) {
|
||||
scheme := "https"
|
||||
if aws.BoolValue(s.Config.DisableSSL) {
|
||||
scheme = "http"
|
||||
}
|
||||
s.Endpoint = scheme + "://" + s.Endpoint
|
||||
}
|
||||
}
|
||||
|
||||
// AddDebugHandlers injects debug logging handlers into the service to log request
|
||||
// debug information.
|
||||
func (s *Service) AddDebugHandlers() {
|
||||
if !s.Config.LogLevel.AtLeast(aws.LogDebug) {
|
||||
return
|
||||
}
|
||||
|
||||
s.Handlers.Send.PushFront(logRequest)
|
||||
s.Handlers.Send.PushBack(logResponse)
|
||||
}
|
||||
|
||||
const logReqMsg = `DEBUG: Request %s/%s Details:
|
||||
---[ REQUEST POST-SIGN ]-----------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logRequest(r *request.Request) {
|
||||
logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
|
||||
|
||||
if logBody {
|
||||
// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
|
||||
// Body as a NoOpCloser and will not be reset after read by the HTTP
|
||||
// client reader.
|
||||
r.Body.Seek(r.BodyStart, 0)
|
||||
r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
|
||||
}
|
||||
|
||||
r.Service.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.Service.ServiceName, r.Operation.Name, string(dumpedBody)))
|
||||
}
|
||||
|
||||
const logRespMsg = `DEBUG: Response %s/%s Details:
|
||||
---[ RESPONSE ]--------------------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logResponse(r *request.Request) {
|
||||
var msg = "no reponse data"
|
||||
if r.HTTPResponse != nil {
|
||||
logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
|
||||
msg = string(dumpedBody)
|
||||
} else if r.Error != nil {
|
||||
msg = r.Error.Error()
|
||||
}
|
||||
r.Service.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.Service.ServiceName, r.Operation.Name, msg))
|
||||
}
|
15
vendor/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo/service_info.go
vendored
Normal file
15
vendor/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo/service_info.go
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
package serviceinfo
|
||||
|
||||
import "github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
// ServiceInfo wraps immutable data from the service.Service structure.
|
||||
type ServiceInfo struct {
|
||||
Config *aws.Config
|
||||
ServiceName string
|
||||
APIVersion string
|
||||
Endpoint string
|
||||
SigningName string
|
||||
SigningRegion string
|
||||
JSONVersion string
|
||||
TargetPrefix string
|
||||
}
|
|
@ -2,6 +2,7 @@ package aws
|
|||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ReadSeekCloser wraps a io.Reader returning a ReaderSeakerCloser
|
||||
|
@ -53,3 +54,35 @@ func (r ReaderSeekerCloser) Close() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A WriteAtBuffer provides a in memory buffer supporting the io.WriterAt interface
|
||||
// Can be used with the s3manager.Downloader to download content to a buffer
|
||||
// in memory. Safe to use concurrently.
|
||||
type WriteAtBuffer struct {
|
||||
buf []byte
|
||||
m sync.Mutex
|
||||
}
|
||||
|
||||
// WriteAt writes a slice of bytes to a buffer starting at the position provided
|
||||
// The number of bytes written will be returned, or error. Can overwrite previous
|
||||
// written slices if the write ats overlap.
|
||||
func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) {
|
||||
b.m.Lock()
|
||||
defer b.m.Unlock()
|
||||
|
||||
expLen := pos + int64(len(p))
|
||||
if int64(len(b.buf)) < expLen {
|
||||
newBuf := make([]byte, expLen)
|
||||
copy(newBuf, b.buf)
|
||||
b.buf = newBuf
|
||||
}
|
||||
copy(b.buf[pos:], p)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Bytes returns a slice of bytes written to the buffer.
|
||||
func (b *WriteAtBuffer) Bytes() []byte {
|
||||
b.m.Lock()
|
||||
defer b.m.Unlock()
|
||||
return b.buf[:len(b.buf):len(b.buf)]
|
||||
}
|
||||
|
|
|
@ -5,4 +5,4 @@ package aws
|
|||
const SDKName = "aws-sdk-go"
|
||||
|
||||
// SDKVersion is the version of this SDK
|
||||
const SDKVersion = "0.7.1"
|
||||
const SDKVersion = "0.9.9"
|
||||
|
|
|
@ -66,6 +66,17 @@ func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag)
|
|||
return nil
|
||||
}
|
||||
|
||||
// unwrap payloads
|
||||
if payload := tag.Get("payload"); payload != "" {
|
||||
field, _ := value.Type().FieldByName(payload)
|
||||
tag = field.Tag
|
||||
value = elemOf(value.FieldByName(payload))
|
||||
|
||||
if !value.IsValid() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString("{")
|
||||
|
||||
t, fields := value.Type(), []*reflect.StructField{}
|
||||
|
@ -197,3 +208,11 @@ func writeString(s string, buf *bytes.Buffer) {
|
|||
}
|
||||
buf.WriteByte('"')
|
||||
}
|
||||
|
||||
// Returns the reflection element of a value, if it is a pointer.
|
||||
func elemOf(value reflect.Value) reflect.Value {
|
||||
for value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -99,7 +98,7 @@ func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTa
|
|||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
if c := field.Name[0:1]; strings.ToLower(c) == c {
|
||||
if field.PkgPath != "" {
|
||||
continue // ignore unexported fields
|
||||
}
|
||||
|
||||
|
|
|
@ -10,15 +10,16 @@ import (
|
|||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/internal/protocol/json/jsonutil"
|
||||
"github.com/aws/aws-sdk-go/internal/protocol/rest"
|
||||
)
|
||||
|
||||
var emptyJSON = []byte("{}")
|
||||
|
||||
// Build builds a JSON payload for a JSON RPC request.
|
||||
func Build(req *aws.Request) {
|
||||
func Build(req *request.Request) {
|
||||
var buf []byte
|
||||
var err error
|
||||
if req.ParamsFilled() {
|
||||
|
@ -46,7 +47,7 @@ func Build(req *aws.Request) {
|
|||
}
|
||||
|
||||
// Unmarshal unmarshals a response for a JSON RPC service.
|
||||
func Unmarshal(req *aws.Request) {
|
||||
func Unmarshal(req *request.Request) {
|
||||
defer req.HTTPResponse.Body.Close()
|
||||
if req.DataFilled() {
|
||||
err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body)
|
||||
|
@ -58,12 +59,12 @@ func Unmarshal(req *aws.Request) {
|
|||
}
|
||||
|
||||
// UnmarshalMeta unmarshals headers from a response for a JSON RPC service.
|
||||
func UnmarshalMeta(req *aws.Request) {
|
||||
req.RequestID = req.HTTPResponse.Header.Get("x-amzn-requestid")
|
||||
func UnmarshalMeta(req *request.Request) {
|
||||
rest.UnmarshalMeta(req)
|
||||
}
|
||||
|
||||
// UnmarshalError unmarshals an error response for a JSON RPC service.
|
||||
func UnmarshalError(req *aws.Request) {
|
||||
func UnmarshalError(req *request.Request) {
|
||||
defer req.HTTPResponse.Body.Close()
|
||||
bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body)
|
||||
if err != nil {
|
||||
|
@ -88,7 +89,7 @@ func UnmarshalError(req *aws.Request) {
|
|||
req.Error = awserr.NewRequestFailure(
|
||||
awserr.New(codes[len(codes)-1], jsonErr.Message, nil),
|
||||
req.HTTPResponse.StatusCode,
|
||||
"",
|
||||
req.RequestID,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Package rest provides RESTful serialisation of AWS requests and responses.
|
||||
// Package rest provides RESTful serialization of AWS requests and responses.
|
||||
package rest
|
||||
|
||||
import (
|
||||
|
@ -13,8 +13,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// RFC822 returns an RFC822 formatted timestamp for AWS protocols
|
||||
|
@ -37,7 +37,7 @@ func init() {
|
|||
}
|
||||
|
||||
// Build builds the REST component of a service request.
|
||||
func Build(r *aws.Request) {
|
||||
func Build(r *request.Request) {
|
||||
if r.ParamsFilled() {
|
||||
v := reflect.ValueOf(r.Params).Elem()
|
||||
buildLocationElements(r, v)
|
||||
|
@ -45,7 +45,7 @@ func Build(r *aws.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func buildLocationElements(r *aws.Request, v reflect.Value) {
|
||||
func buildLocationElements(r *request.Request, v reflect.Value) {
|
||||
query := r.HTTPRequest.URL.Query()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
|
@ -87,7 +87,7 @@ func buildLocationElements(r *aws.Request, v reflect.Value) {
|
|||
updatePath(r.HTTPRequest.URL, r.HTTPRequest.URL.Path)
|
||||
}
|
||||
|
||||
func buildBody(r *aws.Request, v reflect.Value) {
|
||||
func buildBody(r *request.Request, v reflect.Value) {
|
||||
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
||||
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||
pfield, _ := v.Type().FieldByName(payloadName)
|
||||
|
@ -112,7 +112,7 @@ func buildBody(r *aws.Request, v reflect.Value) {
|
|||
}
|
||||
}
|
||||
|
||||
func buildHeader(r *aws.Request, v reflect.Value, name string) {
|
||||
func buildHeader(r *request.Request, v reflect.Value, name string) {
|
||||
str, err := convertType(v)
|
||||
if err != nil {
|
||||
r.Error = awserr.New("SerializationError", "failed to encode REST request", err)
|
||||
|
@ -121,7 +121,7 @@ func buildHeader(r *aws.Request, v reflect.Value, name string) {
|
|||
}
|
||||
}
|
||||
|
||||
func buildHeaderMap(r *aws.Request, v reflect.Value, prefix string) {
|
||||
func buildHeaderMap(r *request.Request, v reflect.Value, prefix string) {
|
||||
for _, key := range v.MapKeys() {
|
||||
str, err := convertType(v.MapIndex(key))
|
||||
if err != nil {
|
||||
|
@ -132,7 +132,7 @@ func buildHeaderMap(r *aws.Request, v reflect.Value, prefix string) {
|
|||
}
|
||||
}
|
||||
|
||||
func buildURI(r *aws.Request, v reflect.Value, name string) {
|
||||
func buildURI(r *request.Request, v reflect.Value, name string) {
|
||||
value, err := convertType(v)
|
||||
if err != nil {
|
||||
r.Error = awserr.New("SerializationError", "failed to encode REST request", err)
|
||||
|
@ -144,7 +144,7 @@ func buildURI(r *aws.Request, v reflect.Value, name string) {
|
|||
}
|
||||
}
|
||||
|
||||
func buildQueryString(r *aws.Request, v reflect.Value, name string, query url.Values) {
|
||||
func buildQueryString(r *request.Request, v reflect.Value, name string, query url.Values) {
|
||||
str, err := convertType(v)
|
||||
if err != nil {
|
||||
r.Error = awserr.New("SerializationError", "failed to encode REST request", err)
|
||||
|
@ -156,8 +156,13 @@ func buildQueryString(r *aws.Request, v reflect.Value, name string, query url.Va
|
|||
func updatePath(url *url.URL, urlPath string) {
|
||||
scheme, query := url.Scheme, url.RawQuery
|
||||
|
||||
hasSlash := strings.HasSuffix(urlPath, "/")
|
||||
|
||||
// clean up path
|
||||
urlPath = path.Clean(urlPath)
|
||||
if hasSlash && !strings.HasSuffix(urlPath, "/") {
|
||||
urlPath += "/"
|
||||
}
|
||||
|
||||
// get formatted URL minus scheme so we can build this into Opaque
|
||||
url.Scheme, url.Path, url.RawQuery = "", "", ""
|
||||
|
|
|
@ -12,18 +12,27 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// Unmarshal unmarshals the REST component of a response in a REST service.
|
||||
func Unmarshal(r *aws.Request) {
|
||||
func Unmarshal(r *request.Request) {
|
||||
if r.DataFilled() {
|
||||
v := reflect.Indirect(reflect.ValueOf(r.Data))
|
||||
unmarshalBody(r, v)
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalMeta unmarshals the REST metadata of a response in a REST service
|
||||
func UnmarshalMeta(r *request.Request) {
|
||||
r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid")
|
||||
if r.DataFilled() {
|
||||
v := reflect.Indirect(reflect.ValueOf(r.Data))
|
||||
unmarshalLocationElements(r, v)
|
||||
}
|
||||
}
|
||||
|
||||
func unmarshalBody(r *aws.Request, v reflect.Value) {
|
||||
func unmarshalBody(r *request.Request, v reflect.Value) {
|
||||
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
||||
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||
pfield, _ := v.Type().FieldByName(payloadName)
|
||||
|
@ -64,7 +73,7 @@ func unmarshalBody(r *aws.Request, v reflect.Value) {
|
|||
}
|
||||
}
|
||||
|
||||
func unmarshalLocationElements(r *aws.Request, v reflect.Value) {
|
||||
func unmarshalLocationElements(r *request.Request, v reflect.Value) {
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
m, field := v.Field(i), v.Type().Field(i)
|
||||
if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/internal/protocol/rest"
|
||||
)
|
||||
|
||||
|
@ -63,7 +64,7 @@ type signer struct {
|
|||
// Will sign the requests with the service config's Credentials object
|
||||
// Signing is skipped if the credentials is the credentials.AnonymousCredentials
|
||||
// object.
|
||||
func Sign(req *aws.Request) {
|
||||
func Sign(req *request.Request) {
|
||||
// If the request does not need to be signed ignore the signing of the
|
||||
// request if the AnonymousCredentials object is used.
|
||||
if req.Service.Config.Credentials == credentials.AnonymousCredentials {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,10 @@ package cloudwatchlogs
|
|||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/defaults"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/service"
|
||||
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||
"github.com/aws/aws-sdk-go/internal/protocol/jsonrpc"
|
||||
"github.com/aws/aws-sdk-go/internal/signer/v4"
|
||||
)
|
||||
|
@ -41,23 +45,25 @@ import (
|
|||
// AWS Ruby Developer Center (http://aws.amazon.com/ruby/) AWS Windows and .NET
|
||||
// Developer Center (http://aws.amazon.com/net/)
|
||||
type CloudWatchLogs struct {
|
||||
*aws.Service
|
||||
*service.Service
|
||||
}
|
||||
|
||||
// Used for custom service initialization logic
|
||||
var initService func(*aws.Service)
|
||||
var initService func(*service.Service)
|
||||
|
||||
// Used for custom request initialization logic
|
||||
var initRequest func(*aws.Request)
|
||||
var initRequest func(*request.Request)
|
||||
|
||||
// New returns a new CloudWatchLogs client.
|
||||
func New(config *aws.Config) *CloudWatchLogs {
|
||||
service := &aws.Service{
|
||||
Config: aws.DefaultConfig.Merge(config),
|
||||
ServiceName: "logs",
|
||||
APIVersion: "2014-03-28",
|
||||
JSONVersion: "1.1",
|
||||
TargetPrefix: "Logs_20140328",
|
||||
service := &service.Service{
|
||||
ServiceInfo: serviceinfo.ServiceInfo{
|
||||
Config: defaults.DefaultConfig.Merge(config),
|
||||
ServiceName: "logs",
|
||||
APIVersion: "2014-03-28",
|
||||
JSONVersion: "1.1",
|
||||
TargetPrefix: "Logs_20140328",
|
||||
},
|
||||
}
|
||||
service.Initialize()
|
||||
|
||||
|
@ -78,8 +84,8 @@ func New(config *aws.Config) *CloudWatchLogs {
|
|||
|
||||
// newRequest creates a new request for a CloudWatchLogs operation and runs any
|
||||
// custom request initialization.
|
||||
func (c *CloudWatchLogs) newRequest(op *aws.Operation, params, data interface{}) *aws.Request {
|
||||
req := aws.NewRequest(c.Service, op, params, data)
|
||||
func (c *CloudWatchLogs) newRequest(op *request.Operation, params, data interface{}) *request.Request {
|
||||
req := c.NewRequest(op, params, data)
|
||||
|
||||
// Run custom request initialization if present
|
||||
if initRequest != nil {
|
||||
|
|
Loading…
Reference in a new issue