Merge pull request #2140 from mfojtik/add-region
Add more regions to registry S3 storage drivermaster
						commit
						954b4e8154
					
				| 
						 | 
					@ -107,7 +107,9 @@ func init() {
 | 
				
			||||||
		"us-west-1",
 | 
							"us-west-1",
 | 
				
			||||||
		"us-west-2",
 | 
							"us-west-2",
 | 
				
			||||||
		"eu-west-1",
 | 
							"eu-west-1",
 | 
				
			||||||
 | 
							"eu-west-2",
 | 
				
			||||||
		"eu-central-1",
 | 
							"eu-central-1",
 | 
				
			||||||
 | 
							"ap-south-1",
 | 
				
			||||||
		"ap-southeast-1",
 | 
							"ap-southeast-1",
 | 
				
			||||||
		"ap-southeast-2",
 | 
							"ap-southeast-2",
 | 
				
			||||||
		"ap-northeast-1",
 | 
							"ap-northeast-1",
 | 
				
			||||||
| 
						 | 
					@ -115,6 +117,7 @@ func init() {
 | 
				
			||||||
		"sa-east-1",
 | 
							"sa-east-1",
 | 
				
			||||||
		"cn-north-1",
 | 
							"cn-north-1",
 | 
				
			||||||
		"us-gov-west-1",
 | 
							"us-gov-west-1",
 | 
				
			||||||
 | 
							"ca-central-1",
 | 
				
			||||||
	} {
 | 
						} {
 | 
				
			||||||
		validRegions[region] = struct{}{}
 | 
							validRegions[region] = struct{}{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
github.com/Azure/azure-sdk-for-go c6f0533defaaaa26ea4dff3c9774e36033088112
 | 
					github.com/Azure/azure-sdk-for-go c6f0533defaaaa26ea4dff3c9774e36033088112
 | 
				
			||||||
github.com/Sirupsen/logrus d26492970760ca5d33129d2d799e34be5c4782eb
 | 
					github.com/Sirupsen/logrus d26492970760ca5d33129d2d799e34be5c4782eb
 | 
				
			||||||
github.com/aws/aws-sdk-go 90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6
 | 
					github.com/aws/aws-sdk-go 36670f6ab1769ad77fa5f7e2c194398733503635
 | 
				
			||||||
github.com/bshuster-repo/logrus-logstash-hook 5f729f2fb50a301153cae84ff5c58981d51c095a
 | 
					github.com/bshuster-repo/logrus-logstash-hook 5f729f2fb50a301153cae84ff5c58981d51c095a
 | 
				
			||||||
github.com/bugsnag/bugsnag-go b1d153021fcd90ca3f080db36bec96dc690fb274
 | 
					github.com/bugsnag/bugsnag-go b1d153021fcd90ca3f080db36bec96dc690fb274
 | 
				
			||||||
github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702
 | 
					github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ type Error interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BatchError is a batch of errors which also wraps lower level errors with
 | 
					// BatchError is a batch of errors which also wraps lower level errors with
 | 
				
			||||||
// code, message, and original errors. Calling Error() will include all errors
 | 
					// code, message, and original errors. Calling Error() will include all errors
 | 
				
			||||||
// that occured in the batch.
 | 
					// that occurred in the batch.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Deprecated: Replaced with BatchedErrors. Only defined for backwards
 | 
					// Deprecated: Replaced with BatchedErrors. Only defined for backwards
 | 
				
			||||||
// compatibility.
 | 
					// compatibility.
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ type BatchError interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BatchedErrors is a batch of errors which also wraps lower level errors with
 | 
					// BatchedErrors is a batch of errors which also wraps lower level errors with
 | 
				
			||||||
// code, message, and original errors. Calling Error() will include all errors
 | 
					// code, message, and original errors. Calling Error() will include all errors
 | 
				
			||||||
// that occured in the batch.
 | 
					// that occurred in the batch.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Replaces BatchError
 | 
					// Replaces BatchError
 | 
				
			||||||
type BatchedErrors interface {
 | 
					type BatchedErrors interface {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ func (b baseError) OrigErr() error {
 | 
				
			||||||
			return NewBatchError(err.Code(), err.Message(), b.errs[1:])
 | 
								return NewBatchError(err.Code(), err.Message(), b.errs[1:])
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return NewBatchError("BatchedErrors",
 | 
							return NewBatchError("BatchedErrors",
 | 
				
			||||||
			"multiple errors occured", b.errs)
 | 
								"multiple errors occurred", b.errs)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ package awsutil
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Copy deeply copies a src structure to dst. Useful for copying request and
 | 
					// Copy deeply copies a src structure to dst. Useful for copying request and
 | 
				
			||||||
| 
						 | 
					@ -49,7 +50,14 @@ func rcopy(dst, src reflect.Value, root bool) {
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			e := src.Type().Elem()
 | 
								e := src.Type().Elem()
 | 
				
			||||||
			if dst.CanSet() && !src.IsNil() {
 | 
								if dst.CanSet() && !src.IsNil() {
 | 
				
			||||||
 | 
									if _, ok := src.Interface().(*time.Time); !ok {
 | 
				
			||||||
					dst.Set(reflect.New(e))
 | 
										dst.Set(reflect.New(e))
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										tempValue := reflect.New(e)
 | 
				
			||||||
 | 
										tempValue.Elem().Set(src.Elem())
 | 
				
			||||||
 | 
										// Sets time.Time's unexported values
 | 
				
			||||||
 | 
										dst.Set(tempValue)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if src.Elem().IsValid() {
 | 
								if src.Elem().IsValid() {
 | 
				
			||||||
				// Keep the current root state since the depth hasn't changed
 | 
									// Keep the current root state since the depth hasn't changed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,8 +106,8 @@ func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if indexStar || index != nil {
 | 
							if indexStar || index != nil {
 | 
				
			||||||
			nextvals = []reflect.Value{}
 | 
								nextvals = []reflect.Value{}
 | 
				
			||||||
			for _, value := range values {
 | 
								for _, valItem := range values {
 | 
				
			||||||
				value := reflect.Indirect(value)
 | 
									value := reflect.Indirect(valItem)
 | 
				
			||||||
				if value.Kind() != reflect.Slice {
 | 
									if value.Kind() != reflect.Slice {
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,6 +61,12 @@ func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
 | 
							buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
 | 
				
			||||||
	case reflect.Slice:
 | 
						case reflect.Slice:
 | 
				
			||||||
 | 
							strtype := v.Type().String()
 | 
				
			||||||
 | 
							if strtype == "[]uint8" {
 | 
				
			||||||
 | 
								fmt.Fprintf(buf, "<binary> len %d", v.Len())
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nl, id, id2 := "", "", ""
 | 
							nl, id, id2 := "", "", ""
 | 
				
			||||||
		if v.Len() > 3 {
 | 
							if v.Len() > 3 {
 | 
				
			||||||
			nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
 | 
								nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,6 @@ package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"net/http/httputil"
 | 
						"net/http/httputil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws"
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
| 
						 | 
					@ -14,7 +13,9 @@ import (
 | 
				
			||||||
type Config struct {
 | 
					type Config struct {
 | 
				
			||||||
	Config        *aws.Config
 | 
						Config        *aws.Config
 | 
				
			||||||
	Handlers      request.Handlers
 | 
						Handlers      request.Handlers
 | 
				
			||||||
	Endpoint, SigningRegion string
 | 
						Endpoint      string
 | 
				
			||||||
 | 
						SigningRegion string
 | 
				
			||||||
 | 
						SigningName   string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ConfigProvider provides a generic way for a service client to receive
 | 
					// ConfigProvider provides a generic way for a service client to receive
 | 
				
			||||||
| 
						 | 
					@ -87,16 +88,24 @@ const logReqMsg = `DEBUG: Request %s/%s Details:
 | 
				
			||||||
%s
 | 
					%s
 | 
				
			||||||
-----------------------------------------------------`
 | 
					-----------------------------------------------------`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
 | 
				
			||||||
 | 
					---[ REQUEST DUMP ERROR ]-----------------------------
 | 
				
			||||||
 | 
					%s
 | 
				
			||||||
 | 
					-----------------------------------------------------`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func logRequest(r *request.Request) {
 | 
					func logRequest(r *request.Request) {
 | 
				
			||||||
	logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
 | 
						logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
 | 
				
			||||||
	dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
 | 
						dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if logBody {
 | 
						if logBody {
 | 
				
			||||||
		// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
 | 
							// 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
 | 
							// Body as a NoOpCloser and will not be reset after read by the HTTP
 | 
				
			||||||
		// client reader.
 | 
							// client reader.
 | 
				
			||||||
		r.Body.Seek(r.BodyStart, 0)
 | 
							r.ResetBody()
 | 
				
			||||||
		r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
 | 
						r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
 | 
				
			||||||
| 
						 | 
					@ -107,11 +116,21 @@ const logRespMsg = `DEBUG: Response %s/%s Details:
 | 
				
			||||||
%s
 | 
					%s
 | 
				
			||||||
-----------------------------------------------------`
 | 
					-----------------------------------------------------`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
 | 
				
			||||||
 | 
					---[ RESPONSE DUMP ERROR ]-----------------------------
 | 
				
			||||||
 | 
					%s
 | 
				
			||||||
 | 
					-----------------------------------------------------`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func logResponse(r *request.Request) {
 | 
					func logResponse(r *request.Request) {
 | 
				
			||||||
	var msg = "no response data"
 | 
						var msg = "no response data"
 | 
				
			||||||
	if r.HTTPResponse != nil {
 | 
						if r.HTTPResponse != nil {
 | 
				
			||||||
		logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
 | 
							logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
 | 
				
			||||||
		dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
 | 
							dumpedBody, err := httputil.DumpResponse(r.HTTPResponse, logBody)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		msg = string(dumpedBody)
 | 
							msg = string(dumpedBody)
 | 
				
			||||||
	} else if r.Error != nil {
 | 
						} else if r.Error != nil {
 | 
				
			||||||
		msg = r.Error.Error()
 | 
							msg = r.Error.Error()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,26 +5,39 @@ import (
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/credentials"
 | 
						"github.com/aws/aws-sdk-go/aws/credentials"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/endpoints"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UseServiceDefaultRetries instructs the config to use the service's own default
 | 
					// UseServiceDefaultRetries instructs the config to use the service's own
 | 
				
			||||||
// number of retries. This will be the default action if Config.MaxRetries
 | 
					// default number of retries. This will be the default action if
 | 
				
			||||||
// is nil also.
 | 
					// Config.MaxRetries is nil also.
 | 
				
			||||||
const UseServiceDefaultRetries = -1
 | 
					const UseServiceDefaultRetries = -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RequestRetryer is an alias for a type that implements the request.Retryer interface.
 | 
					// RequestRetryer is an alias for a type that implements the request.Retryer
 | 
				
			||||||
 | 
					// interface.
 | 
				
			||||||
type RequestRetryer interface{}
 | 
					type RequestRetryer interface{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A Config provides service configuration for service clients. By default,
 | 
					// A Config provides service configuration for service clients. By default,
 | 
				
			||||||
// all clients will use the {defaults.DefaultConfig} structure.
 | 
					// all clients will use the defaults.DefaultConfig tructure.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     // Create Session with MaxRetry configuration to be shared by multiple
 | 
				
			||||||
 | 
					//     // service clients.
 | 
				
			||||||
 | 
					//     sess, err := session.NewSession(&aws.Config{
 | 
				
			||||||
 | 
					//         MaxRetries: aws.Int(3),
 | 
				
			||||||
 | 
					//     })
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     // Create S3 service client with a specific Region.
 | 
				
			||||||
 | 
					//     svc := s3.New(sess, &aws.Config{
 | 
				
			||||||
 | 
					//         Region: aws.String("us-west-2"),
 | 
				
			||||||
 | 
					//     })
 | 
				
			||||||
type Config struct {
 | 
					type Config struct {
 | 
				
			||||||
	// Enables verbose error printing of all credential chain errors.
 | 
						// Enables verbose error printing of all credential chain errors.
 | 
				
			||||||
	// Should be used when wanting to see all errors while attempting to retreive
 | 
						// Should be used when wanting to see all errors while attempting to
 | 
				
			||||||
	// credentials.
 | 
						// retrieve credentials.
 | 
				
			||||||
	CredentialsChainVerboseErrors *bool
 | 
						CredentialsChainVerboseErrors *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The credentials object to use when signing requests. Defaults to
 | 
						// The credentials object to use when signing requests. Defaults to a
 | 
				
			||||||
	// a chain of credential providers to search for credentials in environment
 | 
						// chain of credential providers to search for credentials in environment
 | 
				
			||||||
	// variables, shared credential file, and EC2 Instance Roles.
 | 
						// variables, shared credential file, and EC2 Instance Roles.
 | 
				
			||||||
	Credentials *credentials.Credentials
 | 
						Credentials *credentials.Credentials
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +49,10 @@ type Config struct {
 | 
				
			||||||
	//   endpoint for a client.
 | 
						//   endpoint for a client.
 | 
				
			||||||
	Endpoint *string
 | 
						Endpoint *string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The resolver to use for looking up endpoints for AWS service clients
 | 
				
			||||||
 | 
						// to use based on region.
 | 
				
			||||||
 | 
						EndpointResolver endpoints.Resolver
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The region to send requests to. This parameter is required and must
 | 
						// The region to send requests to. This parameter is required and must
 | 
				
			||||||
	// be configured globally or on a per-client basis unless otherwise
 | 
						// be configured globally or on a per-client basis unless otherwise
 | 
				
			||||||
	// noted. A full list of regions is found in the "Regions and Endpoints"
 | 
						// noted. A full list of regions is found in the "Regions and Endpoints"
 | 
				
			||||||
| 
						 | 
					@ -63,11 +80,12 @@ type Config struct {
 | 
				
			||||||
	Logger Logger
 | 
						Logger Logger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The maximum number of times that a request will be retried for failures.
 | 
						// The maximum number of times that a request will be retried for failures.
 | 
				
			||||||
	// Defaults to -1, which defers the max retry setting to the service specific
 | 
						// Defaults to -1, which defers the max retry setting to the service
 | 
				
			||||||
	// configuration.
 | 
						// specific configuration.
 | 
				
			||||||
	MaxRetries *int
 | 
						MaxRetries *int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Retryer guides how HTTP requests should be retried in case of recoverable failures.
 | 
						// Retryer guides how HTTP requests should be retried in case of
 | 
				
			||||||
 | 
						// recoverable failures.
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// When nil or the value does not implement the request.Retryer interface,
 | 
						// When nil or the value does not implement the request.Retryer interface,
 | 
				
			||||||
	// the request.DefaultRetryer will be used.
 | 
						// the request.DefaultRetryer will be used.
 | 
				
			||||||
| 
						 | 
					@ -82,8 +100,8 @@ type Config struct {
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	Retryer RequestRetryer
 | 
						Retryer RequestRetryer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Disables semantic parameter validation, which validates input for missing
 | 
						// Disables semantic parameter validation, which validates input for
 | 
				
			||||||
	// required fields and/or other semantic request input errors.
 | 
						// missing required fields and/or other semantic request input errors.
 | 
				
			||||||
	DisableParamValidation *bool
 | 
						DisableParamValidation *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Disables the computation of request and response checksums, e.g.,
 | 
						// Disables the computation of request and response checksums, e.g.,
 | 
				
			||||||
| 
						 | 
					@ -91,8 +109,8 @@ type Config struct {
 | 
				
			||||||
	DisableComputeChecksums *bool
 | 
						DisableComputeChecksums *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set this to `true` to force the request to use path-style addressing,
 | 
						// Set this to `true` to force the request to use path-style addressing,
 | 
				
			||||||
	// i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client will
 | 
						// i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client
 | 
				
			||||||
	// use virtual hosted bucket addressing when possible
 | 
						// will use virtual hosted bucket addressing when possible
 | 
				
			||||||
	// (`http://BUCKET.s3.amazonaws.com/KEY`).
 | 
						// (`http://BUCKET.s3.amazonaws.com/KEY`).
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// @note This configuration option is specific to the Amazon S3 service.
 | 
						// @note This configuration option is specific to the Amazon S3 service.
 | 
				
			||||||
| 
						 | 
					@ -109,49 +127,94 @@ type Config struct {
 | 
				
			||||||
	// http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
 | 
						// http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// 100-Continue is only enabled for Go 1.6 and above. See `http.Transport`'s
 | 
						// 100-Continue is only enabled for Go 1.6 and above. See `http.Transport`'s
 | 
				
			||||||
	// `ExpectContinueTimeout` for information on adjusting the continue wait timeout.
 | 
						// `ExpectContinueTimeout` for information on adjusting the continue wait
 | 
				
			||||||
	// https://golang.org/pkg/net/http/#Transport
 | 
						// timeout. https://golang.org/pkg/net/http/#Transport
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// You should use this flag to disble 100-Continue if you experiance issues
 | 
						// You should use this flag to disble 100-Continue if you experience issues
 | 
				
			||||||
	// with proxies or thrid party S3 compatible services.
 | 
						// with proxies or third party S3 compatible services.
 | 
				
			||||||
	S3Disable100Continue *bool
 | 
						S3Disable100Continue *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set this to `true` to enable S3 Accelerate feature. For all operations compatible
 | 
						// Set this to `true` to enable S3 Accelerate feature. For all operations
 | 
				
			||||||
	// with S3 Accelerate will use the accelerate endpoint for requests. Requests not compatible
 | 
						// compatible with S3 Accelerate will use the accelerate endpoint for
 | 
				
			||||||
	// will fall back to normal S3 requests.
 | 
						// requests. Requests not compatible will fall back to normal S3 requests.
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// The bucket must be enable for accelerate to be used with S3 client with accelerate
 | 
						// The bucket must be enable for accelerate to be used with S3 client with
 | 
				
			||||||
	// enabled. If the bucket is not enabled for accelerate an error will be returned.
 | 
						// accelerate enabled. If the bucket is not enabled for accelerate an error
 | 
				
			||||||
	// The bucket name must be DNS compatible to also work with accelerate.
 | 
						// will be returned. The bucket name must be DNS compatible to also work
 | 
				
			||||||
 | 
						// with accelerate.
 | 
				
			||||||
	S3UseAccelerate *bool
 | 
						S3UseAccelerate *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set this to `true` to disable the EC2Metadata client from overriding the
 | 
						// Set this to `true` to disable the EC2Metadata client from overriding the
 | 
				
			||||||
	// default http.Client's Timeout. This is helpful if you do not want the EC2Metadata
 | 
						// default http.Client's Timeout. This is helpful if you do not want the
 | 
				
			||||||
	// client to create a new http.Client. This options is only meaningful if you're not
 | 
						// EC2Metadata client to create a new http.Client. This options is only
 | 
				
			||||||
	// already using a custom HTTP client with the SDK. Enabled by default.
 | 
						// meaningful if you're not already using a custom HTTP client with the
 | 
				
			||||||
 | 
						// SDK. Enabled by default.
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// Must be set and provided to the session.New() in order to disable the EC2Metadata
 | 
						// Must be set and provided to the session.NewSession() in order to disable
 | 
				
			||||||
	// overriding the timeout for default credentials chain.
 | 
						// the EC2Metadata overriding the timeout for default credentials chain.
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// Example:
 | 
						// Example:
 | 
				
			||||||
	//    sess := session.New(aws.NewConfig().WithEC2MetadataDiableTimeoutOverride(true))
 | 
						//    sess, err := session.NewSession(aws.NewConfig().WithEC2MetadataDiableTimeoutOverride(true))
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
	//    svc := s3.New(sess)
 | 
						//    svc := s3.New(sess)
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	EC2MetadataDisableTimeoutOverride *bool
 | 
						EC2MetadataDisableTimeoutOverride *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Instructs the endpiont to be generated for a service client to
 | 
				
			||||||
 | 
						// be the dual stack endpoint. The dual stack endpoint will support
 | 
				
			||||||
 | 
						// both IPv4 and IPv6 addressing.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Setting this for a service which does not support dual stack will fail
 | 
				
			||||||
 | 
						// to make requets. It is not recommended to set this value on the session
 | 
				
			||||||
 | 
						// as it will apply to all service clients created with the session. Even
 | 
				
			||||||
 | 
						// services which don't support dual stack endpoints.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If the Endpoint config value is also provided the UseDualStack flag
 | 
				
			||||||
 | 
						// will be ignored.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Only supported with.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//     sess, err := session.NewSession()
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//     svc := s3.New(sess, &aws.Config{
 | 
				
			||||||
 | 
						//         UseDualStack: aws.Bool(true),
 | 
				
			||||||
 | 
						//     })
 | 
				
			||||||
 | 
						UseDualStack *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// SleepDelay is an override for the func the SDK will call when sleeping
 | 
						// SleepDelay is an override for the func the SDK will call when sleeping
 | 
				
			||||||
	// during the lifecycle of a request. Specifically this will be used for
 | 
						// during the lifecycle of a request. Specifically this will be used for
 | 
				
			||||||
	// request delays. This value should only be used for testing. To adjust
 | 
						// request delays. This value should only be used for testing. To adjust
 | 
				
			||||||
	// the delay of a request see the aws/client.DefaultRetryer and
 | 
						// the delay of a request see the aws/client.DefaultRetryer and
 | 
				
			||||||
	// aws/request.Retryer.
 | 
						// aws/request.Retryer.
 | 
				
			||||||
	SleepDelay func(time.Duration)
 | 
						SleepDelay func(time.Duration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DisableRestProtocolURICleaning will not clean the URL path when making rest protocol requests.
 | 
				
			||||||
 | 
						// Will default to false. This would only be used for empty directory names in s3 requests.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Example:
 | 
				
			||||||
 | 
						//    sess, err := session.NewSession(&aws.Config{DisableRestProtocolURICleaning: aws.Bool(true))
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//    svc := s3.New(sess)
 | 
				
			||||||
 | 
						//    out, err := svc.GetObject(&s3.GetObjectInput {
 | 
				
			||||||
 | 
						//    	Bucket: aws.String("bucketname"),
 | 
				
			||||||
 | 
						//    	Key: aws.String("//foo//bar//moo"),
 | 
				
			||||||
 | 
						//    })
 | 
				
			||||||
 | 
						DisableRestProtocolURICleaning *bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewConfig returns a new Config pointer that can be chained with builder methods to
 | 
					// NewConfig returns a new Config pointer that can be chained with builder
 | 
				
			||||||
// set multiple configuration values inline without using pointers.
 | 
					// methods to set multiple configuration values inline without using pointers.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//     sess := session.New(aws.NewConfig().WithRegion("us-west-2").WithMaxRetries(10))
 | 
					//     // Create Session with MaxRetry configuration to be shared by multiple
 | 
				
			||||||
 | 
					//     // service clients.
 | 
				
			||||||
 | 
					//     sess, err := session.NewSession(aws.NewConfig().
 | 
				
			||||||
 | 
					//         WithMaxRetries(3),
 | 
				
			||||||
 | 
					//     )
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					//     // Create S3 service client with a specific Region.
 | 
				
			||||||
 | 
					//     svc := s3.New(sess, aws.NewConfig().
 | 
				
			||||||
 | 
					//         WithRegion("us-west-2"),
 | 
				
			||||||
 | 
					//     )
 | 
				
			||||||
func NewConfig() *Config {
 | 
					func NewConfig() *Config {
 | 
				
			||||||
	return &Config{}
 | 
						return &Config{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -177,6 +240,13 @@ func (c *Config) WithEndpoint(endpoint string) *Config {
 | 
				
			||||||
	return c
 | 
						return c
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WithEndpointResolver sets a config EndpointResolver value returning a
 | 
				
			||||||
 | 
					// Config pointer for chaining.
 | 
				
			||||||
 | 
					func (c *Config) WithEndpointResolver(resolver endpoints.Resolver) *Config {
 | 
				
			||||||
 | 
						c.EndpointResolver = resolver
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithRegion sets a config Region value returning a Config pointer for
 | 
					// WithRegion sets a config Region value returning a Config pointer for
 | 
				
			||||||
// chaining.
 | 
					// chaining.
 | 
				
			||||||
func (c *Config) WithRegion(region string) *Config {
 | 
					func (c *Config) WithRegion(region string) *Config {
 | 
				
			||||||
| 
						 | 
					@ -254,6 +324,13 @@ func (c *Config) WithS3UseAccelerate(enable bool) *Config {
 | 
				
			||||||
	return c
 | 
						return c
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WithUseDualStack sets a config UseDualStack value returning a Config
 | 
				
			||||||
 | 
					// pointer for chaining.
 | 
				
			||||||
 | 
					func (c *Config) WithUseDualStack(enable bool) *Config {
 | 
				
			||||||
 | 
						c.UseDualStack = &enable
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// WithEC2MetadataDisableTimeoutOverride sets a config EC2MetadataDisableTimeoutOverride value
 | 
					// WithEC2MetadataDisableTimeoutOverride sets a config EC2MetadataDisableTimeoutOverride value
 | 
				
			||||||
// returning a Config pointer for chaining.
 | 
					// returning a Config pointer for chaining.
 | 
				
			||||||
func (c *Config) WithEC2MetadataDisableTimeoutOverride(enable bool) *Config {
 | 
					func (c *Config) WithEC2MetadataDisableTimeoutOverride(enable bool) *Config {
 | 
				
			||||||
| 
						 | 
					@ -292,6 +369,10 @@ func mergeInConfig(dst *Config, other *Config) {
 | 
				
			||||||
		dst.Endpoint = other.Endpoint
 | 
							dst.Endpoint = other.Endpoint
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if other.EndpointResolver != nil {
 | 
				
			||||||
 | 
							dst.EndpointResolver = other.EndpointResolver
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if other.Region != nil {
 | 
						if other.Region != nil {
 | 
				
			||||||
		dst.Region = other.Region
 | 
							dst.Region = other.Region
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -340,6 +421,10 @@ func mergeInConfig(dst *Config, other *Config) {
 | 
				
			||||||
		dst.S3UseAccelerate = other.S3UseAccelerate
 | 
							dst.S3UseAccelerate = other.S3UseAccelerate
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if other.UseDualStack != nil {
 | 
				
			||||||
 | 
							dst.UseDualStack = other.UseDualStack
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if other.EC2MetadataDisableTimeoutOverride != nil {
 | 
						if other.EC2MetadataDisableTimeoutOverride != nil {
 | 
				
			||||||
		dst.EC2MetadataDisableTimeoutOverride = other.EC2MetadataDisableTimeoutOverride
 | 
							dst.EC2MetadataDisableTimeoutOverride = other.EC2MetadataDisableTimeoutOverride
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -347,6 +432,10 @@ func mergeInConfig(dst *Config, other *Config) {
 | 
				
			||||||
	if other.SleepDelay != nil {
 | 
						if other.SleepDelay != nil {
 | 
				
			||||||
		dst.SleepDelay = other.SleepDelay
 | 
							dst.SleepDelay = other.SleepDelay
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if other.DisableRestProtocolURICleaning != nil {
 | 
				
			||||||
 | 
							dst.DisableRestProtocolURICleaning = other.DisableRestProtocolURICleaning
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Copy will return a shallow copy of the Config object. If any additional
 | 
					// Copy will return a shallow copy of the Config object. If any additional
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,9 +10,11 @@ import (
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws"
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/awserr"
 | 
						"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/request"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,6 +69,34 @@ var SDKVersionUserAgentHandler = request.NamedHandler{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var reStatusCode = regexp.MustCompile(`^(\d{3})`)
 | 
					var reStatusCode = regexp.MustCompile(`^(\d{3})`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateReqSigHandler is a request handler to ensure that the request's
 | 
				
			||||||
 | 
					// signature doesn't expire before it is sent. This can happen when a request
 | 
				
			||||||
 | 
					// is built and signed signficantly before it is sent. Or significant delays
 | 
				
			||||||
 | 
					// occur whne retrying requests that would cause the signature to expire.
 | 
				
			||||||
 | 
					var ValidateReqSigHandler = request.NamedHandler{
 | 
				
			||||||
 | 
						Name: "core.ValidateReqSigHandler",
 | 
				
			||||||
 | 
						Fn: func(r *request.Request) {
 | 
				
			||||||
 | 
							// Unsigned requests are not signed
 | 
				
			||||||
 | 
							if r.Config.Credentials == credentials.AnonymousCredentials {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							signedTime := r.Time
 | 
				
			||||||
 | 
							if !r.LastSignedAt.IsZero() {
 | 
				
			||||||
 | 
								signedTime = r.LastSignedAt
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 10 minutes to allow for some clock skew/delays in transmission.
 | 
				
			||||||
 | 
							// Would be improved with aws/aws-sdk-go#423
 | 
				
			||||||
 | 
							if signedTime.Add(10 * time.Minute).After(time.Now()) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fmt.Println("request expired, resigning")
 | 
				
			||||||
 | 
							r.Sign()
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SendHandler is a request handler to send service request using HTTP client.
 | 
					// SendHandler is a request handler to send service request using HTTP client.
 | 
				
			||||||
var SendHandler = request.NamedHandler{Name: "core.SendHandler", Fn: func(r *request.Request) {
 | 
					var SendHandler = request.NamedHandler{Name: "core.SendHandler", Fn: func(r *request.Request) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ var (
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
 | 
					// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
 | 
				
			||||||
// In this example EnvProvider will first check if any credentials are available
 | 
					// In this example EnvProvider will first check if any credentials are available
 | 
				
			||||||
// vai the environment variables. If there are none ChainProvider will check
 | 
					// via the environment variables. If there are none ChainProvider will check
 | 
				
			||||||
// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
 | 
					// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
 | 
				
			||||||
// does not return any credentials ChainProvider will return the error
 | 
					// does not return any credentials ChainProvider will return the error
 | 
				
			||||||
// ErrNoValidProvidersFoundInChain
 | 
					// ErrNoValidProvidersFoundInChain
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
								
								
									generated
								
								
									vendored
								
								
							
							
						
						
									
										2
									
								
								vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
								
								
									generated
								
								
									vendored
								
								
							| 
						 | 
					@ -111,7 +111,7 @@ func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A ec2RoleCredRespBody provides the shape for unmarshalling credential
 | 
					// A ec2RoleCredRespBody provides the shape for unmarshaling credential
 | 
				
			||||||
// request responses.
 | 
					// request responses.
 | 
				
			||||||
type ec2RoleCredRespBody struct {
 | 
					type ec2RoleCredRespBody struct {
 | 
				
			||||||
	// Success State
 | 
						// Success State
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										191
									
								
								vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										191
									
								
								vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							| 
						 | 
					@ -0,0 +1,191 @@
 | 
				
			||||||
 | 
					// Package endpointcreds provides support for retrieving credentials from an
 | 
				
			||||||
 | 
					// arbitrary HTTP endpoint.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The credentials endpoint Provider can receive both static and refreshable
 | 
				
			||||||
 | 
					// credentials that will expire. Credentials are static when an "Expiration"
 | 
				
			||||||
 | 
					// value is not provided in the endpoint's response.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Static credentials will never expire once they have been retrieved. The format
 | 
				
			||||||
 | 
					// of the static credentials response:
 | 
				
			||||||
 | 
					//    {
 | 
				
			||||||
 | 
					//        "AccessKeyId" : "MUA...",
 | 
				
			||||||
 | 
					//        "SecretAccessKey" : "/7PC5om....",
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Refreshable credentials will expire within the "ExpiryWindow" of the Expiration
 | 
				
			||||||
 | 
					// value in the response. The format of the refreshable credentials response:
 | 
				
			||||||
 | 
					//    {
 | 
				
			||||||
 | 
					//        "AccessKeyId" : "MUA...",
 | 
				
			||||||
 | 
					//        "SecretAccessKey" : "/7PC5om....",
 | 
				
			||||||
 | 
					//        "Token" : "AQoDY....=",
 | 
				
			||||||
 | 
					//        "Expiration" : "2016-02-25T06:03:31Z"
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Errors should be returned in the following format and only returned with 400
 | 
				
			||||||
 | 
					// or 500 HTTP status codes.
 | 
				
			||||||
 | 
					//    {
 | 
				
			||||||
 | 
					//        "code": "ErrorCode",
 | 
				
			||||||
 | 
					//        "message": "Helpful error message."
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					package endpointcreds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/client"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/client/metadata"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/credentials"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ProviderName is the name of the credentials provider.
 | 
				
			||||||
 | 
					const ProviderName = `CredentialsEndpointProvider`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Provider satisfies the credentials.Provider interface, and is a client to
 | 
				
			||||||
 | 
					// retrieve credentials from an arbitrary endpoint.
 | 
				
			||||||
 | 
					type Provider struct {
 | 
				
			||||||
 | 
						staticCreds bool
 | 
				
			||||||
 | 
						credentials.Expiry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Requires a AWS Client to make HTTP requests to the endpoint with.
 | 
				
			||||||
 | 
						// the Endpoint the request will be made to is provided by the aws.Config's
 | 
				
			||||||
 | 
						// Endpoint value.
 | 
				
			||||||
 | 
						Client *client.Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ExpiryWindow will allow the credentials to trigger refreshing prior to
 | 
				
			||||||
 | 
						// the credentials actually expiring. This is beneficial so race conditions
 | 
				
			||||||
 | 
						// with expiring credentials do not cause request to fail unexpectedly
 | 
				
			||||||
 | 
						// due to ExpiredTokenException exceptions.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
 | 
				
			||||||
 | 
						// 10 seconds before the credentials are actually expired.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If ExpiryWindow is 0 or less it will be ignored.
 | 
				
			||||||
 | 
						ExpiryWindow time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewProviderClient returns a credentials Provider for retrieving AWS credentials
 | 
				
			||||||
 | 
					// from arbitrary endpoint.
 | 
				
			||||||
 | 
					func NewProviderClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) credentials.Provider {
 | 
				
			||||||
 | 
						p := &Provider{
 | 
				
			||||||
 | 
							Client: client.New(
 | 
				
			||||||
 | 
								cfg,
 | 
				
			||||||
 | 
								metadata.ClientInfo{
 | 
				
			||||||
 | 
									ServiceName: "CredentialsEndpoint",
 | 
				
			||||||
 | 
									Endpoint:    endpoint,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								handlers,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Client.Handlers.Unmarshal.PushBack(unmarshalHandler)
 | 
				
			||||||
 | 
						p.Client.Handlers.UnmarshalError.PushBack(unmarshalError)
 | 
				
			||||||
 | 
						p.Client.Handlers.Validate.Clear()
 | 
				
			||||||
 | 
						p.Client.Handlers.Validate.PushBack(validateEndpointHandler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, option := range options {
 | 
				
			||||||
 | 
							option(p)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewCredentialsClient returns a Credentials wrapper for retrieving credentials
 | 
				
			||||||
 | 
					// from an arbitrary endpoint concurrently. The client will request the
 | 
				
			||||||
 | 
					func NewCredentialsClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) *credentials.Credentials {
 | 
				
			||||||
 | 
						return credentials.NewCredentials(NewProviderClient(cfg, handlers, endpoint, options...))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsExpired returns true if the credentials retrieved are expired, or not yet
 | 
				
			||||||
 | 
					// retrieved.
 | 
				
			||||||
 | 
					func (p *Provider) IsExpired() bool {
 | 
				
			||||||
 | 
						if p.staticCreds {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return p.Expiry.IsExpired()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Retrieve will attempt to request the credentials from the endpoint the Provider
 | 
				
			||||||
 | 
					// was configured for. And error will be returned if the retrieval fails.
 | 
				
			||||||
 | 
					func (p *Provider) Retrieve() (credentials.Value, error) {
 | 
				
			||||||
 | 
						resp, err := p.getCredentials()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return credentials.Value{ProviderName: ProviderName},
 | 
				
			||||||
 | 
								awserr.New("CredentialsEndpointError", "failed to load credentials", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if resp.Expiration != nil {
 | 
				
			||||||
 | 
							p.SetExpiration(*resp.Expiration, p.ExpiryWindow)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.staticCreds = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return credentials.Value{
 | 
				
			||||||
 | 
							AccessKeyID:     resp.AccessKeyID,
 | 
				
			||||||
 | 
							SecretAccessKey: resp.SecretAccessKey,
 | 
				
			||||||
 | 
							SessionToken:    resp.Token,
 | 
				
			||||||
 | 
							ProviderName:    ProviderName,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type getCredentialsOutput struct {
 | 
				
			||||||
 | 
						Expiration      *time.Time
 | 
				
			||||||
 | 
						AccessKeyID     string
 | 
				
			||||||
 | 
						SecretAccessKey string
 | 
				
			||||||
 | 
						Token           string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type errorOutput struct {
 | 
				
			||||||
 | 
						Code    string `json:"code"`
 | 
				
			||||||
 | 
						Message string `json:"message"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Provider) getCredentials() (*getCredentialsOutput, error) {
 | 
				
			||||||
 | 
						op := &request.Operation{
 | 
				
			||||||
 | 
							Name:       "GetCredentials",
 | 
				
			||||||
 | 
							HTTPMethod: "GET",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out := &getCredentialsOutput{}
 | 
				
			||||||
 | 
						req := p.Client.NewRequest(op, nil, out)
 | 
				
			||||||
 | 
						req.HTTPRequest.Header.Set("Accept", "application/json")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return out, req.Send()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func validateEndpointHandler(r *request.Request) {
 | 
				
			||||||
 | 
						if len(r.ClientInfo.Endpoint) == 0 {
 | 
				
			||||||
 | 
							r.Error = aws.ErrMissingEndpoint
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unmarshalHandler(r *request.Request) {
 | 
				
			||||||
 | 
						defer r.HTTPResponse.Body.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out := r.Data.(*getCredentialsOutput)
 | 
				
			||||||
 | 
						if err := json.NewDecoder(r.HTTPResponse.Body).Decode(&out); err != nil {
 | 
				
			||||||
 | 
							r.Error = awserr.New("SerializationError",
 | 
				
			||||||
 | 
								"failed to decode endpoint credentials",
 | 
				
			||||||
 | 
								err,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func unmarshalError(r *request.Request) {
 | 
				
			||||||
 | 
						defer r.HTTPResponse.Body.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var errOut errorOutput
 | 
				
			||||||
 | 
						if err := json.NewDecoder(r.HTTPResponse.Body).Decode(&errOut); err != nil {
 | 
				
			||||||
 | 
							r.Error = awserr.New("SerializationError",
 | 
				
			||||||
 | 
								"failed to decode endpoint credentials",
 | 
				
			||||||
 | 
								err,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Response body format is not consistent between metadata endpoints.
 | 
				
			||||||
 | 
						// Grab the error message as a string and include that as the source error
 | 
				
			||||||
 | 
						r.Error = awserr.New(errOut.Code, errOut.Message, nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -30,13 +30,22 @@ func NewStaticCredentials(id, secret, token string) *Credentials {
 | 
				
			||||||
	}})
 | 
						}})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewStaticCredentialsFromCreds returns a pointer to a new Credentials object
 | 
				
			||||||
 | 
					// wrapping the static credentials value provide. Same as NewStaticCredentials
 | 
				
			||||||
 | 
					// but takes the creds Value instead of individual fields
 | 
				
			||||||
 | 
					func NewStaticCredentialsFromCreds(creds Value) *Credentials {
 | 
				
			||||||
 | 
						return NewCredentials(&StaticProvider{Value: creds})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Retrieve returns the credentials or error if the credentials are invalid.
 | 
					// Retrieve returns the credentials or error if the credentials are invalid.
 | 
				
			||||||
func (s *StaticProvider) Retrieve() (Value, error) {
 | 
					func (s *StaticProvider) Retrieve() (Value, error) {
 | 
				
			||||||
	if s.AccessKeyID == "" || s.SecretAccessKey == "" {
 | 
						if s.AccessKeyID == "" || s.SecretAccessKey == "" {
 | 
				
			||||||
		return Value{ProviderName: StaticProviderName}, ErrStaticCredentialsEmpty
 | 
							return Value{ProviderName: StaticProviderName}, ErrStaticCredentialsEmpty
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(s.Value.ProviderName) == 0 {
 | 
				
			||||||
		s.Value.ProviderName = StaticProviderName
 | 
							s.Value.ProviderName = StaticProviderName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return s.Value, nil
 | 
						return s.Value, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										161
									
								
								vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										161
									
								
								vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							| 
						 | 
					@ -0,0 +1,161 @@
 | 
				
			||||||
 | 
					// Package stscreds are credential Providers to retrieve STS AWS credentials.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// STS provides multiple ways to retrieve credentials which can be used when making
 | 
				
			||||||
 | 
					// future AWS service API operation calls.
 | 
				
			||||||
 | 
					package stscreds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/client"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/credentials"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/service/sts"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ProviderName provides a name of AssumeRole provider
 | 
				
			||||||
 | 
					const ProviderName = "AssumeRoleProvider"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AssumeRoler represents the minimal subset of the STS client API used by this provider.
 | 
				
			||||||
 | 
					type AssumeRoler interface {
 | 
				
			||||||
 | 
						AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DefaultDuration is the default amount of time in minutes that the credentials
 | 
				
			||||||
 | 
					// will be valid for.
 | 
				
			||||||
 | 
					var DefaultDuration = time.Duration(15) * time.Minute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AssumeRoleProvider retrieves temporary credentials from the STS service, and
 | 
				
			||||||
 | 
					// keeps track of their expiration time. This provider must be used explicitly,
 | 
				
			||||||
 | 
					// as it is not included in the credentials chain.
 | 
				
			||||||
 | 
					type AssumeRoleProvider struct {
 | 
				
			||||||
 | 
						credentials.Expiry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// STS client to make assume role request with.
 | 
				
			||||||
 | 
						Client AssumeRoler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Role to be assumed.
 | 
				
			||||||
 | 
						RoleARN string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Session name, if you wish to reuse the credentials elsewhere.
 | 
				
			||||||
 | 
						RoleSessionName string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Expiry duration of the STS credentials. Defaults to 15 minutes if not set.
 | 
				
			||||||
 | 
						Duration time.Duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Optional ExternalID to pass along, defaults to nil if not set.
 | 
				
			||||||
 | 
						ExternalID *string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The policy plain text must be 2048 bytes or shorter. However, an internal
 | 
				
			||||||
 | 
						// conversion compresses it into a packed binary format with a separate limit.
 | 
				
			||||||
 | 
						// The PackedPolicySize response element indicates by percentage how close to
 | 
				
			||||||
 | 
						// the upper size limit the policy is, with 100% equaling the maximum allowed
 | 
				
			||||||
 | 
						// size.
 | 
				
			||||||
 | 
						Policy *string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The identification number of the MFA device that is associated with the user
 | 
				
			||||||
 | 
						// who is making the AssumeRole call. Specify this value if the trust policy
 | 
				
			||||||
 | 
						// of the role being assumed includes a condition that requires MFA authentication.
 | 
				
			||||||
 | 
						// The value is either the serial number for a hardware device (such as GAHT12345678)
 | 
				
			||||||
 | 
						// or an Amazon Resource Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user).
 | 
				
			||||||
 | 
						SerialNumber *string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The value provided by the MFA device, if the trust policy of the role being
 | 
				
			||||||
 | 
						// assumed requires MFA (that is, if the policy includes a condition that tests
 | 
				
			||||||
 | 
						// for MFA). If the role being assumed requires MFA and if the TokenCode value
 | 
				
			||||||
 | 
						// is missing or expired, the AssumeRole call returns an "access denied" error.
 | 
				
			||||||
 | 
						TokenCode *string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ExpiryWindow will allow the credentials to trigger refreshing prior to
 | 
				
			||||||
 | 
						// the credentials actually expiring. This is beneficial so race conditions
 | 
				
			||||||
 | 
						// with expiring credentials do not cause request to fail unexpectedly
 | 
				
			||||||
 | 
						// due to ExpiredTokenException exceptions.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
 | 
				
			||||||
 | 
						// 10 seconds before the credentials are actually expired.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If ExpiryWindow is 0 or less it will be ignored.
 | 
				
			||||||
 | 
						ExpiryWindow time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewCredentials returns a pointer to a new Credentials object wrapping the
 | 
				
			||||||
 | 
					// AssumeRoleProvider. The credentials will expire every 15 minutes and the
 | 
				
			||||||
 | 
					// role will be named after a nanosecond timestamp of this operation.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Takes a Config provider to create the STS client. The ConfigProvider is
 | 
				
			||||||
 | 
					// satisfied by the session.Session type.
 | 
				
			||||||
 | 
					func NewCredentials(c client.ConfigProvider, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
 | 
				
			||||||
 | 
						p := &AssumeRoleProvider{
 | 
				
			||||||
 | 
							Client:   sts.New(c),
 | 
				
			||||||
 | 
							RoleARN:  roleARN,
 | 
				
			||||||
 | 
							Duration: DefaultDuration,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, option := range options {
 | 
				
			||||||
 | 
							option(p)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return credentials.NewCredentials(p)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping the
 | 
				
			||||||
 | 
					// AssumeRoleProvider. The credentials will expire every 15 minutes and the
 | 
				
			||||||
 | 
					// role will be named after a nanosecond timestamp of this operation.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Takes an AssumeRoler which can be satisfiede by the STS client.
 | 
				
			||||||
 | 
					func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
 | 
				
			||||||
 | 
						p := &AssumeRoleProvider{
 | 
				
			||||||
 | 
							Client:   svc,
 | 
				
			||||||
 | 
							RoleARN:  roleARN,
 | 
				
			||||||
 | 
							Duration: DefaultDuration,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, option := range options {
 | 
				
			||||||
 | 
							option(p)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return credentials.NewCredentials(p)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Retrieve generates a new set of temporary credentials using STS.
 | 
				
			||||||
 | 
					func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Apply defaults where parameters are not set.
 | 
				
			||||||
 | 
						if p.RoleSessionName == "" {
 | 
				
			||||||
 | 
							// Try to work out a role name that will hopefully end up unique.
 | 
				
			||||||
 | 
							p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if p.Duration == 0 {
 | 
				
			||||||
 | 
							// Expire as often as AWS permits.
 | 
				
			||||||
 | 
							p.Duration = DefaultDuration
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						input := &sts.AssumeRoleInput{
 | 
				
			||||||
 | 
							DurationSeconds: aws.Int64(int64(p.Duration / time.Second)),
 | 
				
			||||||
 | 
							RoleArn:         aws.String(p.RoleARN),
 | 
				
			||||||
 | 
							RoleSessionName: aws.String(p.RoleSessionName),
 | 
				
			||||||
 | 
							ExternalId:      p.ExternalID,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if p.Policy != nil {
 | 
				
			||||||
 | 
							input.Policy = p.Policy
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if p.SerialNumber != nil && p.TokenCode != nil {
 | 
				
			||||||
 | 
							input.SerialNumber = p.SerialNumber
 | 
				
			||||||
 | 
							input.TokenCode = p.TokenCode
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						roleOutput, err := p.Client.AssumeRole(input)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return credentials.Value{ProviderName: ProviderName}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We will proactively generate new credentials before they expire.
 | 
				
			||||||
 | 
						p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return credentials.Value{
 | 
				
			||||||
 | 
							AccessKeyID:     *roleOutput.Credentials.AccessKeyId,
 | 
				
			||||||
 | 
							SecretAccessKey: *roleOutput.Credentials.SecretAccessKey,
 | 
				
			||||||
 | 
							SessionToken:    *roleOutput.Credentials.SessionToken,
 | 
				
			||||||
 | 
							ProviderName:    ProviderName,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
package defaults
 | 
					package defaults
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -16,9 +17,10 @@ import (
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/corehandlers"
 | 
						"github.com/aws/aws-sdk-go/aws/corehandlers"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/credentials"
 | 
						"github.com/aws/aws-sdk-go/aws/credentials"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
 | 
						"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
 | 
						"github.com/aws/aws-sdk-go/aws/ec2metadata"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/endpoints"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/request"
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/private/endpoints"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A Defaults provides a collection of default values for SDK clients.
 | 
					// A Defaults provides a collection of default values for SDK clients.
 | 
				
			||||||
| 
						 | 
					@ -54,7 +56,8 @@ func Config() *aws.Config {
 | 
				
			||||||
		WithMaxRetries(aws.UseServiceDefaultRetries).
 | 
							WithMaxRetries(aws.UseServiceDefaultRetries).
 | 
				
			||||||
		WithLogger(aws.NewDefaultLogger()).
 | 
							WithLogger(aws.NewDefaultLogger()).
 | 
				
			||||||
		WithLogLevel(aws.LogOff).
 | 
							WithLogLevel(aws.LogOff).
 | 
				
			||||||
		WithSleepDelay(time.Sleep)
 | 
							WithSleepDelay(time.Sleep).
 | 
				
			||||||
 | 
							WithEndpointResolver(endpoints.DefaultResolver())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Handlers returns the default request handlers.
 | 
					// Handlers returns the default request handlers.
 | 
				
			||||||
| 
						 | 
					@ -70,6 +73,7 @@ func Handlers() request.Handlers {
 | 
				
			||||||
	handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
 | 
						handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
 | 
				
			||||||
	handlers.Build.AfterEachFn = request.HandlerListStopOnError
 | 
						handlers.Build.AfterEachFn = request.HandlerListStopOnError
 | 
				
			||||||
	handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
 | 
						handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
 | 
				
			||||||
 | 
						handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
 | 
				
			||||||
	handlers.Send.PushBackNamed(corehandlers.SendHandler)
 | 
						handlers.Send.PushBackNamed(corehandlers.SendHandler)
 | 
				
			||||||
	handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
 | 
						handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
 | 
				
			||||||
	handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
 | 
						handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
 | 
				
			||||||
| 
						 | 
					@ -83,16 +87,48 @@ func Handlers() request.Handlers {
 | 
				
			||||||
// is available if you need to reset the credentials of an
 | 
					// is available if you need to reset the credentials of an
 | 
				
			||||||
// existing service client or session's Config.
 | 
					// existing service client or session's Config.
 | 
				
			||||||
func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
 | 
					func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
 | 
				
			||||||
	endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return credentials.NewCredentials(&credentials.ChainProvider{
 | 
						return credentials.NewCredentials(&credentials.ChainProvider{
 | 
				
			||||||
		VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
 | 
							VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
 | 
				
			||||||
		Providers: []credentials.Provider{
 | 
							Providers: []credentials.Provider{
 | 
				
			||||||
			&credentials.EnvProvider{},
 | 
								&credentials.EnvProvider{},
 | 
				
			||||||
			&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
 | 
								&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
 | 
				
			||||||
			&ec2rolecreds.EC2RoleProvider{
 | 
								RemoteCredProvider(*cfg, handlers),
 | 
				
			||||||
				Client:       ec2metadata.NewClient(*cfg, handlers, endpoint, signingRegion),
 | 
					 | 
				
			||||||
				ExpiryWindow: 5 * time.Minute,
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		}})
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RemoteCredProvider returns a credenitials provider for the default remote
 | 
				
			||||||
 | 
					// endpoints such as EC2 or ECS Roles.
 | 
				
			||||||
 | 
					func RemoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
 | 
				
			||||||
 | 
						ecsCredURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(ecsCredURI) > 0 {
 | 
				
			||||||
 | 
							return ecsCredProvider(cfg, handlers, ecsCredURI)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ec2RoleProvider(cfg, handlers)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ecsCredProvider(cfg aws.Config, handlers request.Handlers, uri string) credentials.Provider {
 | 
				
			||||||
 | 
						const host = `169.254.170.2`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return endpointcreds.NewProviderClient(cfg, handlers,
 | 
				
			||||||
 | 
							fmt.Sprintf("http://%s%s", host, uri),
 | 
				
			||||||
 | 
							func(p *endpointcreds.Provider) {
 | 
				
			||||||
 | 
								p.ExpiryWindow = 5 * time.Minute
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ec2RoleProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
 | 
				
			||||||
 | 
						resolver := cfg.EndpointResolver
 | 
				
			||||||
 | 
						if resolver == nil {
 | 
				
			||||||
 | 
							resolver = endpoints.DefaultResolver()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e, _ := resolver.EndpointFor(endpoints.Ec2metadataServiceID, "")
 | 
				
			||||||
 | 
						return &ec2rolecreds.EC2RoleProvider{
 | 
				
			||||||
 | 
							Client:       ec2metadata.NewClient(cfg, handlers, e.URL, e.SigningRegion),
 | 
				
			||||||
 | 
							ExpiryWindow: 5 * time.Minute,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ package ec2metadata
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -27,6 +28,27 @@ func (c *EC2Metadata) GetMetadata(p string) (string, error) {
 | 
				
			||||||
	return output.Content, req.Send()
 | 
						return output.Content, req.Send()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetUserData returns the userdata that was configured for the service. If
 | 
				
			||||||
 | 
					// there is no user-data setup for the EC2 instance a "NotFoundError" error
 | 
				
			||||||
 | 
					// code will be returned.
 | 
				
			||||||
 | 
					func (c *EC2Metadata) GetUserData() (string, error) {
 | 
				
			||||||
 | 
						op := &request.Operation{
 | 
				
			||||||
 | 
							Name:       "GetUserData",
 | 
				
			||||||
 | 
							HTTPMethod: "GET",
 | 
				
			||||||
 | 
							HTTPPath:   path.Join("/", "user-data"),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output := &metadataOutput{}
 | 
				
			||||||
 | 
						req := c.NewRequest(op, nil, output)
 | 
				
			||||||
 | 
						req.Handlers.UnmarshalError.PushBack(func(r *request.Request) {
 | 
				
			||||||
 | 
							if r.HTTPResponse.StatusCode == http.StatusNotFound {
 | 
				
			||||||
 | 
								r.Error = awserr.New("NotFoundError", "user-data not found", r.Error)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return output.Content, req.Send()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDynamicData uses the path provided to request information from the EC2
 | 
					// GetDynamicData uses the path provided to request information from the EC2
 | 
				
			||||||
// instance metadata service for dynamic data. The content will be returned
 | 
					// instance metadata service for dynamic data. The content will be returned
 | 
				
			||||||
// as a string, or error if the request failed.
 | 
					// as a string, or error if the request failed.
 | 
				
			||||||
| 
						 | 
					@ -111,7 +133,7 @@ func (c *EC2Metadata) Available() bool {
 | 
				
			||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// An EC2IAMInfo provides the shape for unmarshalling
 | 
					// An EC2IAMInfo provides the shape for unmarshaling
 | 
				
			||||||
// an IAM info from the metadata API
 | 
					// an IAM info from the metadata API
 | 
				
			||||||
type EC2IAMInfo struct {
 | 
					type EC2IAMInfo struct {
 | 
				
			||||||
	Code               string
 | 
						Code               string
 | 
				
			||||||
| 
						 | 
					@ -120,7 +142,7 @@ type EC2IAMInfo struct {
 | 
				
			||||||
	InstanceProfileID  string
 | 
						InstanceProfileID  string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// An EC2InstanceIdentityDocument provides the shape for unmarshalling
 | 
					// An EC2InstanceIdentityDocument provides the shape for unmarshaling
 | 
				
			||||||
// an instance identity document
 | 
					// an instance identity document
 | 
				
			||||||
type EC2InstanceIdentityDocument struct {
 | 
					type EC2InstanceIdentityDocument struct {
 | 
				
			||||||
	DevpayProductCodes []string  `json:"devpayProductCodes"`
 | 
						DevpayProductCodes []string  `json:"devpayProductCodes"`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,133 @@
 | 
				
			||||||
 | 
					package endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type modelDefinition map[string]json.RawMessage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A DecodeModelOptions are the options for how the endpoints model definition
 | 
				
			||||||
 | 
					// are decoded.
 | 
				
			||||||
 | 
					type DecodeModelOptions struct {
 | 
				
			||||||
 | 
						SkipCustomizations bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set combines all of the option functions together.
 | 
				
			||||||
 | 
					func (d *DecodeModelOptions) Set(optFns ...func(*DecodeModelOptions)) {
 | 
				
			||||||
 | 
						for _, fn := range optFns {
 | 
				
			||||||
 | 
							fn(d)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DecodeModel unmarshals a Regions and Endpoint model definition file into
 | 
				
			||||||
 | 
					// a endpoint Resolver. If the file format is not supported, or an error occurs
 | 
				
			||||||
 | 
					// when unmarshaling the model an error will be returned.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Casting the return value of this func to a EnumPartitions will
 | 
				
			||||||
 | 
					// allow you to get a list of the partitions in the order the endpoints
 | 
				
			||||||
 | 
					// will be resolved in.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    resolver, err := endpoints.DecodeModel(reader)
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    partitions := resolver.(endpoints.EnumPartitions).Partitions()
 | 
				
			||||||
 | 
					//    for _, p := range partitions {
 | 
				
			||||||
 | 
					//        // ... inspect partitions
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					func DecodeModel(r io.Reader, optFns ...func(*DecodeModelOptions)) (Resolver, error) {
 | 
				
			||||||
 | 
						var opts DecodeModelOptions
 | 
				
			||||||
 | 
						opts.Set(optFns...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the version of the partition file to determine what
 | 
				
			||||||
 | 
						// unmarshaling model to use.
 | 
				
			||||||
 | 
						modelDef := modelDefinition{}
 | 
				
			||||||
 | 
						if err := json.NewDecoder(r).Decode(&modelDef); err != nil {
 | 
				
			||||||
 | 
							return nil, newDecodeModelError("failed to decode endpoints model", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var version string
 | 
				
			||||||
 | 
						if b, ok := modelDef["version"]; ok {
 | 
				
			||||||
 | 
							version = string(b)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return nil, newDecodeModelError("endpoints version not found in model", nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if version == "3" {
 | 
				
			||||||
 | 
							return decodeV3Endpoints(modelDef, opts)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil, newDecodeModelError(
 | 
				
			||||||
 | 
							fmt.Sprintf("endpoints version %s, not supported", version), nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func decodeV3Endpoints(modelDef modelDefinition, opts DecodeModelOptions) (Resolver, error) {
 | 
				
			||||||
 | 
						b, ok := modelDef["partitions"]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return nil, newDecodeModelError("endpoints model missing partitions", nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ps := partitions{}
 | 
				
			||||||
 | 
						if err := json.Unmarshal(b, &ps); err != nil {
 | 
				
			||||||
 | 
							return nil, newDecodeModelError("failed to decode endpoints model", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if opts.SkipCustomizations {
 | 
				
			||||||
 | 
							return ps, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Customization
 | 
				
			||||||
 | 
						for i := 0; i < len(ps); i++ {
 | 
				
			||||||
 | 
							p := &ps[i]
 | 
				
			||||||
 | 
							custAddEC2Metadata(p)
 | 
				
			||||||
 | 
							custAddS3DualStack(p)
 | 
				
			||||||
 | 
							custRmIotDataService(p)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ps, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func custAddS3DualStack(p *partition) {
 | 
				
			||||||
 | 
						if p.ID != "aws" {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s, ok := p.Services["s3"]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s.Defaults.HasDualStack = boxedTrue
 | 
				
			||||||
 | 
						s.Defaults.DualStackHostname = "{service}.dualstack.{region}.{dnsSuffix}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Services["s3"] = s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func custAddEC2Metadata(p *partition) {
 | 
				
			||||||
 | 
						p.Services["ec2metadata"] = service{
 | 
				
			||||||
 | 
							IsRegionalized:    boxedFalse,
 | 
				
			||||||
 | 
							PartitionEndpoint: "aws-global",
 | 
				
			||||||
 | 
							Endpoints: endpoints{
 | 
				
			||||||
 | 
								"aws-global": endpoint{
 | 
				
			||||||
 | 
									Hostname:  "169.254.169.254/latest",
 | 
				
			||||||
 | 
									Protocols: []string{"http"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func custRmIotDataService(p *partition) {
 | 
				
			||||||
 | 
						delete(p.Services, "data.iot")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type decodeModelError struct {
 | 
				
			||||||
 | 
						awsError
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newDecodeModelError(msg string, err error) decodeModelError {
 | 
				
			||||||
 | 
						return decodeModelError{
 | 
				
			||||||
 | 
							awsError: awserr.New("DecodeEndpointsModelError", msg, err),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,66 @@
 | 
				
			||||||
 | 
					// Package endpoints provides the types and functionality for defining regions
 | 
				
			||||||
 | 
					// and endpoints, as well as querying those definitions.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The SDK's Regions and Endpoints metadata is code generated into the endpoints
 | 
				
			||||||
 | 
					// package, and is accessible via the DefaultResolver function. This function
 | 
				
			||||||
 | 
					// returns a endpoint Resolver will search the metadata and build an associated
 | 
				
			||||||
 | 
					// endpoint if one is found. The default resolver will search all partitions
 | 
				
			||||||
 | 
					// known by the SDK. e.g AWS Standard (aws), AWS China (aws-cn), and
 | 
				
			||||||
 | 
					// AWS GovCloud (US) (aws-us-gov).
 | 
				
			||||||
 | 
					// .
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Enumerating Regions and Endpoint Metadata
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Casting the Resolver returned by DefaultResolver to a EnumPartitions interface
 | 
				
			||||||
 | 
					// will allow you to get access to the list of underlying Partitions with the
 | 
				
			||||||
 | 
					// Partitions method. This is helpful if you want to limit the SDK's endpoint
 | 
				
			||||||
 | 
					// resolving to a single partition, or enumerate regions, services, and endpoints
 | 
				
			||||||
 | 
					// in the partition.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     resolver := endpoints.DefaultResolver()
 | 
				
			||||||
 | 
					//     partitions := resolver.(endpoints.EnumPartitions).Partitions()
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     for _, p := range partitions {
 | 
				
			||||||
 | 
					//         fmt.Println("Regions for", p.Name)
 | 
				
			||||||
 | 
					//         for id, _ := range p.Regions() {
 | 
				
			||||||
 | 
					//             fmt.Println("*", id)
 | 
				
			||||||
 | 
					//         }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//         fmt.Println("Services for", p.Name)
 | 
				
			||||||
 | 
					//         for id, _ := range p.Services() {
 | 
				
			||||||
 | 
					//             fmt.Println("*", id)
 | 
				
			||||||
 | 
					//         }
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Using Custom Endpoints
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The endpoints package also gives you the ability to use your own logic how
 | 
				
			||||||
 | 
					// endpoints are resolved. This is a great way to define a custom endpoint
 | 
				
			||||||
 | 
					// for select services, without passing that logic down through your code.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If a type implements the Resolver interface it can be used to resolve
 | 
				
			||||||
 | 
					// endpoints. To use this with the SDK's Session and Config set the value
 | 
				
			||||||
 | 
					// of the type to the EndpointsResolver field of aws.Config when initializing
 | 
				
			||||||
 | 
					// the session, or service client.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// In addition the ResolverFunc is a wrapper for a func matching the signature
 | 
				
			||||||
 | 
					// of Resolver.EndpointFor, converting it to a type that satisfies the
 | 
				
			||||||
 | 
					// Resolver interface.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     myCustomResolver := func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) {
 | 
				
			||||||
 | 
					//         if service == endpoints.S3ServiceID {
 | 
				
			||||||
 | 
					//             return endpoints.ResolvedEndpoint{
 | 
				
			||||||
 | 
					//                 URL:           "s3.custom.endpoint.com",
 | 
				
			||||||
 | 
					//                 SigningRegion: "custom-signing-region",
 | 
				
			||||||
 | 
					//             }, nil
 | 
				
			||||||
 | 
					//         }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//         return endpoints.DefaultResolver().EndpointFor(service, region, optFns...)
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     sess := session.Must(session.NewSession(&aws.Config{
 | 
				
			||||||
 | 
					//         Region:           aws.String("us-west-2"),
 | 
				
			||||||
 | 
					//         EndpointResolver: endpoints.ResolverFunc(myCustomResolver),
 | 
				
			||||||
 | 
					//     }))
 | 
				
			||||||
 | 
					package endpoints
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,369 @@
 | 
				
			||||||
 | 
					package endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Options provide the configuration needed to direct how the
 | 
				
			||||||
 | 
					// endpoints will be resolved.
 | 
				
			||||||
 | 
					type Options struct {
 | 
				
			||||||
 | 
						// DisableSSL forces the endpoint to be resolved as HTTP.
 | 
				
			||||||
 | 
						// instead of HTTPS if the service supports it.
 | 
				
			||||||
 | 
						DisableSSL bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Sets the resolver to resolve the endpoint as a dualstack endpoint
 | 
				
			||||||
 | 
						// for the service. If dualstack support for a service is not known and
 | 
				
			||||||
 | 
						// StrictMatching is not enabled a dualstack endpoint for the service will
 | 
				
			||||||
 | 
						// be returned. This endpoint may not be valid. If StrictMatching is
 | 
				
			||||||
 | 
						// enabled only services that are known to support dualstack will return
 | 
				
			||||||
 | 
						// dualstack endpoints.
 | 
				
			||||||
 | 
						UseDualStack bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Enables strict matching of services and regions resolved endpoints.
 | 
				
			||||||
 | 
						// If the partition doesn't enumerate the exact service and region an
 | 
				
			||||||
 | 
						// error will be returned. This option will prevent returning endpoints
 | 
				
			||||||
 | 
						// that look valid, but may not resolve to any real endpoint.
 | 
				
			||||||
 | 
						StrictMatching bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set combines all of the option functions together.
 | 
				
			||||||
 | 
					func (o *Options) Set(optFns ...func(*Options)) {
 | 
				
			||||||
 | 
						for _, fn := range optFns {
 | 
				
			||||||
 | 
							fn(o)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DisableSSLOption sets the DisableSSL options. Can be used as a functional
 | 
				
			||||||
 | 
					// option when resolving endpoints.
 | 
				
			||||||
 | 
					func DisableSSLOption(o *Options) {
 | 
				
			||||||
 | 
						o.DisableSSL = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UseDualStackOption sets the UseDualStack option. Can be used as a functional
 | 
				
			||||||
 | 
					// option when resolving endpoints.
 | 
				
			||||||
 | 
					func UseDualStackOption(o *Options) {
 | 
				
			||||||
 | 
						o.UseDualStack = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StrictMatchingOption sets the StrictMatching option. Can be used as a functional
 | 
				
			||||||
 | 
					// option when resolving endpoints.
 | 
				
			||||||
 | 
					func StrictMatchingOption(o *Options) {
 | 
				
			||||||
 | 
						o.StrictMatching = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Resolver provides the interface for functionality to resolve endpoints.
 | 
				
			||||||
 | 
					// The build in Partition and DefaultResolver return value satisfy this interface.
 | 
				
			||||||
 | 
					type Resolver interface {
 | 
				
			||||||
 | 
						EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResolverFunc is a helper utility that wraps a function so it satisfies the
 | 
				
			||||||
 | 
					// Resolver interface. This is useful when you want to add additional endpoint
 | 
				
			||||||
 | 
					// resolving logic, or stub out specific endpoints with custom values.
 | 
				
			||||||
 | 
					type ResolverFunc func(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EndpointFor wraps the ResolverFunc function to satisfy the Resolver interface.
 | 
				
			||||||
 | 
					func (fn ResolverFunc) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 | 
				
			||||||
 | 
						return fn(service, region, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var schemeRE = regexp.MustCompile("^([^:]+)://")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddScheme adds the HTTP or HTTPS schemes to a endpoint URL if there is no
 | 
				
			||||||
 | 
					// scheme. If disableSSL is true HTTP will set HTTP instead of the default HTTPS.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If disableSSL is set, it will only set the URL's scheme if the URL does not
 | 
				
			||||||
 | 
					// contain a scheme.
 | 
				
			||||||
 | 
					func AddScheme(endpoint string, disableSSL bool) string {
 | 
				
			||||||
 | 
						if !schemeRE.MatchString(endpoint) {
 | 
				
			||||||
 | 
							scheme := "https"
 | 
				
			||||||
 | 
							if disableSSL {
 | 
				
			||||||
 | 
								scheme = "http"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							endpoint = fmt.Sprintf("%s://%s", scheme, endpoint)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return endpoint
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EnumPartitions a provides a way to retrieve the underlying partitions that
 | 
				
			||||||
 | 
					// make up the SDK's default Resolver, or any resolver decoded from a model
 | 
				
			||||||
 | 
					// file.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Use this interface with DefaultResolver and DecodeModels to get the list of
 | 
				
			||||||
 | 
					// Partitions.
 | 
				
			||||||
 | 
					type EnumPartitions interface {
 | 
				
			||||||
 | 
						Partitions() []Partition
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Partition provides the ability to enumerate the partition's regions
 | 
				
			||||||
 | 
					// and services.
 | 
				
			||||||
 | 
					type Partition struct {
 | 
				
			||||||
 | 
						id string
 | 
				
			||||||
 | 
						p  *partition
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ID returns the identifier of the partition.
 | 
				
			||||||
 | 
					func (p *Partition) ID() string { return p.id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EndpointFor attempts to resolve the endpoint based on service and region.
 | 
				
			||||||
 | 
					// See Options for information on configuring how the endpoint is resolved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If the service cannot be found in the metadata the UnknownServiceError
 | 
				
			||||||
 | 
					// error will be returned. This validation will occur regardless if
 | 
				
			||||||
 | 
					// StrictMatching is enabled.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// When resolving endpoints you can choose to enable StrictMatching. This will
 | 
				
			||||||
 | 
					// require the provided service and region to be known by the partition.
 | 
				
			||||||
 | 
					// If the endpoint cannot be strictly resolved an error will be returned. This
 | 
				
			||||||
 | 
					// mode is useful to ensure the endpoint resolved is valid. Without
 | 
				
			||||||
 | 
					// StrictMatching enabled the enpoint returned my look valid but may not work.
 | 
				
			||||||
 | 
					// StrictMatching requires the SDK to be updated if you want to take advantage
 | 
				
			||||||
 | 
					// of new regions and services expantions.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Errors that can be returned.
 | 
				
			||||||
 | 
					//   * UnknownServiceError
 | 
				
			||||||
 | 
					//   * UnknownEndpointError
 | 
				
			||||||
 | 
					func (p *Partition) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 | 
				
			||||||
 | 
						return p.p.EndpointFor(service, region, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Regions returns a map of Regions indexed by their ID. This is useful for
 | 
				
			||||||
 | 
					// enumerating over the regions in a partition.
 | 
				
			||||||
 | 
					func (p *Partition) Regions() map[string]Region {
 | 
				
			||||||
 | 
						rs := map[string]Region{}
 | 
				
			||||||
 | 
						for id := range p.p.Regions {
 | 
				
			||||||
 | 
							rs[id] = Region{
 | 
				
			||||||
 | 
								id: id,
 | 
				
			||||||
 | 
								p:  p.p,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Services returns a map of Service indexed by their ID. This is useful for
 | 
				
			||||||
 | 
					// enumerating over the services in a partition.
 | 
				
			||||||
 | 
					func (p *Partition) Services() map[string]Service {
 | 
				
			||||||
 | 
						ss := map[string]Service{}
 | 
				
			||||||
 | 
						for id := range p.p.Services {
 | 
				
			||||||
 | 
							ss[id] = Service{
 | 
				
			||||||
 | 
								id: id,
 | 
				
			||||||
 | 
								p:  p.p,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ss
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Region provides information about a region, and ability to resolve an
 | 
				
			||||||
 | 
					// endpoint from the context of a region, given a service.
 | 
				
			||||||
 | 
					type Region struct {
 | 
				
			||||||
 | 
						id, desc string
 | 
				
			||||||
 | 
						p        *partition
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ID returns the region's identifier.
 | 
				
			||||||
 | 
					func (r *Region) ID() string { return r.id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResolveEndpoint resolves an endpoint from the context of the region given
 | 
				
			||||||
 | 
					// a service. See Partition.EndpointFor for usage and errors that can be returned.
 | 
				
			||||||
 | 
					func (r *Region) ResolveEndpoint(service string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 | 
				
			||||||
 | 
						return r.p.EndpointFor(service, r.id, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Services returns a list of all services that are known to be in this region.
 | 
				
			||||||
 | 
					func (r *Region) Services() map[string]Service {
 | 
				
			||||||
 | 
						ss := map[string]Service{}
 | 
				
			||||||
 | 
						for id, s := range r.p.Services {
 | 
				
			||||||
 | 
							if _, ok := s.Endpoints[r.id]; ok {
 | 
				
			||||||
 | 
								ss[id] = Service{
 | 
				
			||||||
 | 
									id: id,
 | 
				
			||||||
 | 
									p:  r.p,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ss
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Service provides information about a service, and ability to resolve an
 | 
				
			||||||
 | 
					// endpoint from the context of a service, given a region.
 | 
				
			||||||
 | 
					type Service struct {
 | 
				
			||||||
 | 
						id string
 | 
				
			||||||
 | 
						p  *partition
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ID returns the identifier for the service.
 | 
				
			||||||
 | 
					func (s *Service) ID() string { return s.id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResolveEndpoint resolves an endpoint from the context of a service given
 | 
				
			||||||
 | 
					// a region. See Partition.EndpointFor for usage and errors that can be returned.
 | 
				
			||||||
 | 
					func (s *Service) ResolveEndpoint(region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 | 
				
			||||||
 | 
						return s.p.EndpointFor(s.id, region, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Endpoints returns a map of Endpoints indexed by their ID for all known
 | 
				
			||||||
 | 
					// endpoints for a service.
 | 
				
			||||||
 | 
					func (s *Service) Endpoints() map[string]Endpoint {
 | 
				
			||||||
 | 
						es := map[string]Endpoint{}
 | 
				
			||||||
 | 
						for id := range s.p.Services[s.id].Endpoints {
 | 
				
			||||||
 | 
							es[id] = Endpoint{
 | 
				
			||||||
 | 
								id:        id,
 | 
				
			||||||
 | 
								serviceID: s.id,
 | 
				
			||||||
 | 
								p:         s.p,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return es
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Endpoint provides information about endpoints, and provides the ability
 | 
				
			||||||
 | 
					// to resolve that endpoint for the service, and the region the endpoint
 | 
				
			||||||
 | 
					// represents.
 | 
				
			||||||
 | 
					type Endpoint struct {
 | 
				
			||||||
 | 
						id        string
 | 
				
			||||||
 | 
						serviceID string
 | 
				
			||||||
 | 
						p         *partition
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ID returns the identifier for an endpoint.
 | 
				
			||||||
 | 
					func (e *Endpoint) ID() string { return e.id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ServiceID returns the identifier the endpoint belongs to.
 | 
				
			||||||
 | 
					func (e *Endpoint) ServiceID() string { return e.serviceID }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResolveEndpoint resolves an endpoint from the context of a service and
 | 
				
			||||||
 | 
					// region the endpoint represents. See Partition.EndpointFor for usage and
 | 
				
			||||||
 | 
					// errors that can be returned.
 | 
				
			||||||
 | 
					func (e *Endpoint) ResolveEndpoint(opts ...func(*Options)) (ResolvedEndpoint, error) {
 | 
				
			||||||
 | 
						return e.p.EndpointFor(e.serviceID, e.id, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A ResolvedEndpoint is an endpoint that has been resolved based on a partition
 | 
				
			||||||
 | 
					// service, and region.
 | 
				
			||||||
 | 
					type ResolvedEndpoint struct {
 | 
				
			||||||
 | 
						// The endpoint URL
 | 
				
			||||||
 | 
						URL string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The region that should be used for signing requests.
 | 
				
			||||||
 | 
						SigningRegion string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The service name that should be used for signing requests.
 | 
				
			||||||
 | 
						SigningName string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The signing method that should be used for signing requests.
 | 
				
			||||||
 | 
						SigningMethod string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// So that the Error interface type can be included as an anonymous field
 | 
				
			||||||
 | 
					// in the requestError struct and not conflict with the error.Error() method.
 | 
				
			||||||
 | 
					type awsError awserr.Error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A EndpointNotFoundError is returned when in StrictMatching mode, and the
 | 
				
			||||||
 | 
					// endpoint for the service and region cannot be found in any of the partitions.
 | 
				
			||||||
 | 
					type EndpointNotFoundError struct {
 | 
				
			||||||
 | 
						awsError
 | 
				
			||||||
 | 
						Partition string
 | 
				
			||||||
 | 
						Service   string
 | 
				
			||||||
 | 
						Region    string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//// NewEndpointNotFoundError builds and returns NewEndpointNotFoundError.
 | 
				
			||||||
 | 
					//func NewEndpointNotFoundError(p, s, r string) EndpointNotFoundError {
 | 
				
			||||||
 | 
					//	return EndpointNotFoundError{
 | 
				
			||||||
 | 
					//		awsError:  awserr.New("EndpointNotFoundError", "unable to find endpoint", nil),
 | 
				
			||||||
 | 
					//		Partition: p,
 | 
				
			||||||
 | 
					//		Service:   s,
 | 
				
			||||||
 | 
					//		Region:    r,
 | 
				
			||||||
 | 
					//	}
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//// Error returns string representation of the error.
 | 
				
			||||||
 | 
					//func (e EndpointNotFoundError) Error() string {
 | 
				
			||||||
 | 
					//	extra := fmt.Sprintf("partition: %q, service: %q, region: %q",
 | 
				
			||||||
 | 
					//		e.Partition, e.Service, e.Region)
 | 
				
			||||||
 | 
					//	return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//// String returns the string representation of the error.
 | 
				
			||||||
 | 
					//func (e EndpointNotFoundError) String() string {
 | 
				
			||||||
 | 
					//	return e.Error()
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A UnknownServiceError is returned when the service does not resolve to an
 | 
				
			||||||
 | 
					// endpoint. Includes a list of all known services for the partition. Returned
 | 
				
			||||||
 | 
					// when a partition does not support the service.
 | 
				
			||||||
 | 
					type UnknownServiceError struct {
 | 
				
			||||||
 | 
						awsError
 | 
				
			||||||
 | 
						Partition string
 | 
				
			||||||
 | 
						Service   string
 | 
				
			||||||
 | 
						Known     []string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewUnknownServiceError builds and returns UnknownServiceError.
 | 
				
			||||||
 | 
					func NewUnknownServiceError(p, s string, known []string) UnknownServiceError {
 | 
				
			||||||
 | 
						return UnknownServiceError{
 | 
				
			||||||
 | 
							awsError: awserr.New("UnknownServiceError",
 | 
				
			||||||
 | 
								"could not resolve endpoint for unknown service", nil),
 | 
				
			||||||
 | 
							Partition: p,
 | 
				
			||||||
 | 
							Service:   s,
 | 
				
			||||||
 | 
							Known:     known,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// String returns the string representation of the error.
 | 
				
			||||||
 | 
					func (e UnknownServiceError) Error() string {
 | 
				
			||||||
 | 
						extra := fmt.Sprintf("partition: %q, service: %q",
 | 
				
			||||||
 | 
							e.Partition, e.Service)
 | 
				
			||||||
 | 
						if len(e.Known) > 0 {
 | 
				
			||||||
 | 
							extra += fmt.Sprintf(", known: %v", e.Known)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// String returns the string representation of the error.
 | 
				
			||||||
 | 
					func (e UnknownServiceError) String() string {
 | 
				
			||||||
 | 
						return e.Error()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A UnknownEndpointError is returned when in StrictMatching mode and the
 | 
				
			||||||
 | 
					// service is valid, but the region does not resolve to an endpoint. Includes
 | 
				
			||||||
 | 
					// a list of all known endpoints for the service.
 | 
				
			||||||
 | 
					type UnknownEndpointError struct {
 | 
				
			||||||
 | 
						awsError
 | 
				
			||||||
 | 
						Partition string
 | 
				
			||||||
 | 
						Service   string
 | 
				
			||||||
 | 
						Region    string
 | 
				
			||||||
 | 
						Known     []string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewUnknownEndpointError builds and returns UnknownEndpointError.
 | 
				
			||||||
 | 
					func NewUnknownEndpointError(p, s, r string, known []string) UnknownEndpointError {
 | 
				
			||||||
 | 
						return UnknownEndpointError{
 | 
				
			||||||
 | 
							awsError: awserr.New("UnknownEndpointError",
 | 
				
			||||||
 | 
								"could not resolve endpoint", nil),
 | 
				
			||||||
 | 
							Partition: p,
 | 
				
			||||||
 | 
							Service:   s,
 | 
				
			||||||
 | 
							Region:    r,
 | 
				
			||||||
 | 
							Known:     known,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// String returns the string representation of the error.
 | 
				
			||||||
 | 
					func (e UnknownEndpointError) Error() string {
 | 
				
			||||||
 | 
						extra := fmt.Sprintf("partition: %q, service: %q, region: %q",
 | 
				
			||||||
 | 
							e.Partition, e.Service, e.Region)
 | 
				
			||||||
 | 
						if len(e.Known) > 0 {
 | 
				
			||||||
 | 
							extra += fmt.Sprintf(", known: %v", e.Known)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// String returns the string representation of the error.
 | 
				
			||||||
 | 
					func (e UnknownEndpointError) String() string {
 | 
				
			||||||
 | 
						return e.Error()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,301 @@
 | 
				
			||||||
 | 
					package endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type partitions []partition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ps partitions) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 | 
				
			||||||
 | 
						var opt Options
 | 
				
			||||||
 | 
						opt.Set(opts...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(ps); i++ {
 | 
				
			||||||
 | 
							if !ps[i].canResolveEndpoint(service, region, opt.StrictMatching) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return ps[i].EndpointFor(service, region, opts...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If loose matching fallback to first partition format to use
 | 
				
			||||||
 | 
						// when resolving the endpoint.
 | 
				
			||||||
 | 
						if !opt.StrictMatching && len(ps) > 0 {
 | 
				
			||||||
 | 
							return ps[0].EndpointFor(service, region, opts...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ResolvedEndpoint{}, NewUnknownEndpointError("all partitions", service, region, []string{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Partitions satisfies the EnumPartitions interface and returns a list
 | 
				
			||||||
 | 
					// of Partitions representing each partition represented in the SDK's
 | 
				
			||||||
 | 
					// endpoints model.
 | 
				
			||||||
 | 
					func (ps partitions) Partitions() []Partition {
 | 
				
			||||||
 | 
						parts := make([]Partition, 0, len(ps))
 | 
				
			||||||
 | 
						for i := 0; i < len(ps); i++ {
 | 
				
			||||||
 | 
							parts = append(parts, ps[i].Partition())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return parts
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type partition struct {
 | 
				
			||||||
 | 
						ID          string      `json:"partition"`
 | 
				
			||||||
 | 
						Name        string      `json:"partitionName"`
 | 
				
			||||||
 | 
						DNSSuffix   string      `json:"dnsSuffix"`
 | 
				
			||||||
 | 
						RegionRegex regionRegex `json:"regionRegex"`
 | 
				
			||||||
 | 
						Defaults    endpoint    `json:"defaults"`
 | 
				
			||||||
 | 
						Regions     regions     `json:"regions"`
 | 
				
			||||||
 | 
						Services    services    `json:"services"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p partition) Partition() Partition {
 | 
				
			||||||
 | 
						return Partition{
 | 
				
			||||||
 | 
							id: p.ID,
 | 
				
			||||||
 | 
							p:  &p,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p partition) canResolveEndpoint(service, region string, strictMatch bool) bool {
 | 
				
			||||||
 | 
						s, hasService := p.Services[service]
 | 
				
			||||||
 | 
						_, hasEndpoint := s.Endpoints[region]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if hasEndpoint && hasService {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if strictMatch {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p.RegionRegex.MatchString(region)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p partition) EndpointFor(service, region string, opts ...func(*Options)) (resolved ResolvedEndpoint, err error) {
 | 
				
			||||||
 | 
						var opt Options
 | 
				
			||||||
 | 
						opt.Set(opts...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s, hasService := p.Services[service]
 | 
				
			||||||
 | 
						if !hasService {
 | 
				
			||||||
 | 
							return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e, hasEndpoint := s.endpointForRegion(region)
 | 
				
			||||||
 | 
						if !hasEndpoint && opt.StrictMatching {
 | 
				
			||||||
 | 
							return resolved, NewUnknownEndpointError(p.ID, service, region, endpointList(s.Endpoints))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defs := []endpoint{p.Defaults, s.Defaults}
 | 
				
			||||||
 | 
						return e.resolve(service, region, p.DNSSuffix, defs, opt), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serviceList(ss services) []string {
 | 
				
			||||||
 | 
						list := make([]string, 0, len(ss))
 | 
				
			||||||
 | 
						for k := range ss {
 | 
				
			||||||
 | 
							list = append(list, k)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return list
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func endpointList(es endpoints) []string {
 | 
				
			||||||
 | 
						list := make([]string, 0, len(es))
 | 
				
			||||||
 | 
						for k := range es {
 | 
				
			||||||
 | 
							list = append(list, k)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return list
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type regionRegex struct {
 | 
				
			||||||
 | 
						*regexp.Regexp
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (rr *regionRegex) UnmarshalJSON(b []byte) (err error) {
 | 
				
			||||||
 | 
						// Strip leading and trailing quotes
 | 
				
			||||||
 | 
						regex, err := strconv.Unquote(string(b))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("unable to strip quotes from regex, %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rr.Regexp, err = regexp.Compile(regex)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("unable to unmarshal region regex, %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type regions map[string]region
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type region struct {
 | 
				
			||||||
 | 
						Description string `json:"description"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type services map[string]service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type service struct {
 | 
				
			||||||
 | 
						PartitionEndpoint string    `json:"partitionEndpoint"`
 | 
				
			||||||
 | 
						IsRegionalized    boxedBool `json:"isRegionalized,omitempty"`
 | 
				
			||||||
 | 
						Defaults          endpoint  `json:"defaults"`
 | 
				
			||||||
 | 
						Endpoints         endpoints `json:"endpoints"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *service) endpointForRegion(region string) (endpoint, bool) {
 | 
				
			||||||
 | 
						if s.IsRegionalized == boxedFalse {
 | 
				
			||||||
 | 
							return s.Endpoints[s.PartitionEndpoint], region == s.PartitionEndpoint
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e, ok := s.Endpoints[region]; ok {
 | 
				
			||||||
 | 
							return e, true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Unable to find any matching endpoint, return
 | 
				
			||||||
 | 
						// blank that will be used for generic endpoint creation.
 | 
				
			||||||
 | 
						return endpoint{}, false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type endpoints map[string]endpoint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type endpoint struct {
 | 
				
			||||||
 | 
						Hostname        string          `json:"hostname"`
 | 
				
			||||||
 | 
						Protocols       []string        `json:"protocols"`
 | 
				
			||||||
 | 
						CredentialScope credentialScope `json:"credentialScope"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Custom fields not modeled
 | 
				
			||||||
 | 
						HasDualStack      boxedBool `json:"-"`
 | 
				
			||||||
 | 
						DualStackHostname string    `json:"-"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Signature Version not used
 | 
				
			||||||
 | 
						SignatureVersions []string `json:"signatureVersions"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// SSLCommonName not used.
 | 
				
			||||||
 | 
						SSLCommonName string `json:"sslCommonName"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						defaultProtocol = "https"
 | 
				
			||||||
 | 
						defaultSigner   = "v4"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						protocolPriority = []string{"https", "http"}
 | 
				
			||||||
 | 
						signerPriority   = []string{"v4", "v2"}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getByPriority(s []string, p []string, def string) string {
 | 
				
			||||||
 | 
						if len(s) == 0 {
 | 
				
			||||||
 | 
							return def
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(p); i++ {
 | 
				
			||||||
 | 
							for j := 0; j < len(s); j++ {
 | 
				
			||||||
 | 
								if s[j] == p[i] {
 | 
				
			||||||
 | 
									return s[j]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return s[0]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e endpoint) resolve(service, region, dnsSuffix string, defs []endpoint, opts Options) ResolvedEndpoint {
 | 
				
			||||||
 | 
						var merged endpoint
 | 
				
			||||||
 | 
						for _, def := range defs {
 | 
				
			||||||
 | 
							merged.mergeIn(def)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						merged.mergeIn(e)
 | 
				
			||||||
 | 
						e = merged
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostname := e.Hostname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Offset the hostname for dualstack if enabled
 | 
				
			||||||
 | 
						if opts.UseDualStack && e.HasDualStack == boxedTrue {
 | 
				
			||||||
 | 
							hostname = e.DualStackHostname
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u := strings.Replace(hostname, "{service}", service, 1)
 | 
				
			||||||
 | 
						u = strings.Replace(u, "{region}", region, 1)
 | 
				
			||||||
 | 
						u = strings.Replace(u, "{dnsSuffix}", dnsSuffix, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scheme := getEndpointScheme(e.Protocols, opts.DisableSSL)
 | 
				
			||||||
 | 
						u = fmt.Sprintf("%s://%s", scheme, u)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signingRegion := e.CredentialScope.Region
 | 
				
			||||||
 | 
						if len(signingRegion) == 0 {
 | 
				
			||||||
 | 
							signingRegion = region
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						signingName := e.CredentialScope.Service
 | 
				
			||||||
 | 
						if len(signingName) == 0 {
 | 
				
			||||||
 | 
							signingName = service
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ResolvedEndpoint{
 | 
				
			||||||
 | 
							URL:           u,
 | 
				
			||||||
 | 
							SigningRegion: signingRegion,
 | 
				
			||||||
 | 
							SigningName:   signingName,
 | 
				
			||||||
 | 
							SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getEndpointScheme(protocols []string, disableSSL bool) string {
 | 
				
			||||||
 | 
						if disableSSL {
 | 
				
			||||||
 | 
							return "http"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return getByPriority(protocols, protocolPriority, defaultProtocol)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *endpoint) mergeIn(other endpoint) {
 | 
				
			||||||
 | 
						if len(other.Hostname) > 0 {
 | 
				
			||||||
 | 
							e.Hostname = other.Hostname
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(other.Protocols) > 0 {
 | 
				
			||||||
 | 
							e.Protocols = other.Protocols
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(other.SignatureVersions) > 0 {
 | 
				
			||||||
 | 
							e.SignatureVersions = other.SignatureVersions
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(other.CredentialScope.Region) > 0 {
 | 
				
			||||||
 | 
							e.CredentialScope.Region = other.CredentialScope.Region
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(other.CredentialScope.Service) > 0 {
 | 
				
			||||||
 | 
							e.CredentialScope.Service = other.CredentialScope.Service
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(other.SSLCommonName) > 0 {
 | 
				
			||||||
 | 
							e.SSLCommonName = other.SSLCommonName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if other.HasDualStack != boxedBoolUnset {
 | 
				
			||||||
 | 
							e.HasDualStack = other.HasDualStack
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(other.DualStackHostname) > 0 {
 | 
				
			||||||
 | 
							e.DualStackHostname = other.DualStackHostname
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type credentialScope struct {
 | 
				
			||||||
 | 
						Region  string `json:"region"`
 | 
				
			||||||
 | 
						Service string `json:"service"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type boxedBool int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *boxedBool) UnmarshalJSON(buf []byte) error {
 | 
				
			||||||
 | 
						v, err := strconv.ParseBool(string(buf))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if v {
 | 
				
			||||||
 | 
							*b = boxedTrue
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							*b = boxedFalse
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						boxedBoolUnset boxedBool = iota
 | 
				
			||||||
 | 
						boxedFalse
 | 
				
			||||||
 | 
						boxedTrue
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										334
									
								
								vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										334
									
								
								vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							| 
						 | 
					@ -0,0 +1,334 @@
 | 
				
			||||||
 | 
					// +build codegen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"text/template"
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A CodeGenOptions are the options for code generating the endpoints into
 | 
				
			||||||
 | 
					// Go code from the endpoints model definition.
 | 
				
			||||||
 | 
					type CodeGenOptions struct {
 | 
				
			||||||
 | 
						// Options for how the model will be decoded.
 | 
				
			||||||
 | 
						DecodeModelOptions DecodeModelOptions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set combines all of the option functions together
 | 
				
			||||||
 | 
					func (d *CodeGenOptions) Set(optFns ...func(*CodeGenOptions)) {
 | 
				
			||||||
 | 
						for _, fn := range optFns {
 | 
				
			||||||
 | 
							fn(d)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CodeGenModel given a endpoints model file will decode it and attempt to
 | 
				
			||||||
 | 
					// generate Go code from the model definition. Error will be returned if
 | 
				
			||||||
 | 
					// the code is unable to be generated, or decoded.
 | 
				
			||||||
 | 
					func CodeGenModel(modelFile io.Reader, outFile io.Writer, optFns ...func(*CodeGenOptions)) error {
 | 
				
			||||||
 | 
						var opts CodeGenOptions
 | 
				
			||||||
 | 
						opts.Set(optFns...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resolver, err := DecodeModel(modelFile, func(d *DecodeModelOptions) {
 | 
				
			||||||
 | 
							*d = opts.DecodeModelOptions
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmpl := template.Must(template.New("tmpl").Funcs(funcMap).Parse(v3Tmpl))
 | 
				
			||||||
 | 
						if err := tmpl.ExecuteTemplate(outFile, "defaults", resolver); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to execute template, %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func toSymbol(v string) string {
 | 
				
			||||||
 | 
						out := []rune{}
 | 
				
			||||||
 | 
						for _, c := range strings.Title(v) {
 | 
				
			||||||
 | 
							if !(unicode.IsNumber(c) || unicode.IsLetter(c)) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							out = append(out, c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return string(out)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func quoteString(v string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("%q", v)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func regionConstName(p, r string) string {
 | 
				
			||||||
 | 
						return toSymbol(p) + toSymbol(r)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func partitionGetter(id string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("%sPartition", toSymbol(id))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func partitionVarName(id string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("%sPartition", strings.ToLower(toSymbol(id)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func listPartitionNames(ps partitions) string {
 | 
				
			||||||
 | 
						names := []string{}
 | 
				
			||||||
 | 
						switch len(ps) {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							return ps[0].Name
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							return fmt.Sprintf("%s and %s", ps[0].Name, ps[1].Name)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							for i, p := range ps {
 | 
				
			||||||
 | 
								if i == len(ps)-1 {
 | 
				
			||||||
 | 
									names = append(names, "and "+p.Name)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									names = append(names, p.Name)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return strings.Join(names, ", ")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func boxedBoolIfSet(msg string, v boxedBool) string {
 | 
				
			||||||
 | 
						switch v {
 | 
				
			||||||
 | 
						case boxedTrue:
 | 
				
			||||||
 | 
							return fmt.Sprintf(msg, "boxedTrue")
 | 
				
			||||||
 | 
						case boxedFalse:
 | 
				
			||||||
 | 
							return fmt.Sprintf(msg, "boxedFalse")
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func stringIfSet(msg, v string) string {
 | 
				
			||||||
 | 
						if len(v) == 0 {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fmt.Sprintf(msg, v)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func stringSliceIfSet(msg string, vs []string) string {
 | 
				
			||||||
 | 
						if len(vs) == 0 {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						names := []string{}
 | 
				
			||||||
 | 
						for _, v := range vs {
 | 
				
			||||||
 | 
							names = append(names, `"`+v+`"`)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fmt.Sprintf(msg, strings.Join(names, ","))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func endpointIsSet(v endpoint) bool {
 | 
				
			||||||
 | 
						return !reflect.DeepEqual(v, endpoint{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serviceSet(ps partitions) map[string]struct{} {
 | 
				
			||||||
 | 
						set := map[string]struct{}{}
 | 
				
			||||||
 | 
						for _, p := range ps {
 | 
				
			||||||
 | 
							for id := range p.Services {
 | 
				
			||||||
 | 
								set[id] = struct{}{}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return set
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var funcMap = template.FuncMap{
 | 
				
			||||||
 | 
						"ToSymbol":           toSymbol,
 | 
				
			||||||
 | 
						"QuoteString":        quoteString,
 | 
				
			||||||
 | 
						"RegionConst":        regionConstName,
 | 
				
			||||||
 | 
						"PartitionGetter":    partitionGetter,
 | 
				
			||||||
 | 
						"PartitionVarName":   partitionVarName,
 | 
				
			||||||
 | 
						"ListPartitionNames": listPartitionNames,
 | 
				
			||||||
 | 
						"BoxedBoolIfSet":     boxedBoolIfSet,
 | 
				
			||||||
 | 
						"StringIfSet":        stringIfSet,
 | 
				
			||||||
 | 
						"StringSliceIfSet":   stringSliceIfSet,
 | 
				
			||||||
 | 
						"EndpointIsSet":      endpointIsSet,
 | 
				
			||||||
 | 
						"ServicesSet":        serviceSet,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const v3Tmpl = `
 | 
				
			||||||
 | 
					{{ define "defaults" -}}
 | 
				
			||||||
 | 
					// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package endpoints
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{{ template "partition consts" . }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{{ range $_, $partition := . }}
 | 
				
			||||||
 | 
							{{ template "partition region consts" $partition }}
 | 
				
			||||||
 | 
						{{ end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{{ template "service consts" . }}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						{{ template "endpoint resolvers" . }}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "partition consts" }}
 | 
				
			||||||
 | 
						// Partition identifiers
 | 
				
			||||||
 | 
						const (
 | 
				
			||||||
 | 
							{{ range $_, $p := . -}}
 | 
				
			||||||
 | 
								{{ ToSymbol $p.ID }}PartitionID = {{ QuoteString $p.ID }} // {{ $p.Name }} partition.
 | 
				
			||||||
 | 
							{{ end -}}
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "partition region consts" }}
 | 
				
			||||||
 | 
						// {{ .Name }} partition's regions.
 | 
				
			||||||
 | 
						const (
 | 
				
			||||||
 | 
							{{ range $id, $region := .Regions -}}
 | 
				
			||||||
 | 
								{{ ToSymbol $id }}RegionID = {{ QuoteString $id }} // {{ $region.Description }}.
 | 
				
			||||||
 | 
							{{ end -}}
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "service consts" }}
 | 
				
			||||||
 | 
						// Service identifiers
 | 
				
			||||||
 | 
						const (
 | 
				
			||||||
 | 
							{{ $serviceSet := ServicesSet . -}}
 | 
				
			||||||
 | 
							{{ range $id, $_ := $serviceSet -}}
 | 
				
			||||||
 | 
								{{ ToSymbol $id }}ServiceID = {{ QuoteString $id }} // {{ ToSymbol $id }}.
 | 
				
			||||||
 | 
							{{ end -}}
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "endpoint resolvers" }}
 | 
				
			||||||
 | 
						// DefaultResolver returns an Endpoint resolver that will be able
 | 
				
			||||||
 | 
						// to resolve endpoints for: {{ ListPartitionNames . }}.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Casting the return value of this func to a EnumPartitions will
 | 
				
			||||||
 | 
						// allow you to get a list of the partitions in the order the endpoints
 | 
				
			||||||
 | 
						// will be resolved in.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//    resolver := endpoints.DefaultResolver()
 | 
				
			||||||
 | 
						//    partitions := resolver.(endpoints.EnumPartitions).Partitions()
 | 
				
			||||||
 | 
						//    for _, p := range partitions {
 | 
				
			||||||
 | 
						//        // ... inspect partitions
 | 
				
			||||||
 | 
						//    }
 | 
				
			||||||
 | 
						func DefaultResolver() Resolver {
 | 
				
			||||||
 | 
							return defaultPartitions
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var defaultPartitions = partitions{
 | 
				
			||||||
 | 
							{{ range $_, $partition := . -}}
 | 
				
			||||||
 | 
								{{ PartitionVarName $partition.ID }},
 | 
				
			||||||
 | 
							{{ end }}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						{{ range $_, $partition := . -}}
 | 
				
			||||||
 | 
							{{ $name := PartitionGetter $partition.ID -}}
 | 
				
			||||||
 | 
							// {{ $name }} returns the Resolver for {{ $partition.Name }}.
 | 
				
			||||||
 | 
							func {{ $name }}() Partition {
 | 
				
			||||||
 | 
								return  {{ PartitionVarName $partition.ID }}.Partition()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var {{ PartitionVarName $partition.ID }} = {{ template "gocode Partition" $partition }}
 | 
				
			||||||
 | 
						{{ end }}
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "default partitions" }}
 | 
				
			||||||
 | 
						func DefaultPartitions() []Partition {
 | 
				
			||||||
 | 
							return []partition{
 | 
				
			||||||
 | 
								{{ range $_, $partition := . -}}
 | 
				
			||||||
 | 
								// {{ ToSymbol $partition.ID}}Partition(),
 | 
				
			||||||
 | 
								{{ end }}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode Partition" -}}
 | 
				
			||||||
 | 
					partition{
 | 
				
			||||||
 | 
						{{ StringIfSet "ID: %q,\n" .ID -}}
 | 
				
			||||||
 | 
						{{ StringIfSet "Name: %q,\n" .Name -}}
 | 
				
			||||||
 | 
						{{ StringIfSet "DNSSuffix: %q,\n" .DNSSuffix -}}
 | 
				
			||||||
 | 
						RegionRegex: {{ template "gocode RegionRegex" .RegionRegex }},
 | 
				
			||||||
 | 
						{{ if EndpointIsSet .Defaults -}}
 | 
				
			||||||
 | 
							Defaults: {{ template "gocode Endpoint" .Defaults }},
 | 
				
			||||||
 | 
						{{- end }}
 | 
				
			||||||
 | 
						Regions:  {{ template "gocode Regions" .Regions }},
 | 
				
			||||||
 | 
						Services: {{ template "gocode Services" .Services }},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode RegionRegex" -}}
 | 
				
			||||||
 | 
					regionRegex{
 | 
				
			||||||
 | 
						Regexp: func() *regexp.Regexp{
 | 
				
			||||||
 | 
							reg, _ := regexp.Compile({{ QuoteString .Regexp.String }})
 | 
				
			||||||
 | 
							return reg
 | 
				
			||||||
 | 
						}(),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode Regions" -}}
 | 
				
			||||||
 | 
					regions{
 | 
				
			||||||
 | 
						{{ range $id, $region := . -}}
 | 
				
			||||||
 | 
							"{{ $id }}": {{ template "gocode Region" $region }},
 | 
				
			||||||
 | 
						{{ end -}}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode Region" -}}
 | 
				
			||||||
 | 
					region{
 | 
				
			||||||
 | 
						{{ StringIfSet "Description: %q,\n" .Description -}}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode Services" -}}
 | 
				
			||||||
 | 
					services{
 | 
				
			||||||
 | 
						{{ range $id, $service := . -}}
 | 
				
			||||||
 | 
						"{{ $id }}": {{ template "gocode Service" $service }},
 | 
				
			||||||
 | 
						{{ end }}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode Service" -}}
 | 
				
			||||||
 | 
					service{
 | 
				
			||||||
 | 
						{{ StringIfSet "PartitionEndpoint: %q,\n" .PartitionEndpoint -}}
 | 
				
			||||||
 | 
						{{ BoxedBoolIfSet "IsRegionalized: %s,\n" .IsRegionalized -}}
 | 
				
			||||||
 | 
						{{ if EndpointIsSet .Defaults -}}
 | 
				
			||||||
 | 
							Defaults: {{ template "gocode Endpoint" .Defaults -}},
 | 
				
			||||||
 | 
						{{- end }}
 | 
				
			||||||
 | 
						{{ if .Endpoints -}}
 | 
				
			||||||
 | 
							Endpoints: {{ template "gocode Endpoints" .Endpoints }},
 | 
				
			||||||
 | 
						{{- end }}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode Endpoints" -}}
 | 
				
			||||||
 | 
					endpoints{
 | 
				
			||||||
 | 
						{{ range $id, $endpoint := . -}}
 | 
				
			||||||
 | 
						"{{ $id }}": {{ template "gocode Endpoint" $endpoint }},
 | 
				
			||||||
 | 
						{{ end }}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{ define "gocode Endpoint" -}}
 | 
				
			||||||
 | 
					endpoint{
 | 
				
			||||||
 | 
						{{ StringIfSet "Hostname: %q,\n" .Hostname -}}
 | 
				
			||||||
 | 
						{{ StringIfSet "SSLCommonName: %q,\n" .SSLCommonName -}}
 | 
				
			||||||
 | 
						{{ StringSliceIfSet "Protocols: []string{%s},\n" .Protocols -}}
 | 
				
			||||||
 | 
						{{ StringSliceIfSet "SignatureVersions: []string{%s},\n" .SignatureVersions -}}
 | 
				
			||||||
 | 
						{{ if or .CredentialScope.Region .CredentialScope.Service -}}
 | 
				
			||||||
 | 
						CredentialScope: credentialScope{
 | 
				
			||||||
 | 
							{{ StringIfSet "Region: %q,\n" .CredentialScope.Region -}}
 | 
				
			||||||
 | 
							{{ StringIfSet "Service: %q,\n" .CredentialScope.Service -}}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{{- end }}
 | 
				
			||||||
 | 
						{{ BoxedBoolIfSet "HasDualStack: %s,\n" .HasDualStack -}}
 | 
				
			||||||
 | 
						{{ StringIfSet "DualStackHostname: %q,\n" .DualStackHostname -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,3 @@
 | 
				
			||||||
// +build go1.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package request
 | 
					package request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
| 
						 | 
					@ -9,20 +7,13 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
 | 
					func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
 | 
				
			||||||
	req := &http.Request{
 | 
						req := new(http.Request)
 | 
				
			||||||
		URL:           &url.URL{},
 | 
						*req = *r
 | 
				
			||||||
		Header:        http.Header{},
 | 
						req.URL = &url.URL{}
 | 
				
			||||||
		Close:         r.Close,
 | 
					 | 
				
			||||||
		Body:          body,
 | 
					 | 
				
			||||||
		Host:          r.Host,
 | 
					 | 
				
			||||||
		Method:        r.Method,
 | 
					 | 
				
			||||||
		Proto:         r.Proto,
 | 
					 | 
				
			||||||
		ContentLength: r.ContentLength,
 | 
					 | 
				
			||||||
		// Cancel will be deprecated in 1.7 and will be replaced with Context
 | 
					 | 
				
			||||||
		Cancel: r.Cancel,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*req.URL = *r.URL
 | 
						*req.URL = *r.URL
 | 
				
			||||||
 | 
						req.Body = body
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req.Header = http.Header{}
 | 
				
			||||||
	for k, v := range r.Header {
 | 
						for k, v := range r.Header {
 | 
				
			||||||
		for _, vv := range v {
 | 
							for _, vv := range v {
 | 
				
			||||||
			req.Header.Add(k, vv)
 | 
								req.Header.Add(k, vv)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,31 +0,0 @@
 | 
				
			||||||
// +build !go1.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package request
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"net/url"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
 | 
					 | 
				
			||||||
	req := &http.Request{
 | 
					 | 
				
			||||||
		URL:           &url.URL{},
 | 
					 | 
				
			||||||
		Header:        http.Header{},
 | 
					 | 
				
			||||||
		Close:         r.Close,
 | 
					 | 
				
			||||||
		Body:          body,
 | 
					 | 
				
			||||||
		Host:          r.Host,
 | 
					 | 
				
			||||||
		Method:        r.Method,
 | 
					 | 
				
			||||||
		Proto:         r.Proto,
 | 
					 | 
				
			||||||
		ContentLength: r.ContentLength,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*req.URL = *r.URL
 | 
					 | 
				
			||||||
	for k, v := range r.Header {
 | 
					 | 
				
			||||||
		for _, vv := range v {
 | 
					 | 
				
			||||||
			req.Header.Add(k, vv)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return req
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import (
 | 
				
			||||||
// with retrying requests
 | 
					// with retrying requests
 | 
				
			||||||
type offsetReader struct {
 | 
					type offsetReader struct {
 | 
				
			||||||
	buf    io.ReadSeeker
 | 
						buf    io.ReadSeeker
 | 
				
			||||||
	lock   sync.RWMutex
 | 
						lock   sync.Mutex
 | 
				
			||||||
	closed bool
 | 
						closed bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,8 @@ func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader {
 | 
				
			||||||
	return reader
 | 
						return reader
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Close is a thread-safe close. Uses the write lock.
 | 
					// Close will close the instance of the offset reader's access to
 | 
				
			||||||
 | 
					// the underlying io.ReadSeeker.
 | 
				
			||||||
func (o *offsetReader) Close() error {
 | 
					func (o *offsetReader) Close() error {
 | 
				
			||||||
	o.lock.Lock()
 | 
						o.lock.Lock()
 | 
				
			||||||
	defer o.lock.Unlock()
 | 
						defer o.lock.Unlock()
 | 
				
			||||||
| 
						 | 
					@ -29,10 +30,10 @@ func (o *offsetReader) Close() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Read is a thread-safe read using a read lock.
 | 
					// Read is a thread-safe read of the underlying io.ReadSeeker
 | 
				
			||||||
func (o *offsetReader) Read(p []byte) (int, error) {
 | 
					func (o *offsetReader) Read(p []byte) (int, error) {
 | 
				
			||||||
	o.lock.RLock()
 | 
						o.lock.Lock()
 | 
				
			||||||
	defer o.lock.RUnlock()
 | 
						defer o.lock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if o.closed {
 | 
						if o.closed {
 | 
				
			||||||
		return 0, io.EOF
 | 
							return 0, io.EOF
 | 
				
			||||||
| 
						 | 
					@ -41,6 +42,14 @@ func (o *offsetReader) Read(p []byte) (int, error) {
 | 
				
			||||||
	return o.buf.Read(p)
 | 
						return o.buf.Read(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Seek is a thread-safe seeking operation.
 | 
				
			||||||
 | 
					func (o *offsetReader) Seek(offset int64, whence int) (int64, error) {
 | 
				
			||||||
 | 
						o.lock.Lock()
 | 
				
			||||||
 | 
						defer o.lock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return o.buf.Seek(offset, whence)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CloseAndCopy will return a new offsetReader with a copy of the old buffer
 | 
					// CloseAndCopy will return a new offsetReader with a copy of the old buffer
 | 
				
			||||||
// and close the old buffer.
 | 
					// and close the old buffer.
 | 
				
			||||||
func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader {
 | 
					func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
						"net"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
| 
						 | 
					@ -42,6 +42,12 @@ type Request struct {
 | 
				
			||||||
	LastSignedAt     time.Time
 | 
						LastSignedAt     time.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	built bool
 | 
						built bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Need to persist an intermideant body betweend the input Body and HTTP
 | 
				
			||||||
 | 
						// request body because the HTTP Client's transport can maintain a reference
 | 
				
			||||||
 | 
						// to the HTTP request's body after the client has returned. This value is
 | 
				
			||||||
 | 
						// safe to use concurrently and rewraps the input Body for each HTTP request.
 | 
				
			||||||
 | 
						safeBody *offsetReader
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// An Operation is the service API operation to be made.
 | 
					// An Operation is the service API operation to be made.
 | 
				
			||||||
| 
						 | 
					@ -50,6 +56,8 @@ type Operation struct {
 | 
				
			||||||
	HTTPMethod string
 | 
						HTTPMethod string
 | 
				
			||||||
	HTTPPath   string
 | 
						HTTPPath   string
 | 
				
			||||||
	*Paginator
 | 
						*Paginator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BeforePresignFn func(r *Request) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Paginator keeps track of pagination configuration for an API operation.
 | 
					// Paginator keeps track of pagination configuration for an API operation.
 | 
				
			||||||
| 
						 | 
					@ -73,15 +81,11 @@ func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,
 | 
				
			||||||
	if method == "" {
 | 
						if method == "" {
 | 
				
			||||||
		method = "POST"
 | 
							method = "POST"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p := operation.HTTPPath
 | 
					 | 
				
			||||||
	if p == "" {
 | 
					 | 
				
			||||||
		p = "/"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	httpReq, _ := http.NewRequest(method, "", nil)
 | 
						httpReq, _ := http.NewRequest(method, "", nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	httpReq.URL, err = url.Parse(clientInfo.Endpoint + p)
 | 
						httpReq.URL, err = url.Parse(clientInfo.Endpoint + operation.HTTPPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		httpReq.URL = &url.URL{}
 | 
							httpReq.URL = &url.URL{}
 | 
				
			||||||
		err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err)
 | 
							err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err)
 | 
				
			||||||
| 
						 | 
					@ -139,8 +143,8 @@ func (r *Request) SetStringBody(s string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetReaderBody will set the request's body reader.
 | 
					// SetReaderBody will set the request's body reader.
 | 
				
			||||||
func (r *Request) SetReaderBody(reader io.ReadSeeker) {
 | 
					func (r *Request) SetReaderBody(reader io.ReadSeeker) {
 | 
				
			||||||
	r.HTTPRequest.Body = newOffsetReader(reader, 0)
 | 
					 | 
				
			||||||
	r.Body = reader
 | 
						r.Body = reader
 | 
				
			||||||
 | 
						r.ResetBody()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Presign returns the request's signed URL. Error will be returned
 | 
					// Presign returns the request's signed URL. Error will be returned
 | 
				
			||||||
| 
						 | 
					@ -148,6 +152,15 @@ func (r *Request) SetReaderBody(reader io.ReadSeeker) {
 | 
				
			||||||
func (r *Request) Presign(expireTime time.Duration) (string, error) {
 | 
					func (r *Request) Presign(expireTime time.Duration) (string, error) {
 | 
				
			||||||
	r.ExpireTime = expireTime
 | 
						r.ExpireTime = expireTime
 | 
				
			||||||
	r.NotHoist = false
 | 
						r.NotHoist = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.Operation.BeforePresignFn != nil {
 | 
				
			||||||
 | 
							r = r.copy()
 | 
				
			||||||
 | 
							err := r.Operation.BeforePresignFn(r)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return "", err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r.Sign()
 | 
						r.Sign()
 | 
				
			||||||
	if r.Error != nil {
 | 
						if r.Error != nil {
 | 
				
			||||||
		return "", r.Error
 | 
							return "", r.Error
 | 
				
			||||||
| 
						 | 
					@ -224,6 +237,99 @@ func (r *Request) Sign() error {
 | 
				
			||||||
	return r.Error
 | 
						return r.Error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResetBody rewinds the request body backto its starting position, and
 | 
				
			||||||
 | 
					// set's the HTTP Request body reference. When the body is read prior
 | 
				
			||||||
 | 
					// to being sent in the HTTP request it will need to be rewound.
 | 
				
			||||||
 | 
					func (r *Request) ResetBody() {
 | 
				
			||||||
 | 
						if r.safeBody != nil {
 | 
				
			||||||
 | 
							r.safeBody.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r.safeBody = newOffsetReader(r.Body, r.BodyStart)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Go 1.8 tightened and clarified the rules code needs to use when building
 | 
				
			||||||
 | 
						// requests with the http package. Go 1.8 removed the automatic detection
 | 
				
			||||||
 | 
						// of if the Request.Body was empty, or actually had bytes in it. The SDK
 | 
				
			||||||
 | 
						// always sets the Request.Body even if it is empty and should not actually
 | 
				
			||||||
 | 
						// be sent. This is incorrect.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Go 1.8 did add a http.NoBody value that the SDK can use to tell the http
 | 
				
			||||||
 | 
						// client that the request really should be sent without a body. The
 | 
				
			||||||
 | 
						// Request.Body cannot be set to nil, which is preferable, because the
 | 
				
			||||||
 | 
						// field is exported and could introduce nil pointer dereferences for users
 | 
				
			||||||
 | 
						// of the SDK if they used that field.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Related golang/go#18257
 | 
				
			||||||
 | 
						l, err := computeBodyLength(r.Body)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							r.Error = awserr.New("SerializationError", "failed to compute request body size", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if l == 0 {
 | 
				
			||||||
 | 
							r.HTTPRequest.Body = noBodyReader
 | 
				
			||||||
 | 
						} else if l > 0 {
 | 
				
			||||||
 | 
							r.HTTPRequest.Body = r.safeBody
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// Hack to prevent sending bodies for methods where the body
 | 
				
			||||||
 | 
							// should be ignored by the server. Sending bodies on these
 | 
				
			||||||
 | 
							// methods without an associated ContentLength will cause the
 | 
				
			||||||
 | 
							// request to socket timeout because the server does not handle
 | 
				
			||||||
 | 
							// Transfer-Encoding: chunked bodies for these methods.
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							// This would only happen if a aws.ReaderSeekerCloser was used with
 | 
				
			||||||
 | 
							// a io.Reader that was not also an io.Seeker.
 | 
				
			||||||
 | 
							switch r.Operation.HTTPMethod {
 | 
				
			||||||
 | 
							case "GET", "HEAD", "DELETE":
 | 
				
			||||||
 | 
								r.HTTPRequest.Body = noBodyReader
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								r.HTTPRequest.Body = r.safeBody
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Attempts to compute the length of the body of the reader using the
 | 
				
			||||||
 | 
					// io.Seeker interface. If the value is not seekable because of being
 | 
				
			||||||
 | 
					// a ReaderSeekerCloser without an unerlying Seeker -1 will be returned.
 | 
				
			||||||
 | 
					// If no error occurs the length of the body will be returned.
 | 
				
			||||||
 | 
					func computeBodyLength(r io.ReadSeeker) (int64, error) {
 | 
				
			||||||
 | 
						seekable := true
 | 
				
			||||||
 | 
						// Determine if the seeker is actually seekable. ReaderSeekerCloser
 | 
				
			||||||
 | 
						// hides the fact that a io.Readers might not actually be seekable.
 | 
				
			||||||
 | 
						switch v := r.(type) {
 | 
				
			||||||
 | 
						case aws.ReaderSeekerCloser:
 | 
				
			||||||
 | 
							seekable = v.IsSeeker()
 | 
				
			||||||
 | 
						case *aws.ReaderSeekerCloser:
 | 
				
			||||||
 | 
							seekable = v.IsSeeker()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !seekable {
 | 
				
			||||||
 | 
							return -1, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						curOffset, err := r.Seek(0, 1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						endOffset, err := r.Seek(0, 2)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = r.Seek(curOffset, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return endOffset - curOffset, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetBody will return an io.ReadSeeker of the Request's underlying
 | 
				
			||||||
 | 
					// input body with a concurrency safe wrapper.
 | 
				
			||||||
 | 
					func (r *Request) GetBody() io.ReadSeeker {
 | 
				
			||||||
 | 
						return r.safeBody
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Send will send the request returning error if errors are encountered.
 | 
					// Send will send the request returning error if errors are encountered.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Send will sign the request prior to sending. All Send Handlers will
 | 
					// Send will sign the request prior to sending. All Send Handlers will
 | 
				
			||||||
| 
						 | 
					@ -235,6 +341,8 @@ func (r *Request) Sign() error {
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// readLoop() and getConn(req *Request, cm connectMethod)
 | 
					// readLoop() and getConn(req *Request, cm connectMethod)
 | 
				
			||||||
// https://github.com/golang/go/blob/master/src/net/http/transport.go
 | 
					// https://github.com/golang/go/blob/master/src/net/http/transport.go
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Send will not close the request.Request's body.
 | 
				
			||||||
func (r *Request) Send() error {
 | 
					func (r *Request) Send() error {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		if aws.BoolValue(r.Retryable) {
 | 
							if aws.BoolValue(r.Retryable) {
 | 
				
			||||||
| 
						 | 
					@ -243,21 +351,15 @@ func (r *Request) Send() error {
 | 
				
			||||||
					r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
 | 
										r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var body io.ReadCloser
 | 
								// The previous http.Request will have a reference to the r.Body
 | 
				
			||||||
			if reader, ok := r.HTTPRequest.Body.(*offsetReader); ok {
 | 
								// and the HTTP Client's Transport may still be reading from
 | 
				
			||||||
				body = reader.CloseAndCopy(r.BodyStart)
 | 
								// the request's body even though the Client's Do returned.
 | 
				
			||||||
			} else {
 | 
								r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil)
 | 
				
			||||||
				if r.Config.Logger != nil {
 | 
								r.ResetBody()
 | 
				
			||||||
					r.Config.Logger.Log("Request body type has been overwritten. May cause race conditions")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				r.Body.Seek(r.BodyStart, 0)
 | 
					 | 
				
			||||||
				body = ioutil.NopCloser(r.Body)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, body)
 | 
								// Closing response body to ensure that no response body is leaked
 | 
				
			||||||
 | 
								// between retry attempts.
 | 
				
			||||||
			if r.HTTPResponse != nil && r.HTTPResponse.Body != nil {
 | 
								if r.HTTPResponse != nil && r.HTTPResponse.Body != nil {
 | 
				
			||||||
				// Closing response body. Since we are setting a new request to send off, this
 | 
					 | 
				
			||||||
				// response will get squashed and leaked.
 | 
					 | 
				
			||||||
				r.HTTPResponse.Body.Close()
 | 
									r.HTTPResponse.Body.Close()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -271,7 +373,7 @@ func (r *Request) Send() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		r.Handlers.Send.Run(r)
 | 
							r.Handlers.Send.Run(r)
 | 
				
			||||||
		if r.Error != nil {
 | 
							if r.Error != nil {
 | 
				
			||||||
			if strings.Contains(r.Error.Error(), "net/http: request canceled") {
 | 
								if !shouldRetryCancel(r) {
 | 
				
			||||||
				return r.Error
 | 
									return r.Error
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,7 +387,6 @@ func (r *Request) Send() error {
 | 
				
			||||||
			debugLogReqError(r, "Send Request", true, err)
 | 
								debugLogReqError(r, "Send Request", true, err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		r.Handlers.UnmarshalMeta.Run(r)
 | 
							r.Handlers.UnmarshalMeta.Run(r)
 | 
				
			||||||
		r.Handlers.ValidateResponse.Run(r)
 | 
							r.Handlers.ValidateResponse.Run(r)
 | 
				
			||||||
		if r.Error != nil {
 | 
							if r.Error != nil {
 | 
				
			||||||
| 
						 | 
					@ -320,6 +421,17 @@ func (r *Request) Send() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// copy will copy a request which will allow for local manipulation of the
 | 
				
			||||||
 | 
					// request.
 | 
				
			||||||
 | 
					func (r *Request) copy() *Request {
 | 
				
			||||||
 | 
						req := &Request{}
 | 
				
			||||||
 | 
						*req = *r
 | 
				
			||||||
 | 
						req.Handlers = r.Handlers.Copy()
 | 
				
			||||||
 | 
						op := *r.Operation
 | 
				
			||||||
 | 
						req.Operation = &op
 | 
				
			||||||
 | 
						return req
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AddToUserAgent adds the string to the end of the request's current user agent.
 | 
					// AddToUserAgent adds the string to the end of the request's current user agent.
 | 
				
			||||||
func AddToUserAgent(r *Request, s string) {
 | 
					func AddToUserAgent(r *Request, s string) {
 | 
				
			||||||
	curUA := r.HTTPRequest.Header.Get("User-Agent")
 | 
						curUA := r.HTTPRequest.Header.Get("User-Agent")
 | 
				
			||||||
| 
						 | 
					@ -328,3 +440,26 @@ func AddToUserAgent(r *Request, s string) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	r.HTTPRequest.Header.Set("User-Agent", s)
 | 
						r.HTTPRequest.Header.Set("User-Agent", s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func shouldRetryCancel(r *Request) bool {
 | 
				
			||||||
 | 
						awsErr, ok := r.Error.(awserr.Error)
 | 
				
			||||||
 | 
						timeoutErr := false
 | 
				
			||||||
 | 
						errStr := r.Error.Error()
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							err := awsErr.OrigErr()
 | 
				
			||||||
 | 
							netErr, netOK := err.(net.Error)
 | 
				
			||||||
 | 
							timeoutErr = netOK && netErr.Temporary()
 | 
				
			||||||
 | 
							if urlErr, ok := err.(*url.Error); !timeoutErr && ok {
 | 
				
			||||||
 | 
								errStr = urlErr.Err.Error()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// There can be two types of canceled errors here.
 | 
				
			||||||
 | 
						// The first being a net.Error and the other being an error.
 | 
				
			||||||
 | 
						// If the request was timed out, we want to continue the retry
 | 
				
			||||||
 | 
						// process. Otherwise, return the canceled error.
 | 
				
			||||||
 | 
						return timeoutErr ||
 | 
				
			||||||
 | 
							(errStr != "net/http: request canceled" &&
 | 
				
			||||||
 | 
								errStr != "net/http: request canceled while waiting for connection")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					// +build !go1.8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
 | 
				
			||||||
 | 
					// and Close always returns nil. It can be used in an outgoing client
 | 
				
			||||||
 | 
					// request to explicitly signal that a request has zero bytes.
 | 
				
			||||||
 | 
					// An alternative, however, is to simply set Request.Body to nil.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copy of Go 1.8 NoBody type from net/http/http.go
 | 
				
			||||||
 | 
					type noBody struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (noBody) Read([]byte) (int, error)         { return 0, io.EOF }
 | 
				
			||||||
 | 
					func (noBody) Close() error                     { return nil }
 | 
				
			||||||
 | 
					func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Is an empty reader that will trigger the Go HTTP client to not include
 | 
				
			||||||
 | 
					// and body in the HTTP request.
 | 
				
			||||||
 | 
					var noBodyReader = noBody{}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					// +build go1.8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Is a http.NoBody reader instructing Go HTTP client to not include
 | 
				
			||||||
 | 
					// and body in the HTTP request.
 | 
				
			||||||
 | 
					var noBodyReader = http.NoBody
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@ var throttleCodes = map[string]struct{}{
 | 
				
			||||||
	"RequestThrottled":                       {},
 | 
						"RequestThrottled":                       {},
 | 
				
			||||||
	"LimitExceededException":                 {}, // Deleting 10+ DynamoDb tables at once
 | 
						"LimitExceededException":                 {}, // Deleting 10+ DynamoDb tables at once
 | 
				
			||||||
	"TooManyRequestsException":               {}, // Lambda functions
 | 
						"TooManyRequestsException":               {}, // Lambda functions
 | 
				
			||||||
 | 
						"PriorRequestNotComplete":                {}, // Route53
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// credsExpiredCodes is a collection of error codes which signify the credentials
 | 
					// credsExpiredCodes is a collection of error codes which signify the credentials
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,223 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Package session provides configuration for the SDK's service clients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sessions can be shared across all service clients that share the same base
 | 
				
			||||||
 | 
					configuration.  The Session is built from the SDK's default configuration and
 | 
				
			||||||
 | 
					request handlers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sessions should be cached when possible, because creating a new Session will
 | 
				
			||||||
 | 
					load all configuration values from the environment, and config files each time
 | 
				
			||||||
 | 
					the Session is created. Sharing the Session value across all of your service
 | 
				
			||||||
 | 
					clients will ensure the configuration is loaded the fewest number of times possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Concurrency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sessions are safe to use concurrently as long as the Session is not being
 | 
				
			||||||
 | 
					modified. The SDK will not modify the Session once the Session has been created.
 | 
				
			||||||
 | 
					Creating service clients concurrently from a shared Session is safe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sessions from Shared Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sessions can be created using the method above that will only load the
 | 
				
			||||||
 | 
					additional config if the AWS_SDK_LOAD_CONFIG environment variable is set.
 | 
				
			||||||
 | 
					Alternatively you can explicitly create a Session with shared config enabled.
 | 
				
			||||||
 | 
					To do this you can use NewSessionWithOptions to configure how the Session will
 | 
				
			||||||
 | 
					be created. Using the NewSessionWithOptions with SharedConfigState set to
 | 
				
			||||||
 | 
					SharedConfigEnabled will create the session as if the AWS_SDK_LOAD_CONFIG
 | 
				
			||||||
 | 
					environment variable was set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Creating Sessions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When creating Sessions optional aws.Config values can be passed in that will
 | 
				
			||||||
 | 
					override the default, or loaded config values the Session is being created
 | 
				
			||||||
 | 
					with. This allows you to provide additional, or case based, configuration
 | 
				
			||||||
 | 
					as needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By default NewSession will only load credentials from the shared credentials
 | 
				
			||||||
 | 
					file (~/.aws/credentials). If the AWS_SDK_LOAD_CONFIG environment variable is
 | 
				
			||||||
 | 
					set to a truthy value the Session will be created from the configuration
 | 
				
			||||||
 | 
					values from the shared config (~/.aws/config) and shared credentials
 | 
				
			||||||
 | 
					(~/.aws/credentials) files. See the section Sessions from Shared Config for
 | 
				
			||||||
 | 
					more information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create a Session with the default config and request handlers. With credentials
 | 
				
			||||||
 | 
					region, and profile loaded from the environment and shared config automatically.
 | 
				
			||||||
 | 
					Requires the AWS_PROFILE to be set, or "default" is used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create Session
 | 
				
			||||||
 | 
						sess, err := session.NewSession()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create a Session with a custom region
 | 
				
			||||||
 | 
						sess, err := session.NewSession(&aws.Config{Region: aws.String("us-east-1")})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create a S3 client instance from a session
 | 
				
			||||||
 | 
						sess, err := session.NewSession()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// Handle Session creation error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						svc := s3.New(sess)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create Session With Option Overrides
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In addition to NewSession, Sessions can be created using NewSessionWithOptions.
 | 
				
			||||||
 | 
					This func allows you to control and override how the Session will be created
 | 
				
			||||||
 | 
					through code instead of being driven by environment variables only.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use NewSessionWithOptions when you want to provide the config profile, or
 | 
				
			||||||
 | 
					override the shared config state (AWS_SDK_LOAD_CONFIG).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Equivalent to session.NewSession()
 | 
				
			||||||
 | 
						sess, err := session.NewSessionWithOptions(session.Options{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Specify profile to load for the session's config
 | 
				
			||||||
 | 
						sess, err := session.NewSessionWithOptions(session.Options{
 | 
				
			||||||
 | 
							 Profile: "profile_name",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Specify profile for config and region for requests
 | 
				
			||||||
 | 
						sess, err := session.NewSessionWithOptions(session.Options{
 | 
				
			||||||
 | 
							 Config: aws.Config{Region: aws.String("us-east-1")},
 | 
				
			||||||
 | 
							 Profile: "profile_name",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Force enable Shared Config support
 | 
				
			||||||
 | 
						sess, err := session.NewSessionWithOptions(session.Options{
 | 
				
			||||||
 | 
							SharedConfigState: SharedConfigEnable,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Adding Handlers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can add handlers to a session for processing HTTP requests. All service
 | 
				
			||||||
 | 
					clients that use the session inherit the handlers. For example, the following
 | 
				
			||||||
 | 
					handler logs every request and its payload made by a service client:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create a session, and add additional handlers for all service
 | 
				
			||||||
 | 
						// clients created with the Session to inherit. Adds logging handler.
 | 
				
			||||||
 | 
						sess, err := session.NewSession()
 | 
				
			||||||
 | 
						sess.Handlers.Send.PushFront(func(r *request.Request) {
 | 
				
			||||||
 | 
							// Log every request made and its payload
 | 
				
			||||||
 | 
							logger.Println("Request: %s/%s, Payload: %s",
 | 
				
			||||||
 | 
								r.ClientInfo.ServiceName, r.Operation, r.Params)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Deprecated "New" function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The New session function has been deprecated because it does not provide good
 | 
				
			||||||
 | 
					way to return errors that occur when loading the configuration files and values.
 | 
				
			||||||
 | 
					Because of this, NewSession was created so errors can be retrieved when
 | 
				
			||||||
 | 
					creating a session fails.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Shared Config Fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By default the SDK will only load the shared credentials file's (~/.aws/credentials)
 | 
				
			||||||
 | 
					credentials values, and all other config is provided by the environment variables,
 | 
				
			||||||
 | 
					SDK defaults, and user provided aws.Config values.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the AWS_SDK_LOAD_CONFIG environment variable is set, or SharedConfigEnable
 | 
				
			||||||
 | 
					option is used to create the Session the full shared config values will be
 | 
				
			||||||
 | 
					loaded. This includes credentials, region, and support for assume role. In
 | 
				
			||||||
 | 
					addition the Session will load its configuration from both the shared config
 | 
				
			||||||
 | 
					file (~/.aws/config) and shared credentials file (~/.aws/credentials). Both
 | 
				
			||||||
 | 
					files have the same format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If both config files are present the configuration from both files will be
 | 
				
			||||||
 | 
					read. The Session will be created from  configuration values from the shared
 | 
				
			||||||
 | 
					credentials file (~/.aws/credentials) over those in the shared credentials
 | 
				
			||||||
 | 
					file (~/.aws/config).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Credentials are the values the SDK should use for authenticating requests with
 | 
				
			||||||
 | 
					AWS Services. They arfrom a configuration file will need to include both
 | 
				
			||||||
 | 
					aws_access_key_id and aws_secret_access_key must be provided together in the
 | 
				
			||||||
 | 
					same file to be considered valid. The values will be ignored if not a complete
 | 
				
			||||||
 | 
					group. aws_session_token is an optional field that can be provided if both of
 | 
				
			||||||
 | 
					the other two fields are also provided.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aws_access_key_id = AKID
 | 
				
			||||||
 | 
						aws_secret_access_key = SECRET
 | 
				
			||||||
 | 
						aws_session_token = TOKEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Assume Role values allow you to configure the SDK to assume an IAM role using
 | 
				
			||||||
 | 
					a set of credentials provided in a config file via the source_profile field.
 | 
				
			||||||
 | 
					Both "role_arn" and "source_profile" are required. The SDK does not support
 | 
				
			||||||
 | 
					assuming a role with MFA token Via the Session's constructor. You can use the
 | 
				
			||||||
 | 
					stscreds.AssumeRoleProvider credentials provider to specify custom
 | 
				
			||||||
 | 
					configuration and support for MFA.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						role_arn = arn:aws:iam::<account_number>:role/<role_name>
 | 
				
			||||||
 | 
						source_profile = profile_with_creds
 | 
				
			||||||
 | 
						external_id = 1234
 | 
				
			||||||
 | 
						mfa_serial = not supported!
 | 
				
			||||||
 | 
						role_session_name = session_name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Region is the region the SDK should use for looking up AWS service endpoints
 | 
				
			||||||
 | 
					and signing requests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						region = us-east-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Environment Variables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When a Session is created several environment variables can be set to adjust
 | 
				
			||||||
 | 
					how the SDK functions, and what configuration data it loads when creating
 | 
				
			||||||
 | 
					Sessions. All environment values are optional, but some values like credentials
 | 
				
			||||||
 | 
					require multiple of the values to set or the partial values will be ignored.
 | 
				
			||||||
 | 
					All environment variable values are strings unless otherwise noted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Environment configuration values. If set both Access Key ID and Secret Access
 | 
				
			||||||
 | 
					Key must be provided. Session Token and optionally also be provided, but is
 | 
				
			||||||
 | 
					not required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Access Key ID
 | 
				
			||||||
 | 
						AWS_ACCESS_KEY_ID=AKID
 | 
				
			||||||
 | 
						AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Secret Access Key
 | 
				
			||||||
 | 
						AWS_SECRET_ACCESS_KEY=SECRET
 | 
				
			||||||
 | 
						AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Session Token
 | 
				
			||||||
 | 
						AWS_SESSION_TOKEN=TOKEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Region value will instruct the SDK where to make service API requests to. If is
 | 
				
			||||||
 | 
					not provided in the environment the region must be provided before a service
 | 
				
			||||||
 | 
					client request is made.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AWS_REGION=us-east-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set,
 | 
				
			||||||
 | 
						# and AWS_REGION is not also set.
 | 
				
			||||||
 | 
						AWS_DEFAULT_REGION=us-east-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Profile name the SDK should load use when loading shared config from the
 | 
				
			||||||
 | 
					configuration files. If not provided "default" will be used as the profile name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AWS_PROFILE=my_profile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set,
 | 
				
			||||||
 | 
						# and AWS_PROFILE is not also set.
 | 
				
			||||||
 | 
						AWS_DEFAULT_PROFILE=my_profile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SDK load config instructs the SDK to load the shared config in addition to
 | 
				
			||||||
 | 
					shared credentials. This also expands the configuration loaded so the shared
 | 
				
			||||||
 | 
					credentials will have parity with the shared config file. This also enables
 | 
				
			||||||
 | 
					Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE
 | 
				
			||||||
 | 
					env values as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AWS_SDK_LOAD_CONFIG=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Shared credentials file path can be set to instruct the SDK to use an alternative
 | 
				
			||||||
 | 
					file for the shared credentials. If not set the file will be loaded from
 | 
				
			||||||
 | 
					$HOME/.aws/credentials on Linux/Unix based systems, and
 | 
				
			||||||
 | 
					%USERPROFILE%\.aws\credentials on Windows.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Shared config file path can be set to instruct the SDK to use an alternative
 | 
				
			||||||
 | 
					file for the shared config. If not set the file will be loaded from
 | 
				
			||||||
 | 
					$HOME/.aws/config on Linux/Unix based systems, and
 | 
				
			||||||
 | 
					%USERPROFILE%\.aws\config on Windows.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AWS_CONFIG_FILE=$HOME/my_shared_config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					package session
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,188 @@
 | 
				
			||||||
 | 
					package session
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/credentials"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// envConfig is a collection of environment values the SDK will read
 | 
				
			||||||
 | 
					// setup config from. All environment values are optional. But some values
 | 
				
			||||||
 | 
					// such as credentials require multiple values to be complete or the values
 | 
				
			||||||
 | 
					// will be ignored.
 | 
				
			||||||
 | 
					type envConfig struct {
 | 
				
			||||||
 | 
						// Environment configuration values. If set both Access Key ID and Secret Access
 | 
				
			||||||
 | 
						// Key must be provided. Session Token and optionally also be provided, but is
 | 
				
			||||||
 | 
						// not required.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	# Access Key ID
 | 
				
			||||||
 | 
						//	AWS_ACCESS_KEY_ID=AKID
 | 
				
			||||||
 | 
						//	AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	# Secret Access Key
 | 
				
			||||||
 | 
						//	AWS_SECRET_ACCESS_KEY=SECRET
 | 
				
			||||||
 | 
						//	AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	# Session Token
 | 
				
			||||||
 | 
						//	AWS_SESSION_TOKEN=TOKEN
 | 
				
			||||||
 | 
						Creds credentials.Value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Region value will instruct the SDK where to make service API requests to. If is
 | 
				
			||||||
 | 
						// not provided in the environment the region must be provided before a service
 | 
				
			||||||
 | 
						// client request is made.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	AWS_REGION=us-east-1
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	# AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set,
 | 
				
			||||||
 | 
						//	# and AWS_REGION is not also set.
 | 
				
			||||||
 | 
						//	AWS_DEFAULT_REGION=us-east-1
 | 
				
			||||||
 | 
						Region string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Profile name the SDK should load use when loading shared configuration from the
 | 
				
			||||||
 | 
						// shared configuration files. If not provided "default" will be used as the
 | 
				
			||||||
 | 
						// profile name.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	AWS_PROFILE=my_profile
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	# AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set,
 | 
				
			||||||
 | 
						//	# and AWS_PROFILE is not also set.
 | 
				
			||||||
 | 
						//	AWS_DEFAULT_PROFILE=my_profile
 | 
				
			||||||
 | 
						Profile string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// SDK load config instructs the SDK to load the shared config in addition to
 | 
				
			||||||
 | 
						// shared credentials. This also expands the configuration loaded from the shared
 | 
				
			||||||
 | 
						// credentials to have parity with the shared config file. This also enables
 | 
				
			||||||
 | 
						// Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE
 | 
				
			||||||
 | 
						// env values as well.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	AWS_SDK_LOAD_CONFIG=1
 | 
				
			||||||
 | 
						EnableSharedConfig bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shared credentials file path can be set to instruct the SDK to use an alternate
 | 
				
			||||||
 | 
						// file for the shared credentials. If not set the file will be loaded from
 | 
				
			||||||
 | 
						// $HOME/.aws/credentials on Linux/Unix based systems, and
 | 
				
			||||||
 | 
						// %USERPROFILE%\.aws\credentials on Windows.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
 | 
				
			||||||
 | 
						SharedCredentialsFile string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shared config file path can be set to instruct the SDK to use an alternate
 | 
				
			||||||
 | 
						// file for the shared config. If not set the file will be loaded from
 | 
				
			||||||
 | 
						// $HOME/.aws/config on Linux/Unix based systems, and
 | 
				
			||||||
 | 
						// %USERPROFILE%\.aws\config on Windows.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	AWS_CONFIG_FILE=$HOME/my_shared_config
 | 
				
			||||||
 | 
						SharedConfigFile string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						credAccessEnvKey = []string{
 | 
				
			||||||
 | 
							"AWS_ACCESS_KEY_ID",
 | 
				
			||||||
 | 
							"AWS_ACCESS_KEY",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						credSecretEnvKey = []string{
 | 
				
			||||||
 | 
							"AWS_SECRET_ACCESS_KEY",
 | 
				
			||||||
 | 
							"AWS_SECRET_KEY",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						credSessionEnvKey = []string{
 | 
				
			||||||
 | 
							"AWS_SESSION_TOKEN",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regionEnvKeys = []string{
 | 
				
			||||||
 | 
							"AWS_REGION",
 | 
				
			||||||
 | 
							"AWS_DEFAULT_REGION", // Only read if AWS_SDK_LOAD_CONFIG is also set
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						profileEnvKeys = []string{
 | 
				
			||||||
 | 
							"AWS_PROFILE",
 | 
				
			||||||
 | 
							"AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// loadEnvConfig retrieves the SDK's environment configuration.
 | 
				
			||||||
 | 
					// See `envConfig` for the values that will be retrieved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If the environment variable `AWS_SDK_LOAD_CONFIG` is set to a truthy value
 | 
				
			||||||
 | 
					// the shared SDK config will be loaded in addition to the SDK's specific
 | 
				
			||||||
 | 
					// configuration values.
 | 
				
			||||||
 | 
					func loadEnvConfig() envConfig {
 | 
				
			||||||
 | 
						enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG"))
 | 
				
			||||||
 | 
						return envConfigLoad(enableSharedConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// loadEnvSharedConfig retrieves the SDK's environment configuration, and the
 | 
				
			||||||
 | 
					// SDK shared config. See `envConfig` for the values that will be retrieved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Loads the shared configuration in addition to the SDK's specific configuration.
 | 
				
			||||||
 | 
					// This will load the same values as `loadEnvConfig` if the `AWS_SDK_LOAD_CONFIG`
 | 
				
			||||||
 | 
					// environment variable is set.
 | 
				
			||||||
 | 
					func loadSharedEnvConfig() envConfig {
 | 
				
			||||||
 | 
						return envConfigLoad(true)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func envConfigLoad(enableSharedConfig bool) envConfig {
 | 
				
			||||||
 | 
						cfg := envConfig{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg.EnableSharedConfig = enableSharedConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setFromEnvVal(&cfg.Creds.AccessKeyID, credAccessEnvKey)
 | 
				
			||||||
 | 
						setFromEnvVal(&cfg.Creds.SecretAccessKey, credSecretEnvKey)
 | 
				
			||||||
 | 
						setFromEnvVal(&cfg.Creds.SessionToken, credSessionEnvKey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Require logical grouping of credentials
 | 
				
			||||||
 | 
						if len(cfg.Creds.AccessKeyID) == 0 || len(cfg.Creds.SecretAccessKey) == 0 {
 | 
				
			||||||
 | 
							cfg.Creds = credentials.Value{}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							cfg.Creds.ProviderName = "EnvConfigCredentials"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regionKeys := regionEnvKeys
 | 
				
			||||||
 | 
						profileKeys := profileEnvKeys
 | 
				
			||||||
 | 
						if !cfg.EnableSharedConfig {
 | 
				
			||||||
 | 
							regionKeys = regionKeys[:1]
 | 
				
			||||||
 | 
							profileKeys = profileKeys[:1]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setFromEnvVal(&cfg.Region, regionKeys)
 | 
				
			||||||
 | 
						setFromEnvVal(&cfg.Profile, profileKeys)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg.SharedCredentialsFile = sharedCredentialsFilename()
 | 
				
			||||||
 | 
						cfg.SharedConfigFile = sharedConfigFilename()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cfg
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func setFromEnvVal(dst *string, keys []string) {
 | 
				
			||||||
 | 
						for _, k := range keys {
 | 
				
			||||||
 | 
							if v := os.Getenv(k); len(v) > 0 {
 | 
				
			||||||
 | 
								*dst = v
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sharedCredentialsFilename() string {
 | 
				
			||||||
 | 
						if name := os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(name) > 0 {
 | 
				
			||||||
 | 
							return name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return filepath.Join(userHomeDir(), ".aws", "credentials")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sharedConfigFilename() string {
 | 
				
			||||||
 | 
						if name := os.Getenv("AWS_CONFIG_FILE"); len(name) > 0 {
 | 
				
			||||||
 | 
							return name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return filepath.Join(userHomeDir(), ".aws", "config")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func userHomeDir() string {
 | 
				
			||||||
 | 
						homeDir := os.Getenv("HOME") // *nix
 | 
				
			||||||
 | 
						if len(homeDir) == 0 {       // windows
 | 
				
			||||||
 | 
							homeDir = os.Getenv("USERPROFILE")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return homeDir
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,62 +1,232 @@
 | 
				
			||||||
// Package session provides a way to create service clients with shared configuration
 | 
					 | 
				
			||||||
// and handlers.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Generally this package should be used instead of the `defaults` package.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A session should be used to share configurations and request handlers between multiple
 | 
					 | 
				
			||||||
// service clients. When service clients need specific configuration aws.Config can be
 | 
					 | 
				
			||||||
// used to provide additional configuration directly to the service client.
 | 
					 | 
				
			||||||
package session
 | 
					package session
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws"
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/client"
 | 
						"github.com/aws/aws-sdk-go/aws/client"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/corehandlers"
 | 
						"github.com/aws/aws-sdk-go/aws/corehandlers"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/credentials"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/defaults"
 | 
						"github.com/aws/aws-sdk-go/aws/defaults"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/endpoints"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/request"
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/private/endpoints"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A Session provides a central location to create service clients from and
 | 
					// A Session provides a central location to create service clients from and
 | 
				
			||||||
// store configurations and request handlers for those services.
 | 
					// store configurations and request handlers for those services.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Sessions are safe to create service clients concurrently, but it is not safe
 | 
					// Sessions are safe to create service clients concurrently, but it is not safe
 | 
				
			||||||
// to mutate the session concurrently.
 | 
					// to mutate the Session concurrently.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The Session satisfies the service client's client.ClientConfigProvider.
 | 
				
			||||||
type Session struct {
 | 
					type Session struct {
 | 
				
			||||||
	Config   *aws.Config
 | 
						Config   *aws.Config
 | 
				
			||||||
	Handlers request.Handlers
 | 
						Handlers request.Handlers
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New creates a new instance of the handlers merging in the provided Configs
 | 
					// New creates a new instance of the handlers merging in the provided configs
 | 
				
			||||||
// on top of the SDK's default configurations. Once the session is created it
 | 
					// on top of the SDK's default configurations. Once the Session is created it
 | 
				
			||||||
// can be mutated to modify Configs or Handlers. The session is safe to be read
 | 
					// can be mutated to modify the Config or Handlers. The Session is safe to be
 | 
				
			||||||
// concurrently, but it should not be written to concurrently.
 | 
					// read concurrently, but it should not be written to concurrently.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Example:
 | 
					// If the AWS_SDK_LOAD_CONFIG environment is set to a truthy value, the New
 | 
				
			||||||
//     // Create a session with the default config and request handlers.
 | 
					// method could now encounter an error when loading the configuration. When
 | 
				
			||||||
//     sess := session.New()
 | 
					// The environment variable is set, and an error occurs, New will return a
 | 
				
			||||||
 | 
					// session that will fail all requests reporting the error that occurred while
 | 
				
			||||||
 | 
					// loading the session. Use NewSession to get the error when creating the
 | 
				
			||||||
 | 
					// session.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//     // Create a session with a custom region
 | 
					// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
 | 
				
			||||||
//     sess := session.New(&aws.Config{Region: aws.String("us-east-1")})
 | 
					// the shared config file (~/.aws/config) will also be loaded, in addition to
 | 
				
			||||||
 | 
					// the shared credentials file (~/.aws/config). Values set in both the
 | 
				
			||||||
 | 
					// shared config, and shared credentials will be taken from the shared
 | 
				
			||||||
 | 
					// credentials file.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//     // Create a session, and add additional handlers for all service
 | 
					// Deprecated: Use NewSession functions to create sessions instead. NewSession
 | 
				
			||||||
//     // clients created with the session to inherit. Adds logging handler.
 | 
					// has the same functionality as New except an error can be returned when the
 | 
				
			||||||
//     sess := session.New()
 | 
					// func is called instead of waiting to receive an error until a request is made.
 | 
				
			||||||
//     sess.Handlers.Send.PushFront(func(r *request.Request) {
 | 
					func New(cfgs ...*aws.Config) *Session {
 | 
				
			||||||
//          // Log every request made and its payload
 | 
						// load initial config from environment
 | 
				
			||||||
//          logger.Println("Request: %s/%s, Payload: %s", r.ClientInfo.ServiceName, r.Operation, r.Params)
 | 
						envCfg := loadEnvConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if envCfg.EnableSharedConfig {
 | 
				
			||||||
 | 
							s, err := newSession(envCfg, cfgs...)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								// Old session.New expected all errors to be discovered when
 | 
				
			||||||
 | 
								// a request is made, and would report the errors then. This
 | 
				
			||||||
 | 
								// needs to be replicated if an error occurs while creating
 | 
				
			||||||
 | 
								// the session.
 | 
				
			||||||
 | 
								msg := "failed to create session with AWS_SDK_LOAD_CONFIG enabled. " +
 | 
				
			||||||
 | 
									"Use session.NewSession to handle errors occurring during session creation."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Session creation failed, need to report the error and prevent
 | 
				
			||||||
 | 
								// any requests from succeeding.
 | 
				
			||||||
 | 
								s = &Session{Config: defaults.Config()}
 | 
				
			||||||
 | 
								s.Config.MergeIn(cfgs...)
 | 
				
			||||||
 | 
								s.Config.Logger.Log("ERROR:", msg, "Error:", err)
 | 
				
			||||||
 | 
								s.Handlers.Validate.PushBack(func(r *request.Request) {
 | 
				
			||||||
 | 
									r.Error = err
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return s
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return oldNewSession(cfgs...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewSession returns a new Session created from SDK defaults, config files,
 | 
				
			||||||
 | 
					// environment, and user provided config files. Once the Session is created
 | 
				
			||||||
 | 
					// it can be mutated to modify the Config or Handlers. The Session is safe to
 | 
				
			||||||
 | 
					// be read concurrently, but it should not be written to concurrently.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
 | 
				
			||||||
 | 
					// the shared config file (~/.aws/config) will also be loaded in addition to
 | 
				
			||||||
 | 
					// the shared credentials file (~/.aws/config). Values set in both the
 | 
				
			||||||
 | 
					// shared config, and shared credentials will be taken from the shared
 | 
				
			||||||
 | 
					// credentials file. Enabling the Shared Config will also allow the Session
 | 
				
			||||||
 | 
					// to be built with retrieving credentials with AssumeRole set in the config.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See the NewSessionWithOptions func for information on how to override or
 | 
				
			||||||
 | 
					// control through code how the Session will be created. Such as specifying the
 | 
				
			||||||
 | 
					// config profile, and controlling if shared config is enabled or not.
 | 
				
			||||||
 | 
					func NewSession(cfgs ...*aws.Config) (*Session, error) {
 | 
				
			||||||
 | 
						envCfg := loadEnvConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return newSession(envCfg, cfgs...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SharedConfigState provides the ability to optionally override the state
 | 
				
			||||||
 | 
					// of the session's creation based on the shared config being enabled or
 | 
				
			||||||
 | 
					// disabled.
 | 
				
			||||||
 | 
					type SharedConfigState int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// SharedConfigStateFromEnv does not override any state of the
 | 
				
			||||||
 | 
						// AWS_SDK_LOAD_CONFIG env var. It is the default value of the
 | 
				
			||||||
 | 
						// SharedConfigState type.
 | 
				
			||||||
 | 
						SharedConfigStateFromEnv SharedConfigState = iota
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// SharedConfigDisable overrides the AWS_SDK_LOAD_CONFIG env var value
 | 
				
			||||||
 | 
						// and disables the shared config functionality.
 | 
				
			||||||
 | 
						SharedConfigDisable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// SharedConfigEnable overrides the AWS_SDK_LOAD_CONFIG env var value
 | 
				
			||||||
 | 
						// and enables the shared config functionality.
 | 
				
			||||||
 | 
						SharedConfigEnable
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Options provides the means to control how a Session is created and what
 | 
				
			||||||
 | 
					// configuration values will be loaded.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					type Options struct {
 | 
				
			||||||
 | 
						// Provides config values for the SDK to use when creating service clients
 | 
				
			||||||
 | 
						// and making API requests to services. Any value set in with this field
 | 
				
			||||||
 | 
						// will override the associated value provided by the SDK defaults,
 | 
				
			||||||
 | 
						// environment or config files where relevant.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If not set, configuration values from from SDK defaults, environment,
 | 
				
			||||||
 | 
						// config will be used.
 | 
				
			||||||
 | 
						Config aws.Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Overrides the config profile the Session should be created from. If not
 | 
				
			||||||
 | 
						// set the value of the environment variable will be loaded (AWS_PROFILE,
 | 
				
			||||||
 | 
						// or AWS_DEFAULT_PROFILE if the Shared Config is enabled).
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// If not set and environment variables are not set the "default"
 | 
				
			||||||
 | 
						// (DefaultSharedConfigProfile) will be used as the profile to load the
 | 
				
			||||||
 | 
						// session config from.
 | 
				
			||||||
 | 
						Profile string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Instructs how the Session will be created based on the AWS_SDK_LOAD_CONFIG
 | 
				
			||||||
 | 
						// environment variable. By default a Session will be created using the
 | 
				
			||||||
 | 
						// value provided by the AWS_SDK_LOAD_CONFIG environment variable.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Setting this value to SharedConfigEnable or SharedConfigDisable
 | 
				
			||||||
 | 
						// will allow you to override the AWS_SDK_LOAD_CONFIG environment variable
 | 
				
			||||||
 | 
						// and enable or disable the shared config functionality.
 | 
				
			||||||
 | 
						SharedConfigState SharedConfigState
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewSessionWithOptions returns a new Session created from SDK defaults, config files,
 | 
				
			||||||
 | 
					// environment, and user provided config files. This func uses the Options
 | 
				
			||||||
 | 
					// values to configure how the Session is created.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
 | 
				
			||||||
 | 
					// the shared config file (~/.aws/config) will also be loaded in addition to
 | 
				
			||||||
 | 
					// the shared credentials file (~/.aws/config). Values set in both the
 | 
				
			||||||
 | 
					// shared config, and shared credentials will be taken from the shared
 | 
				
			||||||
 | 
					// credentials file. Enabling the Shared Config will also allow the Session
 | 
				
			||||||
 | 
					// to be built with retrieving credentials with AssumeRole set in the config.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     // Equivalent to session.New
 | 
				
			||||||
 | 
					//     sess, err := session.NewSessionWithOptions(session.Options{})
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     // Specify profile to load for the session's config
 | 
				
			||||||
 | 
					//     sess, err := session.NewSessionWithOptions(session.Options{
 | 
				
			||||||
 | 
					//          Profile: "profile_name",
 | 
				
			||||||
//     })
 | 
					//     })
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//     // Create a S3 client instance from a session
 | 
					//     // Specify profile for config and region for requests
 | 
				
			||||||
//     sess := session.New()
 | 
					//     sess, err := session.NewSessionWithOptions(session.Options{
 | 
				
			||||||
//     svc := s3.New(sess)
 | 
					//          Config: aws.Config{Region: aws.String("us-east-1")},
 | 
				
			||||||
func New(cfgs ...*aws.Config) *Session {
 | 
					//          Profile: "profile_name",
 | 
				
			||||||
 | 
					//     })
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     // Force enable Shared Config support
 | 
				
			||||||
 | 
					//     sess, err := session.NewSessionWithOptions(session.Options{
 | 
				
			||||||
 | 
					//         SharedConfigState: SharedConfigEnable,
 | 
				
			||||||
 | 
					//     })
 | 
				
			||||||
 | 
					func NewSessionWithOptions(opts Options) (*Session, error) {
 | 
				
			||||||
 | 
						var envCfg envConfig
 | 
				
			||||||
 | 
						if opts.SharedConfigState == SharedConfigEnable {
 | 
				
			||||||
 | 
							envCfg = loadSharedEnvConfig()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							envCfg = loadEnvConfig()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(opts.Profile) > 0 {
 | 
				
			||||||
 | 
							envCfg.Profile = opts.Profile
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch opts.SharedConfigState {
 | 
				
			||||||
 | 
						case SharedConfigDisable:
 | 
				
			||||||
 | 
							envCfg.EnableSharedConfig = false
 | 
				
			||||||
 | 
						case SharedConfigEnable:
 | 
				
			||||||
 | 
							envCfg.EnableSharedConfig = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return newSession(envCfg, &opts.Config)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Must is a helper function to ensure the Session is valid and there was no
 | 
				
			||||||
 | 
					// error when calling a NewSession function.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This helper is intended to be used in variable initialization to load the
 | 
				
			||||||
 | 
					// Session and configuration at startup. Such as:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     var sess = session.Must(session.NewSession())
 | 
				
			||||||
 | 
					func Must(sess *Session, err error) *Session {
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sess
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func oldNewSession(cfgs ...*aws.Config) *Session {
 | 
				
			||||||
	cfg := defaults.Config()
 | 
						cfg := defaults.Config()
 | 
				
			||||||
	handlers := defaults.Handlers()
 | 
						handlers := defaults.Handlers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Apply the passed in configs so the configuration can be applied to the
 | 
						// Apply the passed in configs so the configuration can be applied to the
 | 
				
			||||||
	// default credential chain
 | 
						// default credential chain
 | 
				
			||||||
	cfg.MergeIn(cfgs...)
 | 
						cfg.MergeIn(cfgs...)
 | 
				
			||||||
 | 
						if cfg.EndpointResolver == nil {
 | 
				
			||||||
 | 
							// An endpoint resolver is required for a session to be able to provide
 | 
				
			||||||
 | 
							// endpoints for service client configurations.
 | 
				
			||||||
 | 
							cfg.EndpointResolver = endpoints.DefaultResolver()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	cfg.Credentials = defaults.CredChain(cfg, handlers)
 | 
						cfg.Credentials = defaults.CredChain(cfg, handlers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Reapply any passed in configs to override credentials if set
 | 
						// Reapply any passed in configs to override credentials if set
 | 
				
			||||||
| 
						 | 
					@ -72,6 +242,115 @@ func New(cfgs ...*aws.Config) *Session {
 | 
				
			||||||
	return s
 | 
						return s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newSession(envCfg envConfig, cfgs ...*aws.Config) (*Session, error) {
 | 
				
			||||||
 | 
						cfg := defaults.Config()
 | 
				
			||||||
 | 
						handlers := defaults.Handlers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get a merged version of the user provided config to determine if
 | 
				
			||||||
 | 
						// credentials were.
 | 
				
			||||||
 | 
						userCfg := &aws.Config{}
 | 
				
			||||||
 | 
						userCfg.MergeIn(cfgs...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Order config files will be loaded in with later files overwriting
 | 
				
			||||||
 | 
						// previous config file values.
 | 
				
			||||||
 | 
						cfgFiles := []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile}
 | 
				
			||||||
 | 
						if !envCfg.EnableSharedConfig {
 | 
				
			||||||
 | 
							// The shared config file (~/.aws/config) is only loaded if instructed
 | 
				
			||||||
 | 
							// to load via the envConfig.EnableSharedConfig (AWS_SDK_LOAD_CONFIG).
 | 
				
			||||||
 | 
							cfgFiles = cfgFiles[1:]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Load additional config from file(s)
 | 
				
			||||||
 | 
						sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s := &Session{
 | 
				
			||||||
 | 
							Config:   cfg,
 | 
				
			||||||
 | 
							Handlers: handlers,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initHandlers(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return s, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mergeConfigSrcs(cfg, userCfg *aws.Config, envCfg envConfig, sharedCfg sharedConfig, handlers request.Handlers) {
 | 
				
			||||||
 | 
						// Merge in user provided configuration
 | 
				
			||||||
 | 
						cfg.MergeIn(userCfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Region if not already set by user
 | 
				
			||||||
 | 
						if len(aws.StringValue(cfg.Region)) == 0 {
 | 
				
			||||||
 | 
							if len(envCfg.Region) > 0 {
 | 
				
			||||||
 | 
								cfg.WithRegion(envCfg.Region)
 | 
				
			||||||
 | 
							} else if envCfg.EnableSharedConfig && len(sharedCfg.Region) > 0 {
 | 
				
			||||||
 | 
								cfg.WithRegion(sharedCfg.Region)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Configure credentials if not already set
 | 
				
			||||||
 | 
						if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil {
 | 
				
			||||||
 | 
							if len(envCfg.Creds.AccessKeyID) > 0 {
 | 
				
			||||||
 | 
								cfg.Credentials = credentials.NewStaticCredentialsFromCreds(
 | 
				
			||||||
 | 
									envCfg.Creds,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							} else if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.RoleARN) > 0 && sharedCfg.AssumeRoleSource != nil {
 | 
				
			||||||
 | 
								cfgCp := *cfg
 | 
				
			||||||
 | 
								cfgCp.Credentials = credentials.NewStaticCredentialsFromCreds(
 | 
				
			||||||
 | 
									sharedCfg.AssumeRoleSource.Creds,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
								cfg.Credentials = stscreds.NewCredentials(
 | 
				
			||||||
 | 
									&Session{
 | 
				
			||||||
 | 
										Config:   &cfgCp,
 | 
				
			||||||
 | 
										Handlers: handlers.Copy(),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									sharedCfg.AssumeRole.RoleARN,
 | 
				
			||||||
 | 
									func(opt *stscreds.AssumeRoleProvider) {
 | 
				
			||||||
 | 
										opt.RoleSessionName = sharedCfg.AssumeRole.RoleSessionName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if len(sharedCfg.AssumeRole.ExternalID) > 0 {
 | 
				
			||||||
 | 
											opt.ExternalID = aws.String(sharedCfg.AssumeRole.ExternalID)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// MFA not supported
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							} else if len(sharedCfg.Creds.AccessKeyID) > 0 {
 | 
				
			||||||
 | 
								cfg.Credentials = credentials.NewStaticCredentialsFromCreds(
 | 
				
			||||||
 | 
									sharedCfg.Creds,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// Fallback to default credentials provider, include mock errors
 | 
				
			||||||
 | 
								// for the credential chain so user can identify why credentials
 | 
				
			||||||
 | 
								// failed to be retrieved.
 | 
				
			||||||
 | 
								cfg.Credentials = credentials.NewCredentials(&credentials.ChainProvider{
 | 
				
			||||||
 | 
									VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
 | 
				
			||||||
 | 
									Providers: []credentials.Provider{
 | 
				
			||||||
 | 
										&credProviderError{Err: awserr.New("EnvAccessKeyNotFound", "failed to find credentials in the environment.", nil)},
 | 
				
			||||||
 | 
										&credProviderError{Err: awserr.New("SharedCredsLoad", fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil)},
 | 
				
			||||||
 | 
										defaults.RemoteCredProvider(*cfg, handlers),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type credProviderError struct {
 | 
				
			||||||
 | 
						Err error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var emptyCreds = credentials.Value{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c credProviderError) Retrieve() (credentials.Value, error) {
 | 
				
			||||||
 | 
						return credentials.Value{}, c.Err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (c credProviderError) IsExpired() bool {
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func initHandlers(s *Session) {
 | 
					func initHandlers(s *Session) {
 | 
				
			||||||
	// Add the Validate parameter handler if it is not disabled.
 | 
						// Add the Validate parameter handler if it is not disabled.
 | 
				
			||||||
	s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler)
 | 
						s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler)
 | 
				
			||||||
| 
						 | 
					@ -80,12 +359,11 @@ func initHandlers(s *Session) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Copy creates and returns a copy of the current session, coping the config
 | 
					// Copy creates and returns a copy of the current Session, coping the config
 | 
				
			||||||
// and handlers. If any additional configs are provided they will be merged
 | 
					// and handlers. If any additional configs are provided they will be merged
 | 
				
			||||||
// on top of the session's copied config.
 | 
					// on top of the Session's copied config.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Example:
 | 
					//     // Create a copy of the current Session, configured for the us-west-2 region.
 | 
				
			||||||
//     // Create a copy of the current session, configured for the us-west-2 region.
 | 
					 | 
				
			||||||
//     sess.Copy(&aws.Config{Region: aws.String("us-west-2")})
 | 
					//     sess.Copy(&aws.Config{Region: aws.String("us-west-2")})
 | 
				
			||||||
func (s *Session) Copy(cfgs ...*aws.Config) *Session {
 | 
					func (s *Session) Copy(cfgs ...*aws.Config) *Session {
 | 
				
			||||||
	newSession := &Session{
 | 
						newSession := &Session{
 | 
				
			||||||
| 
						 | 
					@ -101,20 +379,40 @@ func (s *Session) Copy(cfgs ...*aws.Config) *Session {
 | 
				
			||||||
// ClientConfig satisfies the client.ConfigProvider interface and is used to
 | 
					// ClientConfig satisfies the client.ConfigProvider interface and is used to
 | 
				
			||||||
// configure the service client instances. Passing the Session to the service
 | 
					// configure the service client instances. Passing the Session to the service
 | 
				
			||||||
// client's constructor (New) will use this method to configure the client.
 | 
					// client's constructor (New) will use this method to configure the client.
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Example:
 | 
					 | 
				
			||||||
//     sess := session.New()
 | 
					 | 
				
			||||||
//     s3.New(sess)
 | 
					 | 
				
			||||||
func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config {
 | 
					func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config {
 | 
				
			||||||
 | 
						// Backwards compatibility, the error will be eaten if user calls ClientConfig
 | 
				
			||||||
 | 
						// directly. All SDK services will use ClientconfigWithError.
 | 
				
			||||||
 | 
						cfg, _ := s.clientConfigWithErr(serviceName, cfgs...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cfg
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (client.Config, error) {
 | 
				
			||||||
	s = s.Copy(cfgs...)
 | 
						s = s.Copy(cfgs...)
 | 
				
			||||||
	endpoint, signingRegion := endpoints.NormalizeEndpoint(
 | 
					
 | 
				
			||||||
		aws.StringValue(s.Config.Endpoint), serviceName,
 | 
						var resolved endpoints.ResolvedEndpoint
 | 
				
			||||||
		aws.StringValue(s.Config.Region), aws.BoolValue(s.Config.DisableSSL))
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						region := aws.StringValue(s.Config.Region)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if endpoint := aws.StringValue(s.Config.Endpoint); len(endpoint) != 0 {
 | 
				
			||||||
 | 
							resolved.URL = endpoints.AddScheme(endpoint, aws.BoolValue(s.Config.DisableSSL))
 | 
				
			||||||
 | 
							resolved.SigningRegion = region
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							resolved, err = s.Config.EndpointResolver.EndpointFor(
 | 
				
			||||||
 | 
								serviceName, region,
 | 
				
			||||||
 | 
								func(opt *endpoints.Options) {
 | 
				
			||||||
 | 
									opt.DisableSSL = aws.BoolValue(s.Config.DisableSSL)
 | 
				
			||||||
 | 
									opt.UseDualStack = aws.BoolValue(s.Config.UseDualStack)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return client.Config{
 | 
						return client.Config{
 | 
				
			||||||
		Config:        s.Config,
 | 
							Config:        s.Config,
 | 
				
			||||||
		Handlers:      s.Handlers,
 | 
							Handlers:      s.Handlers,
 | 
				
			||||||
		Endpoint:      endpoint,
 | 
							Endpoint:      resolved.URL,
 | 
				
			||||||
		SigningRegion: signingRegion,
 | 
							SigningRegion: resolved.SigningRegion,
 | 
				
			||||||
	}
 | 
							SigningName:   resolved.SigningName,
 | 
				
			||||||
 | 
						}, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,295 @@
 | 
				
			||||||
 | 
					package session
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/credentials"
 | 
				
			||||||
 | 
						"github.com/go-ini/ini"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// Static Credentials group
 | 
				
			||||||
 | 
						accessKeyIDKey  = `aws_access_key_id`     // group required
 | 
				
			||||||
 | 
						secretAccessKey = `aws_secret_access_key` // group required
 | 
				
			||||||
 | 
						sessionTokenKey = `aws_session_token`     // optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assume Role Credentials group
 | 
				
			||||||
 | 
						roleArnKey         = `role_arn`          // group required
 | 
				
			||||||
 | 
						sourceProfileKey   = `source_profile`    // group required
 | 
				
			||||||
 | 
						externalIDKey      = `external_id`       // optional
 | 
				
			||||||
 | 
						mfaSerialKey       = `mfa_serial`        // optional
 | 
				
			||||||
 | 
						roleSessionNameKey = `role_session_name` // optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Additional Config fields
 | 
				
			||||||
 | 
						regionKey = `region`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DefaultSharedConfigProfile is the default profile to be used when
 | 
				
			||||||
 | 
						// loading configuration from the config files if another profile name
 | 
				
			||||||
 | 
						// is not provided.
 | 
				
			||||||
 | 
						DefaultSharedConfigProfile = `default`
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type assumeRoleConfig struct {
 | 
				
			||||||
 | 
						RoleARN         string
 | 
				
			||||||
 | 
						SourceProfile   string
 | 
				
			||||||
 | 
						ExternalID      string
 | 
				
			||||||
 | 
						MFASerial       string
 | 
				
			||||||
 | 
						RoleSessionName string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// sharedConfig represents the configuration fields of the SDK config files.
 | 
				
			||||||
 | 
					type sharedConfig struct {
 | 
				
			||||||
 | 
						// Credentials values from the config file. Both aws_access_key_id
 | 
				
			||||||
 | 
						// and aws_secret_access_key must be provided together in the same file
 | 
				
			||||||
 | 
						// to be considered valid. The values will be ignored if not a complete group.
 | 
				
			||||||
 | 
						// aws_session_token is an optional field that can be provided if both of the
 | 
				
			||||||
 | 
						// other two fields are also provided.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	aws_access_key_id
 | 
				
			||||||
 | 
						//	aws_secret_access_key
 | 
				
			||||||
 | 
						//	aws_session_token
 | 
				
			||||||
 | 
						Creds credentials.Value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AssumeRole       assumeRoleConfig
 | 
				
			||||||
 | 
						AssumeRoleSource *sharedConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Region is the region the SDK should use for looking up AWS service endpoints
 | 
				
			||||||
 | 
						// and signing requests.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//	region
 | 
				
			||||||
 | 
						Region string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type sharedConfigFile struct {
 | 
				
			||||||
 | 
						Filename string
 | 
				
			||||||
 | 
						IniData  *ini.File
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// loadSharedConfig retrieves the configuration from the list of files
 | 
				
			||||||
 | 
					// using the profile provided. The order the files are listed will determine
 | 
				
			||||||
 | 
					// precedence. Values in subsequent files will overwrite values defined in
 | 
				
			||||||
 | 
					// earlier files.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// For example, given two files A and B. Both define credentials. If the order
 | 
				
			||||||
 | 
					// of the files are A then B, B's credential values will be used instead of A's.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// See sharedConfig.setFromFile for information how the config files
 | 
				
			||||||
 | 
					// will be loaded.
 | 
				
			||||||
 | 
					func loadSharedConfig(profile string, filenames []string) (sharedConfig, error) {
 | 
				
			||||||
 | 
						if len(profile) == 0 {
 | 
				
			||||||
 | 
							profile = DefaultSharedConfigProfile
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						files, err := loadSharedConfigIniFiles(filenames)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return sharedConfig{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg := sharedConfig{}
 | 
				
			||||||
 | 
						if err = cfg.setFromIniFiles(profile, files); err != nil {
 | 
				
			||||||
 | 
							return sharedConfig{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(cfg.AssumeRole.SourceProfile) > 0 {
 | 
				
			||||||
 | 
							if err := cfg.setAssumeRoleSource(profile, files); err != nil {
 | 
				
			||||||
 | 
								return sharedConfig{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cfg, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
 | 
				
			||||||
 | 
						files := make([]sharedConfigFile, 0, len(filenames))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, filename := range filenames {
 | 
				
			||||||
 | 
							b, err := ioutil.ReadFile(filename)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								// Skip files which can't be opened and read for whatever reason
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							f, err := ini.Load(b)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, SharedConfigLoadError{Filename: filename}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							files = append(files, sharedConfigFile{
 | 
				
			||||||
 | 
								Filename: filename, IniData: f,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return files, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cfg *sharedConfig) setAssumeRoleSource(origProfile string, files []sharedConfigFile) error {
 | 
				
			||||||
 | 
						var assumeRoleSrc sharedConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Multiple level assume role chains are not support
 | 
				
			||||||
 | 
						if cfg.AssumeRole.SourceProfile == origProfile {
 | 
				
			||||||
 | 
							assumeRoleSrc = *cfg
 | 
				
			||||||
 | 
							assumeRoleSrc.AssumeRole = assumeRoleConfig{}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err := assumeRoleSrc.setFromIniFiles(cfg.AssumeRole.SourceProfile, files)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(assumeRoleSrc.Creds.AccessKeyID) == 0 {
 | 
				
			||||||
 | 
							return SharedConfigAssumeRoleError{RoleARN: cfg.AssumeRole.RoleARN}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg.AssumeRoleSource = &assumeRoleSrc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cfg *sharedConfig) setFromIniFiles(profile string, files []sharedConfigFile) error {
 | 
				
			||||||
 | 
						// Trim files from the list that don't exist.
 | 
				
			||||||
 | 
						for _, f := range files {
 | 
				
			||||||
 | 
							if err := cfg.setFromIniFile(profile, f); err != nil {
 | 
				
			||||||
 | 
								if _, ok := err.(SharedConfigProfileNotExistsError); ok {
 | 
				
			||||||
 | 
									// Ignore proviles missings
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// setFromFile loads the configuration from the file using
 | 
				
			||||||
 | 
					// the profile provided. A sharedConfig pointer type value is used so that
 | 
				
			||||||
 | 
					// multiple config file loadings can be chained.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Only loads complete logically grouped values, and will not set fields in cfg
 | 
				
			||||||
 | 
					// for incomplete grouped values in the config. Such as credentials. For example
 | 
				
			||||||
 | 
					// if a config file only includes aws_access_key_id but no aws_secret_access_key
 | 
				
			||||||
 | 
					// the aws_access_key_id will be ignored.
 | 
				
			||||||
 | 
					func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) error {
 | 
				
			||||||
 | 
						section, err := file.IniData.GetSection(profile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// Fallback to to alternate profile name: profile <name>
 | 
				
			||||||
 | 
							section, err = file.IniData.GetSection(fmt.Sprintf("profile %s", profile))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return SharedConfigProfileNotExistsError{Profile: profile, Err: err}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shared Credentials
 | 
				
			||||||
 | 
						akid := section.Key(accessKeyIDKey).String()
 | 
				
			||||||
 | 
						secret := section.Key(secretAccessKey).String()
 | 
				
			||||||
 | 
						if len(akid) > 0 && len(secret) > 0 {
 | 
				
			||||||
 | 
							cfg.Creds = credentials.Value{
 | 
				
			||||||
 | 
								AccessKeyID:     akid,
 | 
				
			||||||
 | 
								SecretAccessKey: secret,
 | 
				
			||||||
 | 
								SessionToken:    section.Key(sessionTokenKey).String(),
 | 
				
			||||||
 | 
								ProviderName:    fmt.Sprintf("SharedConfigCredentials: %s", file.Filename),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assume Role
 | 
				
			||||||
 | 
						roleArn := section.Key(roleArnKey).String()
 | 
				
			||||||
 | 
						srcProfile := section.Key(sourceProfileKey).String()
 | 
				
			||||||
 | 
						if len(roleArn) > 0 && len(srcProfile) > 0 {
 | 
				
			||||||
 | 
							cfg.AssumeRole = assumeRoleConfig{
 | 
				
			||||||
 | 
								RoleARN:         roleArn,
 | 
				
			||||||
 | 
								SourceProfile:   srcProfile,
 | 
				
			||||||
 | 
								ExternalID:      section.Key(externalIDKey).String(),
 | 
				
			||||||
 | 
								MFASerial:       section.Key(mfaSerialKey).String(),
 | 
				
			||||||
 | 
								RoleSessionName: section.Key(roleSessionNameKey).String(),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Region
 | 
				
			||||||
 | 
						if v := section.Key(regionKey).String(); len(v) > 0 {
 | 
				
			||||||
 | 
							cfg.Region = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SharedConfigLoadError is an error for the shared config file failed to load.
 | 
				
			||||||
 | 
					type SharedConfigLoadError struct {
 | 
				
			||||||
 | 
						Filename string
 | 
				
			||||||
 | 
						Err      error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code is the short id of the error.
 | 
				
			||||||
 | 
					func (e SharedConfigLoadError) Code() string {
 | 
				
			||||||
 | 
						return "SharedConfigLoadError"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Message is the description of the error
 | 
				
			||||||
 | 
					func (e SharedConfigLoadError) Message() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("failed to load config file, %s", e.Filename)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OrigErr is the underlying error that caused the failure.
 | 
				
			||||||
 | 
					func (e SharedConfigLoadError) OrigErr() error {
 | 
				
			||||||
 | 
						return e.Err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Error satisfies the error interface.
 | 
				
			||||||
 | 
					func (e SharedConfigLoadError) Error() string {
 | 
				
			||||||
 | 
						return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SharedConfigProfileNotExistsError is an error for the shared config when
 | 
				
			||||||
 | 
					// the profile was not find in the config file.
 | 
				
			||||||
 | 
					type SharedConfigProfileNotExistsError struct {
 | 
				
			||||||
 | 
						Profile string
 | 
				
			||||||
 | 
						Err     error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code is the short id of the error.
 | 
				
			||||||
 | 
					func (e SharedConfigProfileNotExistsError) Code() string {
 | 
				
			||||||
 | 
						return "SharedConfigProfileNotExistsError"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Message is the description of the error
 | 
				
			||||||
 | 
					func (e SharedConfigProfileNotExistsError) Message() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("failed to get profile, %s", e.Profile)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OrigErr is the underlying error that caused the failure.
 | 
				
			||||||
 | 
					func (e SharedConfigProfileNotExistsError) OrigErr() error {
 | 
				
			||||||
 | 
						return e.Err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Error satisfies the error interface.
 | 
				
			||||||
 | 
					func (e SharedConfigProfileNotExistsError) Error() string {
 | 
				
			||||||
 | 
						return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SharedConfigAssumeRoleError is an error for the shared config when the
 | 
				
			||||||
 | 
					// profile contains assume role information, but that information is invalid
 | 
				
			||||||
 | 
					// or not complete.
 | 
				
			||||||
 | 
					type SharedConfigAssumeRoleError struct {
 | 
				
			||||||
 | 
						RoleARN string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Code is the short id of the error.
 | 
				
			||||||
 | 
					func (e SharedConfigAssumeRoleError) Code() string {
 | 
				
			||||||
 | 
						return "SharedConfigAssumeRoleError"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Message is the description of the error
 | 
				
			||||||
 | 
					func (e SharedConfigAssumeRoleError) Message() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("failed to load assume role for %s, source profile has no shared credentials",
 | 
				
			||||||
 | 
							e.RoleARN)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OrigErr is the underlying error that caused the failure.
 | 
				
			||||||
 | 
					func (e SharedConfigAssumeRoleError) OrigErr() error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Error satisfies the error interface.
 | 
				
			||||||
 | 
					func (e SharedConfigAssumeRoleError) Error() string {
 | 
				
			||||||
 | 
						return awserr.SprintError(e.Code(), e.Message(), "", nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					// +build go1.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package v4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getURIPath(u *url.URL) string {
 | 
				
			||||||
 | 
						var uri string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(u.Opaque) > 0 {
 | 
				
			||||||
 | 
							uri = "/" + strings.Join(strings.Split(u.Opaque, "/")[3:], "/")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							uri = u.EscapedPath()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(uri) == 0 {
 | 
				
			||||||
 | 
							uri = "/"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return uri
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,56 @@
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Provides request signing for request that need to be signed with
 | 
					// Provides request signing for request that need to be signed with
 | 
				
			||||||
// AWS V4 Signatures.
 | 
					// AWS V4 Signatures.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Standalone Signer
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Generally using the signer outside of the SDK should not require any additional
 | 
				
			||||||
 | 
					// logic when using Go v1.5 or higher. The signer does this by taking advantage
 | 
				
			||||||
 | 
					// of the URL.EscapedPath method. If your request URI requires additional escaping
 | 
				
			||||||
 | 
					// you many need to use the URL.Opaque to define what the raw URI should be sent
 | 
				
			||||||
 | 
					// to the service as.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The signer will first check the URL.Opaque field, and use its value if set.
 | 
				
			||||||
 | 
					// The signer does require the URL.Opaque field to be set in the form of:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     "//<hostname>/<path>"
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     // e.g.
 | 
				
			||||||
 | 
					//     "//example.com/some/path"
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The leading "//" and hostname are required or the URL.Opaque escaping will
 | 
				
			||||||
 | 
					// not work correctly.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If URL.Opaque is not set the signer will fallback to the URL.EscapedPath()
 | 
				
			||||||
 | 
					// method and using the returned value. If you're using Go v1.4 you must set
 | 
				
			||||||
 | 
					// URL.Opaque if the URI path needs escaping. If URL.Opaque is not set with
 | 
				
			||||||
 | 
					// Go v1.5 the signer will fallback to URL.Path.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// AWS v4 signature validation requires that the canonical string's URI path
 | 
				
			||||||
 | 
					// element must be the URI escaped form of the HTTP request's path.
 | 
				
			||||||
 | 
					// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The Go HTTP client will perform escaping automatically on the request. Some
 | 
				
			||||||
 | 
					// of these escaping may cause signature validation errors because the HTTP
 | 
				
			||||||
 | 
					// request differs from the URI path or query that the signature was generated.
 | 
				
			||||||
 | 
					// https://golang.org/pkg/net/url/#URL.EscapedPath
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Because of this, it is recommended that when using the signer outside of the
 | 
				
			||||||
 | 
					// SDK that explicitly escaping the request prior to being signed is preferable,
 | 
				
			||||||
 | 
					// and will help prevent signature validation errors. This can be done by setting
 | 
				
			||||||
 | 
					// the URL.Opaque or URL.RawPath. The SDK will use URL.Opaque first and then
 | 
				
			||||||
 | 
					// call URL.EscapedPath() if Opaque is not set.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If signing a request intended for HTTP2 server, and you're using Go 1.6.2
 | 
				
			||||||
 | 
					// through 1.7.4 you should use the URL.RawPath as the pre-escaped form of the
 | 
				
			||||||
 | 
					// request URL. https://github.com/golang/go/issues/16847 points to a bug in
 | 
				
			||||||
 | 
					// Go pre 1.8 that failes to make HTTP2 requests using absolute URL in the HTTP
 | 
				
			||||||
 | 
					// message. URL.Opaque generally will force Go to make requests with absolute URL.
 | 
				
			||||||
 | 
					// URL.RawPath does not do this, but RawPath must be a valid escaping of Path
 | 
				
			||||||
 | 
					// or url.EscapedPath will ignore the RawPath escaping.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Test `TestStandaloneSign` provides a complete example of using the signer
 | 
				
			||||||
 | 
					// outside of the SDK and pre-escaping the URI path.
 | 
				
			||||||
package v4
 | 
					package v4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
| 
						 | 
					@ -11,6 +61,7 @@ import (
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
| 
						 | 
					@ -38,6 +89,7 @@ var ignoredHeaders = rules{
 | 
				
			||||||
		mapRule{
 | 
							mapRule{
 | 
				
			||||||
			"Authorization":   struct{}{},
 | 
								"Authorization":   struct{}{},
 | 
				
			||||||
			"User-Agent":      struct{}{},
 | 
								"User-Agent":      struct{}{},
 | 
				
			||||||
 | 
								"X-Amzn-Trace-Id": struct{}{},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -119,6 +171,25 @@ type Signer struct {
 | 
				
			||||||
	// request's query string.
 | 
						// request's query string.
 | 
				
			||||||
	DisableHeaderHoisting bool
 | 
						DisableHeaderHoisting bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Disables the automatic escaping of the URI path of the request for the
 | 
				
			||||||
 | 
						// siganture's canonical string's path. For services that do not need additional
 | 
				
			||||||
 | 
						// escaping then use this to disable the signer escaping the path.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// S3 is an example of a service that does not need additional escaping.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
 | 
				
			||||||
 | 
						DisableURIPathEscaping bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Disales the automatical setting of the HTTP request's Body field with the
 | 
				
			||||||
 | 
						// io.ReadSeeker passed in to the signer. This is useful if you're using a
 | 
				
			||||||
 | 
						// custom wrapper around the body for the io.ReadSeeker and want to preserve
 | 
				
			||||||
 | 
						// the Body value on the Request.Body.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// This does run the risk of signing a request with a body that will not be
 | 
				
			||||||
 | 
						// sent in the request. Need to ensure that the underlying data of the Body
 | 
				
			||||||
 | 
						// values are the same.
 | 
				
			||||||
 | 
						DisableRequestBodyOverwrite bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// currentTimeFn returns the time value which represents the current time.
 | 
						// currentTimeFn returns the time value which represents the current time.
 | 
				
			||||||
	// This value should only be used for testing. If it is nil the default
 | 
						// This value should only be used for testing. If it is nil the default
 | 
				
			||||||
	// time.Now will be used.
 | 
						// time.Now will be used.
 | 
				
			||||||
| 
						 | 
					@ -150,6 +221,8 @@ type signingCtx struct {
 | 
				
			||||||
	ExpireTime       time.Duration
 | 
						ExpireTime       time.Duration
 | 
				
			||||||
	SignedHeaderVals http.Header
 | 
						SignedHeaderVals http.Header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DisableURIPathEscaping bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	credValues         credentials.Value
 | 
						credValues         credentials.Value
 | 
				
			||||||
	isPresign          bool
 | 
						isPresign          bool
 | 
				
			||||||
	formattedTime      string
 | 
						formattedTime      string
 | 
				
			||||||
| 
						 | 
					@ -175,6 +248,12 @@ type signingCtx struct {
 | 
				
			||||||
// is not needed as the full request context will be captured by the http.Request
 | 
					// is not needed as the full request context will be captured by the http.Request
 | 
				
			||||||
// value. It is included for reference though.
 | 
					// value. It is included for reference though.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					// Sign will set the request's Body to be the `body` parameter passed in. If
 | 
				
			||||||
 | 
					// the body is not already an io.ReadCloser, it will be wrapped within one. If
 | 
				
			||||||
 | 
					// a `nil` body parameter passed to Sign, the request's Body field will be
 | 
				
			||||||
 | 
					// also set to nil. Its important to note that this functionality will not
 | 
				
			||||||
 | 
					// change the request's ContentLength of the request.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
// Sign differs from Presign in that it will sign the request using HTTP
 | 
					// Sign differs from Presign in that it will sign the request using HTTP
 | 
				
			||||||
// header values. This type of signing is intended for http.Request values that
 | 
					// header values. This type of signing is intended for http.Request values that
 | 
				
			||||||
// will not be shared, or are shared in a way the header values on the request
 | 
					// will not be shared, or are shared in a way the header values on the request
 | 
				
			||||||
| 
						 | 
					@ -237,14 +316,14 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
 | 
				
			||||||
		isPresign:              exp != 0,
 | 
							isPresign:              exp != 0,
 | 
				
			||||||
		ServiceName:            service,
 | 
							ServiceName:            service,
 | 
				
			||||||
		Region:                 region,
 | 
							Region:                 region,
 | 
				
			||||||
 | 
							DisableURIPathEscaping: v4.DisableURIPathEscaping,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for key := range ctx.Query {
 | 
				
			||||||
 | 
							sort.Strings(ctx.Query[key])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.isRequestSigned() {
 | 
						if ctx.isRequestSigned() {
 | 
				
			||||||
		if !v4.Credentials.IsExpired() && currentTimeFn().Before(ctx.Time.Add(10*time.Minute)) {
 | 
					 | 
				
			||||||
			// If the request is already signed, and the credentials have not
 | 
					 | 
				
			||||||
			// expired, and the request is not too old ignore the signing request.
 | 
					 | 
				
			||||||
			return ctx.SignedHeaderVals, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ctx.Time = currentTimeFn()
 | 
							ctx.Time = currentTimeFn()
 | 
				
			||||||
		ctx.handlePresignRemoval()
 | 
							ctx.handlePresignRemoval()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -258,6 +337,20 @@ func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, regi
 | 
				
			||||||
	ctx.assignAmzQueryValues()
 | 
						ctx.assignAmzQueryValues()
 | 
				
			||||||
	ctx.build(v4.DisableHeaderHoisting)
 | 
						ctx.build(v4.DisableHeaderHoisting)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If the request is not presigned the body should be attached to it. This
 | 
				
			||||||
 | 
						// prevents the confusion of wanting to send a signed request without
 | 
				
			||||||
 | 
						// the body the request was signed for attached.
 | 
				
			||||||
 | 
						if !(v4.DisableRequestBodyOverwrite || ctx.isPresign) {
 | 
				
			||||||
 | 
							var reader io.ReadCloser
 | 
				
			||||||
 | 
							if body != nil {
 | 
				
			||||||
 | 
								var ok bool
 | 
				
			||||||
 | 
								if reader, ok = body.(io.ReadCloser); !ok {
 | 
				
			||||||
 | 
									reader = ioutil.NopCloser(body)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							r.Body = reader
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if v4.Debug.Matches(aws.LogDebugWithSigning) {
 | 
						if v4.Debug.Matches(aws.LogDebugWithSigning) {
 | 
				
			||||||
		v4.logSigningInfo(ctx)
 | 
							v4.logSigningInfo(ctx)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -338,6 +431,14 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
 | 
				
			||||||
		v4.Logger = req.Config.Logger
 | 
							v4.Logger = req.Config.Logger
 | 
				
			||||||
		v4.DisableHeaderHoisting = req.NotHoist
 | 
							v4.DisableHeaderHoisting = req.NotHoist
 | 
				
			||||||
		v4.currentTimeFn = curTimeFn
 | 
							v4.currentTimeFn = curTimeFn
 | 
				
			||||||
 | 
							if name == "s3" {
 | 
				
			||||||
 | 
								// S3 service should not have any escaping applied
 | 
				
			||||||
 | 
								v4.DisableURIPathEscaping = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Prevents setting the HTTPRequest's Body. Since the Body could be
 | 
				
			||||||
 | 
							// wrapped in a custom io.Closer that we do not want to be stompped
 | 
				
			||||||
 | 
							// on top of by the signer.
 | 
				
			||||||
 | 
							v4.DisableRequestBodyOverwrite = true
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	signingTime := req.Time
 | 
						signingTime := req.Time
 | 
				
			||||||
| 
						 | 
					@ -345,7 +446,9 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
 | 
				
			||||||
		signingTime = req.LastSignedAt
 | 
							signingTime = req.LastSignedAt
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.Body, name, region, req.ExpireTime, signingTime)
 | 
						signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(),
 | 
				
			||||||
 | 
							name, region, req.ExpireTime, signingTime,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		req.Error = err
 | 
							req.Error = err
 | 
				
			||||||
		req.SignedHeaderVals = nil
 | 
							req.SignedHeaderVals = nil
 | 
				
			||||||
| 
						 | 
					@ -356,7 +459,7 @@ func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time
 | 
				
			||||||
	req.LastSignedAt = curTimeFn()
 | 
						req.LastSignedAt = curTimeFn()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const logSignInfoMsg = `DEBUG: Request Signiture:
 | 
					const logSignInfoMsg = `DEBUG: Request Signature:
 | 
				
			||||||
---[ CANONICAL STRING  ]-----------------------------
 | 
					---[ CANONICAL STRING  ]-----------------------------
 | 
				
			||||||
%s
 | 
					%s
 | 
				
			||||||
---[ STRING TO SIGN ]--------------------------------
 | 
					---[ STRING TO SIGN ]--------------------------------
 | 
				
			||||||
| 
						 | 
					@ -492,17 +595,10 @@ func (ctx *signingCtx) buildCanonicalHeaders(r rule, header http.Header) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (ctx *signingCtx) buildCanonicalString() {
 | 
					func (ctx *signingCtx) buildCanonicalString() {
 | 
				
			||||||
	ctx.Request.URL.RawQuery = strings.Replace(ctx.Query.Encode(), "+", "%20", -1)
 | 
						ctx.Request.URL.RawQuery = strings.Replace(ctx.Query.Encode(), "+", "%20", -1)
 | 
				
			||||||
	uri := ctx.Request.URL.Opaque
 | 
					 | 
				
			||||||
	if uri != "" {
 | 
					 | 
				
			||||||
		uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/")
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		uri = ctx.Request.URL.Path
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if uri == "" {
 | 
					 | 
				
			||||||
		uri = "/"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.ServiceName != "s3" {
 | 
						uri := getURIPath(ctx.Request.URL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !ctx.DisableURIPathEscaping {
 | 
				
			||||||
		uri = rest.EscapePath(uri, false)
 | 
							uri = rest.EscapePath(uri, false)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -545,7 +641,7 @@ func (ctx *signingCtx) buildBodyDigest() {
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			hash = hex.EncodeToString(makeSha256Reader(ctx.Body))
 | 
								hash = hex.EncodeToString(makeSha256Reader(ctx.Body))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if ctx.ServiceName == "s3" {
 | 
							if ctx.ServiceName == "s3" || ctx.ServiceName == "glacier" {
 | 
				
			||||||
			ctx.Request.Header.Set("X-Amz-Content-Sha256", hash)
 | 
								ctx.Request.Header.Set("X-Amz-Content-Sha256", hash)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,13 @@ import (
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser
 | 
					// ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser. Should
 | 
				
			||||||
 | 
					// only be used with an io.Reader that is also an io.Seeker. Doing so may
 | 
				
			||||||
 | 
					// cause request signature errors, or request body's not sent for GET, HEAD
 | 
				
			||||||
 | 
					// and DELETE HTTP methods.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Deprecated: Should only be used with io.ReadSeeker. If using for
 | 
				
			||||||
 | 
					// S3 PutObject to stream content use s3manager.Uploader instead.
 | 
				
			||||||
func ReadSeekCloser(r io.Reader) ReaderSeekerCloser {
 | 
					func ReadSeekCloser(r io.Reader) ReaderSeekerCloser {
 | 
				
			||||||
	return ReaderSeekerCloser{r}
 | 
						return ReaderSeekerCloser{r}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -44,6 +50,12 @@ func (r ReaderSeekerCloser) Seek(offset int64, whence int) (int64, error) {
 | 
				
			||||||
	return int64(0), nil
 | 
						return int64(0), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsSeeker returns if the underlying reader is also a seeker.
 | 
				
			||||||
 | 
					func (r ReaderSeekerCloser) IsSeeker() bool {
 | 
				
			||||||
 | 
						_, ok := r.r.(io.Seeker)
 | 
				
			||||||
 | 
						return ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Close closes the ReaderSeekerCloser.
 | 
					// Close closes the ReaderSeekerCloser.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// If the ReaderSeekerCloser is not an io.Closer nothing will be done.
 | 
					// If the ReaderSeekerCloser is not an io.Closer nothing will be done.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,4 +5,4 @@ package aws
 | 
				
			||||||
const SDKName = "aws-sdk-go"
 | 
					const SDKName = "aws-sdk-go"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SDKVersion is the version of this SDK
 | 
					// SDKVersion is the version of this SDK
 | 
				
			||||||
const SDKVersion = "1.2.4"
 | 
					const SDKVersion = "1.6.9"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,65 +0,0 @@
 | 
				
			||||||
// Package endpoints validates regional endpoints for services.
 | 
					 | 
				
			||||||
package endpoints
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go
 | 
					 | 
				
			||||||
//go:generate gofmt -s -w endpoints_map.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NormalizeEndpoint takes and endpoint and service API information to return a
 | 
					 | 
				
			||||||
// normalized endpoint and signing region.  If the endpoint is not an empty string
 | 
					 | 
				
			||||||
// the service name and region will be used to look up the service's API endpoint.
 | 
					 | 
				
			||||||
// If the endpoint is provided the scheme will be added if it is not present.
 | 
					 | 
				
			||||||
func NormalizeEndpoint(endpoint, serviceName, region string, disableSSL bool) (normEndpoint, signingRegion string) {
 | 
					 | 
				
			||||||
	if endpoint == "" {
 | 
					 | 
				
			||||||
		return EndpointForRegion(serviceName, region, disableSSL)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return AddScheme(endpoint, disableSSL), ""
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// EndpointForRegion returns an endpoint and its signing region for a service and region.
 | 
					 | 
				
			||||||
// if the service and region pair are not found endpoint and signingRegion will be empty.
 | 
					 | 
				
			||||||
func EndpointForRegion(svcName, region string, disableSSL bool) (endpoint, signingRegion string) {
 | 
					 | 
				
			||||||
	derivedKeys := []string{
 | 
					 | 
				
			||||||
		region + "/" + svcName,
 | 
					 | 
				
			||||||
		region + "/*",
 | 
					 | 
				
			||||||
		"*/" + svcName,
 | 
					 | 
				
			||||||
		"*/*",
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, key := range derivedKeys {
 | 
					 | 
				
			||||||
		if val, ok := endpointsMap.Endpoints[key]; ok {
 | 
					 | 
				
			||||||
			ep := val.Endpoint
 | 
					 | 
				
			||||||
			ep = strings.Replace(ep, "{region}", region, -1)
 | 
					 | 
				
			||||||
			ep = strings.Replace(ep, "{service}", svcName, -1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			endpoint = ep
 | 
					 | 
				
			||||||
			signingRegion = val.SigningRegion
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return AddScheme(endpoint, disableSSL), signingRegion
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Regular expression to determine if the endpoint string is prefixed with a scheme.
 | 
					 | 
				
			||||||
var schemeRE = regexp.MustCompile("^([^:]+)://")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// AddScheme adds the HTTP or HTTPS schemes to a endpoint URL if there is no
 | 
					 | 
				
			||||||
// scheme. If disableSSL is true HTTP will be added instead of the default HTTPS.
 | 
					 | 
				
			||||||
func AddScheme(endpoint string, disableSSL bool) string {
 | 
					 | 
				
			||||||
	if endpoint != "" && !schemeRE.MatchString(endpoint) {
 | 
					 | 
				
			||||||
		scheme := "https"
 | 
					 | 
				
			||||||
		if disableSSL {
 | 
					 | 
				
			||||||
			scheme = "http"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		endpoint = fmt.Sprintf("%s://%s", scheme, endpoint)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return endpoint
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,88 +0,0 @@
 | 
				
			||||||
package endpoints
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type endpointStruct struct {
 | 
					 | 
				
			||||||
	Version   int
 | 
					 | 
				
			||||||
	Endpoints map[string]endpointEntry
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type endpointEntry struct {
 | 
					 | 
				
			||||||
	Endpoint      string
 | 
					 | 
				
			||||||
	SigningRegion string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var endpointsMap = endpointStruct{
 | 
					 | 
				
			||||||
	Version: 2,
 | 
					 | 
				
			||||||
	Endpoints: map[string]endpointEntry{
 | 
					 | 
				
			||||||
		"*/*": {
 | 
					 | 
				
			||||||
			Endpoint: "{service}.{region}.amazonaws.com",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/cloudfront": {
 | 
					 | 
				
			||||||
			Endpoint:      "cloudfront.amazonaws.com",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/cloudsearchdomain": {
 | 
					 | 
				
			||||||
			Endpoint:      "",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/data.iot": {
 | 
					 | 
				
			||||||
			Endpoint:      "",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/ec2metadata": {
 | 
					 | 
				
			||||||
			Endpoint: "http://169.254.169.254/latest",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/iam": {
 | 
					 | 
				
			||||||
			Endpoint:      "iam.amazonaws.com",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/importexport": {
 | 
					 | 
				
			||||||
			Endpoint:      "importexport.amazonaws.com",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/route53": {
 | 
					 | 
				
			||||||
			Endpoint:      "route53.amazonaws.com",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/s3": {
 | 
					 | 
				
			||||||
			Endpoint: "s3-{region}.amazonaws.com",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/sts": {
 | 
					 | 
				
			||||||
			Endpoint:      "sts.amazonaws.com",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"*/waf": {
 | 
					 | 
				
			||||||
			Endpoint:      "waf.amazonaws.com",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"cn-north-1/*": {
 | 
					 | 
				
			||||||
			Endpoint: "{service}.{region}.amazonaws.com.cn",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"cn-north-1/ec2metadata": {
 | 
					 | 
				
			||||||
			Endpoint: "http://169.254.169.254/latest",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"eu-central-1/s3": {
 | 
					 | 
				
			||||||
			Endpoint: "{service}.{region}.amazonaws.com",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"us-east-1/s3": {
 | 
					 | 
				
			||||||
			Endpoint: "s3.amazonaws.com",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"us-east-1/sdb": {
 | 
					 | 
				
			||||||
			Endpoint:      "sdb.amazonaws.com",
 | 
					 | 
				
			||||||
			SigningRegion: "us-east-1",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"us-gov-west-1/ec2metadata": {
 | 
					 | 
				
			||||||
			Endpoint: "http://169.254.169.254/latest",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"us-gov-west-1/iam": {
 | 
					 | 
				
			||||||
			Endpoint: "iam.us-gov.amazonaws.com",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"us-gov-west-1/s3": {
 | 
					 | 
				
			||||||
			Endpoint: "s3-{region}.amazonaws.com",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		"us-gov-west-1/sts": {
 | 
					 | 
				
			||||||
			Endpoint: "sts.us-gov-west-1.amazonaws.com",
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
// Package query provides serialisation of AWS query requests, and responses.
 | 
					// Package query provides serialization of AWS query requests, and responses.
 | 
				
			||||||
package query
 | 
					package query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/query.json build_test.go
 | 
					//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/query.json build_test.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,6 +76,10 @@ func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix stri
 | 
				
			||||||
		if field.PkgPath != "" {
 | 
							if field.PkgPath != "" {
 | 
				
			||||||
			continue // ignore unexported fields
 | 
								continue // ignore unexported fields
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if field.Tag.Get("ignore") != "" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if protocol.CanSetIdempotencyToken(value.Field(i), field) {
 | 
							if protocol.CanSetIdempotencyToken(value.Field(i), field) {
 | 
				
			||||||
			token := protocol.GetIdempotencyToken()
 | 
								token := protocol.GetIdempotencyToken()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
package query
 | 
					package query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/query.json unmarshal_test.go
 | 
					//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/query.json unmarshal_test.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/xml"
 | 
						"encoding/xml"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ import (
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/awserr"
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/request"
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -46,14 +47,29 @@ var BuildHandler = request.NamedHandler{Name: "awssdk.rest.Build", Fn: Build}
 | 
				
			||||||
func Build(r *request.Request) {
 | 
					func Build(r *request.Request) {
 | 
				
			||||||
	if r.ParamsFilled() {
 | 
						if r.ParamsFilled() {
 | 
				
			||||||
		v := reflect.ValueOf(r.Params).Elem()
 | 
							v := reflect.ValueOf(r.Params).Elem()
 | 
				
			||||||
		buildLocationElements(r, v)
 | 
							buildLocationElements(r, v, false)
 | 
				
			||||||
		buildBody(r, v)
 | 
							buildBody(r, v)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func buildLocationElements(r *request.Request, v reflect.Value) {
 | 
					// BuildAsGET builds the REST component of a service request with the ability to hoist
 | 
				
			||||||
 | 
					// data from the body.
 | 
				
			||||||
 | 
					func BuildAsGET(r *request.Request) {
 | 
				
			||||||
 | 
						if r.ParamsFilled() {
 | 
				
			||||||
 | 
							v := reflect.ValueOf(r.Params).Elem()
 | 
				
			||||||
 | 
							buildLocationElements(r, v, true)
 | 
				
			||||||
 | 
							buildBody(r, v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func buildLocationElements(r *request.Request, v reflect.Value, buildGETQuery bool) {
 | 
				
			||||||
	query := r.HTTPRequest.URL.Query()
 | 
						query := r.HTTPRequest.URL.Query()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup the raw path to match the base path pattern. This is needed
 | 
				
			||||||
 | 
						// so that when the path is mutated a custom escaped version can be
 | 
				
			||||||
 | 
						// stored in RawPath that will be used by the Go client.
 | 
				
			||||||
 | 
						r.HTTPRequest.URL.RawPath = r.HTTPRequest.URL.Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < v.NumField(); i++ {
 | 
						for i := 0; i < v.NumField(); i++ {
 | 
				
			||||||
		m := v.Field(i)
 | 
							m := v.Field(i)
 | 
				
			||||||
		if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) {
 | 
							if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) {
 | 
				
			||||||
| 
						 | 
					@ -72,6 +88,9 @@ func buildLocationElements(r *request.Request, v reflect.Value) {
 | 
				
			||||||
			if !m.IsValid() {
 | 
								if !m.IsValid() {
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if field.Tag.Get("ignore") != "" {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var err error
 | 
								var err error
 | 
				
			||||||
			switch field.Tag.Get("location") {
 | 
								switch field.Tag.Get("location") {
 | 
				
			||||||
| 
						 | 
					@ -83,6 +102,10 @@ func buildLocationElements(r *request.Request, v reflect.Value) {
 | 
				
			||||||
				err = buildURI(r.HTTPRequest.URL, m, name)
 | 
									err = buildURI(r.HTTPRequest.URL, m, name)
 | 
				
			||||||
			case "querystring":
 | 
								case "querystring":
 | 
				
			||||||
				err = buildQueryString(query, m, name)
 | 
									err = buildQueryString(query, m, name)
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									if buildGETQuery {
 | 
				
			||||||
 | 
										err = buildQueryString(query, m, name)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			r.Error = err
 | 
								r.Error = err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -92,7 +115,9 @@ func buildLocationElements(r *request.Request, v reflect.Value) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r.HTTPRequest.URL.RawQuery = query.Encode()
 | 
						r.HTTPRequest.URL.RawQuery = query.Encode()
 | 
				
			||||||
	updatePath(r.HTTPRequest.URL, r.HTTPRequest.URL.Path)
 | 
						if !aws.BoolValue(r.Config.DisableRestProtocolURICleaning) {
 | 
				
			||||||
 | 
							cleanPath(r.HTTPRequest.URL)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func buildBody(r *request.Request, v reflect.Value) {
 | 
					func buildBody(r *request.Request, v reflect.Value) {
 | 
				
			||||||
| 
						 | 
					@ -156,10 +181,11 @@ func buildURI(u *url.URL, v reflect.Value, name string) error {
 | 
				
			||||||
		return awserr.New("SerializationError", "failed to encode REST request", err)
 | 
							return awserr.New("SerializationError", "failed to encode REST request", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uri := u.Path
 | 
						u.Path = strings.Replace(u.Path, "{"+name+"}", value, -1)
 | 
				
			||||||
	uri = strings.Replace(uri, "{"+name+"}", EscapePath(value, true), -1)
 | 
						u.Path = strings.Replace(u.Path, "{"+name+"+}", value, -1)
 | 
				
			||||||
	uri = strings.Replace(uri, "{"+name+"+}", EscapePath(value, false), -1)
 | 
					
 | 
				
			||||||
	u.Path = uri
 | 
						u.RawPath = strings.Replace(u.RawPath, "{"+name+"}", EscapePath(value, true), -1)
 | 
				
			||||||
 | 
						u.RawPath = strings.Replace(u.RawPath, "{"+name+"+}", EscapePath(value, false), -1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -193,25 +219,17 @@ func buildQueryString(query url.Values, v reflect.Value, name string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func updatePath(url *url.URL, urlPath string) {
 | 
					func cleanPath(u *url.URL) {
 | 
				
			||||||
	scheme, query := url.Scheme, url.RawQuery
 | 
						hasSlash := strings.HasSuffix(u.Path, "/")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hasSlash := strings.HasSuffix(urlPath, "/")
 | 
						// clean up path, removing duplicate `/`
 | 
				
			||||||
 | 
						u.Path = path.Clean(u.Path)
 | 
				
			||||||
 | 
						u.RawPath = path.Clean(u.RawPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// clean up path
 | 
						if hasSlash && !strings.HasSuffix(u.Path, "/") {
 | 
				
			||||||
	urlPath = path.Clean(urlPath)
 | 
							u.Path += "/"
 | 
				
			||||||
	if hasSlash && !strings.HasSuffix(urlPath, "/") {
 | 
							u.RawPath += "/"
 | 
				
			||||||
		urlPath += "/"
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get formatted URL minus scheme so we can build this into Opaque
 | 
					 | 
				
			||||||
	url.Scheme, url.Path, url.RawQuery = "", "", ""
 | 
					 | 
				
			||||||
	s := url.String()
 | 
					 | 
				
			||||||
	url.Scheme = scheme
 | 
					 | 
				
			||||||
	url.RawQuery = query
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// build opaque URI
 | 
					 | 
				
			||||||
	url.Opaque = s + urlPath
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EscapePath escapes part of a URL path in Amazon style
 | 
					// EscapePath escapes part of a URL path in Amazon style
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
package rest
 | 
					package rest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
	"encoding/base64"
 | 
						"encoding/base64"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
| 
						 | 
					@ -11,7 +12,6 @@ import (
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws"
 | 
					 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/awserr"
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/request"
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -70,10 +70,16 @@ func unmarshalBody(r *request.Request, v reflect.Value) {
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					default:
 | 
										default:
 | 
				
			||||||
						switch payload.Type().String() {
 | 
											switch payload.Type().String() {
 | 
				
			||||||
						case "io.ReadSeeker":
 | 
											case "io.ReadCloser":
 | 
				
			||||||
							payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body)))
 | 
					 | 
				
			||||||
						case "aws.ReadSeekCloser", "io.ReadCloser":
 | 
					 | 
				
			||||||
							payload.Set(reflect.ValueOf(r.HTTPResponse.Body))
 | 
												payload.Set(reflect.ValueOf(r.HTTPResponse.Body))
 | 
				
			||||||
 | 
											case "io.ReadSeeker":
 | 
				
			||||||
 | 
												b, err := ioutil.ReadAll(r.HTTPResponse.Body)
 | 
				
			||||||
 | 
												if err != nil {
 | 
				
			||||||
 | 
													r.Error = awserr.New("SerializationError",
 | 
				
			||||||
 | 
														"failed to read response body", err)
 | 
				
			||||||
 | 
													return
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												payload.Set(reflect.ValueOf(ioutil.NopCloser(bytes.NewReader(b))))
 | 
				
			||||||
						default:
 | 
											default:
 | 
				
			||||||
							io.Copy(ioutil.Discard, r.HTTPResponse.Body)
 | 
												io.Copy(ioutil.Discard, r.HTTPResponse.Body)
 | 
				
			||||||
							defer r.HTTPResponse.Body.Close()
 | 
												defer r.HTTPResponse.Body.Close()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,9 @@
 | 
				
			||||||
// Package restxml provides RESTful XML serialisation of AWS
 | 
					// Package restxml provides RESTful XML serialization of AWS
 | 
				
			||||||
// requests and responses.
 | 
					// requests and responses.
 | 
				
			||||||
package restxml
 | 
					package restxml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/rest-xml.json build_test.go
 | 
					//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/rest-xml.json build_test.go
 | 
				
			||||||
//go:generate go run ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/rest-xml.json unmarshal_test.go
 | 
					//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/rest-xml.json unmarshal_test.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
// Package xmlutil provides XML serialisation of AWS requests and responses.
 | 
					// Package xmlutil provides XML serialization of AWS requests and responses.
 | 
				
			||||||
package xmlutil
 | 
					package xmlutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
| 
						 | 
					@ -127,6 +127,10 @@ func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag refl
 | 
				
			||||||
		if field.PkgPath != "" {
 | 
							if field.PkgPath != "" {
 | 
				
			||||||
			continue // ignore unexported fields
 | 
								continue // ignore unexported fields
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if field.Tag.Get("ignore") != "" {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mTag := field.Tag
 | 
							mTag := field.Tag
 | 
				
			||||||
		if mTag.Get("location") != "" { // skip non-body members
 | 
							if mTag.Get("location") != "" { // skip non-body members
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,11 +111,8 @@ func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
 | 
				
			||||||
		elems := node.Children[name]
 | 
							elems := node.Children[name]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if elems == nil { // try to find the field in attributes
 | 
							if elems == nil { // try to find the field in attributes
 | 
				
			||||||
			for _, a := range node.Attr {
 | 
								if val, ok := node.findElem(name); ok {
 | 
				
			||||||
				if name == a.Name.Local {
 | 
									elems = []*XMLNode{{Text: val}}
 | 
				
			||||||
					// turn this into a text node for de-serializing
 | 
					 | 
				
			||||||
					elems = []*XMLNode{{Text: a.Value}}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
								
								
									generated
								
								
									vendored
								
								
							
							
						
						
									
										37
									
								
								vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
								
								
									generated
								
								
									vendored
								
								
							| 
						 | 
					@ -2,6 +2,7 @@ package xmlutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/xml"
 | 
						"encoding/xml"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -12,6 +13,9 @@ type XMLNode struct {
 | 
				
			||||||
	Children map[string][]*XMLNode `json:",omitempty"`
 | 
						Children map[string][]*XMLNode `json:",omitempty"`
 | 
				
			||||||
	Text     string                `json:",omitempty"`
 | 
						Text     string                `json:",omitempty"`
 | 
				
			||||||
	Attr     []xml.Attr            `json:",omitempty"`
 | 
						Attr     []xml.Attr            `json:",omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						namespaces map[string]string
 | 
				
			||||||
 | 
						parent     *XMLNode
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
 | 
					// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
 | 
				
			||||||
| 
						 | 
					@ -59,21 +63,54 @@ func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
 | 
				
			||||||
				slice = []*XMLNode{}
 | 
									slice = []*XMLNode{}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			node, e := XMLToStruct(d, &el)
 | 
								node, e := XMLToStruct(d, &el)
 | 
				
			||||||
 | 
								out.findNamespaces()
 | 
				
			||||||
			if e != nil {
 | 
								if e != nil {
 | 
				
			||||||
				return out, e
 | 
									return out, e
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			node.Name = typed.Name
 | 
								node.Name = typed.Name
 | 
				
			||||||
 | 
								node.findNamespaces()
 | 
				
			||||||
 | 
								tempOut := *out
 | 
				
			||||||
 | 
								// Save into a temp variable, simply because out gets squashed during
 | 
				
			||||||
 | 
								// loop iterations
 | 
				
			||||||
 | 
								node.parent = &tempOut
 | 
				
			||||||
			slice = append(slice, node)
 | 
								slice = append(slice, node)
 | 
				
			||||||
			out.Children[name] = slice
 | 
								out.Children[name] = slice
 | 
				
			||||||
		case xml.EndElement:
 | 
							case xml.EndElement:
 | 
				
			||||||
			if s != nil && s.Name.Local == typed.Name.Local { // matching end token
 | 
								if s != nil && s.Name.Local == typed.Name.Local { // matching end token
 | 
				
			||||||
				return out, nil
 | 
									return out, nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								out = &XMLNode{}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return out, nil
 | 
						return out, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (n *XMLNode) findNamespaces() {
 | 
				
			||||||
 | 
						ns := map[string]string{}
 | 
				
			||||||
 | 
						for _, a := range n.Attr {
 | 
				
			||||||
 | 
							if a.Name.Space == "xmlns" {
 | 
				
			||||||
 | 
								ns[a.Value] = a.Name.Local
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n.namespaces = ns
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (n *XMLNode) findElem(name string) (string, bool) {
 | 
				
			||||||
 | 
						for node := n; node != nil; node = node.parent {
 | 
				
			||||||
 | 
							for _, a := range node.Attr {
 | 
				
			||||||
 | 
								namespace := a.Name.Space
 | 
				
			||||||
 | 
								if v, ok := node.namespaces[namespace]; ok {
 | 
				
			||||||
 | 
									namespace = v
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if name == fmt.Sprintf("%s:%s", namespace, a.Name.Local) {
 | 
				
			||||||
 | 
									return a.Value, true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StructToXML writes an XMLNode to a xml.Encoder as tokens.
 | 
					// StructToXML writes an XMLNode to a xml.Encoder as tokens.
 | 
				
			||||||
func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
 | 
					func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
 | 
				
			||||||
	e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})
 | 
						e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ const (
 | 
				
			||||||
	CookieKeyIDName = "CloudFront-Key-Pair-Id"
 | 
						CookieKeyIDName = "CloudFront-Key-Pair-Id"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A CookieOptions optional additonal options that can be applied to the signed
 | 
					// A CookieOptions optional additional options that can be applied to the signed
 | 
				
			||||||
// cookies.
 | 
					// cookies.
 | 
				
			||||||
type CookieOptions struct {
 | 
					type CookieOptions struct {
 | 
				
			||||||
	Path   string
 | 
						Path   string
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -67,6 +67,10 @@ func updateEndpointForHostStyle(r *request.Request) {
 | 
				
			||||||
	moveBucketToHost(r.HTTPRequest.URL, bucket)
 | 
						moveBucketToHost(r.HTTPRequest.URL, bucket)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						accelElem = []byte("s3-accelerate.dualstack.")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func updateEndpointForAccelerate(r *request.Request) {
 | 
					func updateEndpointForAccelerate(r *request.Request) {
 | 
				
			||||||
	bucket, ok := bucketNameFromReqParams(r.Params)
 | 
						bucket, ok := bucketNameFromReqParams(r.Params)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
| 
						 | 
					@ -78,13 +82,31 @@ func updateEndpointForAccelerate(r *request.Request) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !hostCompatibleBucketName(r.HTTPRequest.URL, bucket) {
 | 
						if !hostCompatibleBucketName(r.HTTPRequest.URL, bucket) {
 | 
				
			||||||
		r.Error = awserr.New("InvalidParameterException",
 | 
							r.Error = awserr.New("InvalidParameterException",
 | 
				
			||||||
			fmt.Sprintf("bucket name %s is not compatibile with S3 Accelerate", bucket),
 | 
								fmt.Sprintf("bucket name %s is not compatible with S3 Accelerate", bucket),
 | 
				
			||||||
			nil)
 | 
								nil)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Change endpoint from s3(-[a-z0-1-])?.amazonaws.com to s3-accelerate.amazonaws.com
 | 
						parts := strings.Split(r.HTTPRequest.URL.Host, ".")
 | 
				
			||||||
	r.HTTPRequest.URL.Host = replaceHostRegion(r.HTTPRequest.URL.Host, "accelerate")
 | 
						if len(parts) < 3 {
 | 
				
			||||||
 | 
							r.Error = awserr.New("InvalidParameterExecption",
 | 
				
			||||||
 | 
								fmt.Sprintf("unable to update endpoint host for S3 accelerate, hostname invalid, %s",
 | 
				
			||||||
 | 
									r.HTTPRequest.URL.Host), nil)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if parts[0] == "s3" || strings.HasPrefix(parts[0], "s3-") {
 | 
				
			||||||
 | 
							parts[0] = "s3-accelerate"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := 1; i+1 < len(parts); i++ {
 | 
				
			||||||
 | 
							if parts[i] == aws.StringValue(r.Config.Region) {
 | 
				
			||||||
 | 
								parts = append(parts[:i], parts[i+1:]...)
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r.HTTPRequest.URL.Host = strings.Join(parts, ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	moveBucketToHost(r.HTTPRequest.URL, bucket)
 | 
						moveBucketToHost(r.HTTPRequest.URL, bucket)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -138,28 +160,3 @@ func moveBucketToHost(u *url.URL, bucket string) {
 | 
				
			||||||
		u.Path = "/"
 | 
							u.Path = "/"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
const s3HostPrefix = "s3"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// replaceHostRegion replaces the S3 region string in the host with the
 | 
					 | 
				
			||||||
// value provided. If v is empty the host prefix returned will be s3.
 | 
					 | 
				
			||||||
func replaceHostRegion(host, v string) string {
 | 
					 | 
				
			||||||
	if !strings.HasPrefix(host, s3HostPrefix) {
 | 
					 | 
				
			||||||
		return host
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	suffix := host[len(s3HostPrefix):]
 | 
					 | 
				
			||||||
	for i := len(s3HostPrefix); i < len(host); i++ {
 | 
					 | 
				
			||||||
		if host[i] == '.' {
 | 
					 | 
				
			||||||
			// Trim until '.' leave the it in place.
 | 
					 | 
				
			||||||
			suffix = host[i:]
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if len(v) == 0 {
 | 
					 | 
				
			||||||
		return fmt.Sprintf("s3%s", suffix)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return fmt.Sprintf("s3-%s%s", v, suffix)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ import (
 | 
				
			||||||
// S3 is a client for Amazon S3.
 | 
					// S3 is a client for Amazon S3.
 | 
				
			||||||
// The service client's operations are safe to be used concurrently.
 | 
					// The service client's operations are safe to be used concurrently.
 | 
				
			||||||
// It is not safe to mutate any of the client's properties though.
 | 
					// It is not safe to mutate any of the client's properties though.
 | 
				
			||||||
 | 
					// Please also see https://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01
 | 
				
			||||||
type S3 struct {
 | 
					type S3 struct {
 | 
				
			||||||
	*client.Client
 | 
						*client.Client
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -24,8 +25,11 @@ var initClient func(*client.Client)
 | 
				
			||||||
// Used for custom request initialization logic
 | 
					// Used for custom request initialization logic
 | 
				
			||||||
var initRequest func(*request.Request)
 | 
					var initRequest func(*request.Request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A ServiceName is the name of the service the client will make API calls to.
 | 
					// Service information constants
 | 
				
			||||||
const ServiceName = "s3"
 | 
					const (
 | 
				
			||||||
 | 
						ServiceName = "s3"        // Service endpoint prefix API calls made to.
 | 
				
			||||||
 | 
						EndpointsID = ServiceName // Service ID for Regions and Endpoints metadata.
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New creates a new instance of the S3 client with a session.
 | 
					// New creates a new instance of the S3 client with a session.
 | 
				
			||||||
// If additional configuration is needed for the client instance use the optional
 | 
					// If additional configuration is needed for the client instance use the optional
 | 
				
			||||||
| 
						 | 
					@ -38,17 +42,18 @@ const ServiceName = "s3"
 | 
				
			||||||
//     // Create a S3 client with additional configuration
 | 
					//     // Create a S3 client with additional configuration
 | 
				
			||||||
//     svc := s3.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
 | 
					//     svc := s3.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
 | 
				
			||||||
func New(p client.ConfigProvider, cfgs ...*aws.Config) *S3 {
 | 
					func New(p client.ConfigProvider, cfgs ...*aws.Config) *S3 {
 | 
				
			||||||
	c := p.ClientConfig(ServiceName, cfgs...)
 | 
						c := p.ClientConfig(EndpointsID, cfgs...)
 | 
				
			||||||
	return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
 | 
						return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// newClient creates, initializes and returns a new service client instance.
 | 
					// newClient creates, initializes and returns a new service client instance.
 | 
				
			||||||
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *S3 {
 | 
					func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *S3 {
 | 
				
			||||||
	svc := &S3{
 | 
						svc := &S3{
 | 
				
			||||||
		Client: client.New(
 | 
							Client: client.New(
 | 
				
			||||||
			cfg,
 | 
								cfg,
 | 
				
			||||||
			metadata.ClientInfo{
 | 
								metadata.ClientInfo{
 | 
				
			||||||
				ServiceName:   ServiceName,
 | 
									ServiceName:   ServiceName,
 | 
				
			||||||
 | 
									SigningName:   signingName,
 | 
				
			||||||
				SigningRegion: signingRegion,
 | 
									SigningRegion: signingRegion,
 | 
				
			||||||
				Endpoint:      endpoint,
 | 
									Endpoint:      endpoint,
 | 
				
			||||||
				APIVersion:    "2006-03-01",
 | 
									APIVersion:    "2006-03-01",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,6 @@ import (
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws"
 | 
					 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/awserr"
 | 
						"github.com/aws/aws-sdk-go/aws/awserr"
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/aws/request"
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -17,8 +16,8 @@ func copyMultipartStatusOKUnmarhsalError(r *request.Request) {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	body := bytes.NewReader(b)
 | 
						body := bytes.NewReader(b)
 | 
				
			||||||
	r.HTTPResponse.Body = aws.ReadSeekCloser(body)
 | 
						r.HTTPResponse.Body = ioutil.NopCloser(body)
 | 
				
			||||||
	defer r.HTTPResponse.Body.(aws.ReaderSeekerCloser).Seek(0, 0)
 | 
						defer body.Seek(0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if body.Len() == 0 {
 | 
						if body.Len() == 0 {
 | 
				
			||||||
		// If there is no body don't attempt to parse the body.
 | 
							// If there is no body don't attempt to parse the body.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,8 @@ func unmarshalError(r *request.Request) {
 | 
				
			||||||
	defer r.HTTPResponse.Body.Close()
 | 
						defer r.HTTPResponse.Body.Close()
 | 
				
			||||||
	defer io.Copy(ioutil.Discard, r.HTTPResponse.Body)
 | 
						defer io.Copy(ioutil.Discard, r.HTTPResponse.Body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Bucket exists in a different region, and request needs
 | 
				
			||||||
 | 
						// to be made to the correct region.
 | 
				
			||||||
	if r.HTTPResponse.StatusCode == http.StatusMovedPermanently {
 | 
						if r.HTTPResponse.StatusCode == http.StatusMovedPermanently {
 | 
				
			||||||
		r.Error = awserr.NewRequestFailure(
 | 
							r.Error = awserr.NewRequestFailure(
 | 
				
			||||||
			awserr.New("BucketRegionError",
 | 
								awserr.New("BucketRegionError",
 | 
				
			||||||
| 
						 | 
					@ -35,25 +37,29 @@ func unmarshalError(r *request.Request) {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r.HTTPResponse.ContentLength == 0 {
 | 
						var errCode, errMsg string
 | 
				
			||||||
		// No body, use status code to generate an awserr.Error
 | 
					 | 
				
			||||||
		r.Error = awserr.NewRequestFailure(
 | 
					 | 
				
			||||||
			awserr.New(strings.Replace(r.HTTPResponse.Status, " ", "", -1), r.HTTPResponse.Status, nil),
 | 
					 | 
				
			||||||
			r.HTTPResponse.StatusCode,
 | 
					 | 
				
			||||||
			r.RequestID,
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Attempt to parse error from body if it is known
 | 
				
			||||||
	resp := &xmlErrorResponse{}
 | 
						resp := &xmlErrorResponse{}
 | 
				
			||||||
	err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp)
 | 
						err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp)
 | 
				
			||||||
	if err != nil && err != io.EOF {
 | 
						if err != nil && err != io.EOF {
 | 
				
			||||||
		r.Error = awserr.New("SerializationError", "failed to decode S3 XML error response", nil)
 | 
							errCode = "SerializationError"
 | 
				
			||||||
 | 
							errMsg = "failed to decode S3 XML error response"
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							errCode = resp.Code
 | 
				
			||||||
 | 
							errMsg = resp.Message
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Fallback to status code converted to message if still no error code
 | 
				
			||||||
 | 
						if len(errCode) == 0 {
 | 
				
			||||||
 | 
							statusText := http.StatusText(r.HTTPResponse.StatusCode)
 | 
				
			||||||
 | 
							errCode = strings.Replace(statusText, " ", "", -1)
 | 
				
			||||||
 | 
							errMsg = statusText
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r.Error = awserr.NewRequestFailure(
 | 
						r.Error = awserr.NewRequestFailure(
 | 
				
			||||||
			awserr.New(resp.Code, resp.Message, nil),
 | 
							awserr.New(errCode, errMsg, nil),
 | 
				
			||||||
		r.HTTPResponse.StatusCode,
 | 
							r.HTTPResponse.StatusCode,
 | 
				
			||||||
		r.RequestID,
 | 
							r.RequestID,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,10 @@ import (
 | 
				
			||||||
	"github.com/aws/aws-sdk-go/private/waiter"
 | 
						"github.com/aws/aws-sdk-go/private/waiter"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WaitUntilBucketExists uses the Amazon S3 API operation
 | 
				
			||||||
 | 
					// HeadBucket to wait for a condition to be met before returning.
 | 
				
			||||||
 | 
					// If the condition is not meet within the max attempt window an error will
 | 
				
			||||||
 | 
					// be returned.
 | 
				
			||||||
func (c *S3) WaitUntilBucketExists(input *HeadBucketInput) error {
 | 
					func (c *S3) WaitUntilBucketExists(input *HeadBucketInput) error {
 | 
				
			||||||
	waiterCfg := waiter.Config{
 | 
						waiterCfg := waiter.Config{
 | 
				
			||||||
		Operation:   "HeadBucket",
 | 
							Operation:   "HeadBucket",
 | 
				
			||||||
| 
						 | 
					@ -47,6 +51,10 @@ func (c *S3) WaitUntilBucketExists(input *HeadBucketInput) error {
 | 
				
			||||||
	return w.Wait()
 | 
						return w.Wait()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WaitUntilBucketNotExists uses the Amazon S3 API operation
 | 
				
			||||||
 | 
					// HeadBucket to wait for a condition to be met before returning.
 | 
				
			||||||
 | 
					// If the condition is not meet within the max attempt window an error will
 | 
				
			||||||
 | 
					// be returned.
 | 
				
			||||||
func (c *S3) WaitUntilBucketNotExists(input *HeadBucketInput) error {
 | 
					func (c *S3) WaitUntilBucketNotExists(input *HeadBucketInput) error {
 | 
				
			||||||
	waiterCfg := waiter.Config{
 | 
						waiterCfg := waiter.Config{
 | 
				
			||||||
		Operation:   "HeadBucket",
 | 
							Operation:   "HeadBucket",
 | 
				
			||||||
| 
						 | 
					@ -70,6 +78,10 @@ func (c *S3) WaitUntilBucketNotExists(input *HeadBucketInput) error {
 | 
				
			||||||
	return w.Wait()
 | 
						return w.Wait()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WaitUntilObjectExists uses the Amazon S3 API operation
 | 
				
			||||||
 | 
					// HeadObject to wait for a condition to be met before returning.
 | 
				
			||||||
 | 
					// If the condition is not meet within the max attempt window an error will
 | 
				
			||||||
 | 
					// be returned.
 | 
				
			||||||
func (c *S3) WaitUntilObjectExists(input *HeadObjectInput) error {
 | 
					func (c *S3) WaitUntilObjectExists(input *HeadObjectInput) error {
 | 
				
			||||||
	waiterCfg := waiter.Config{
 | 
						waiterCfg := waiter.Config{
 | 
				
			||||||
		Operation:   "HeadObject",
 | 
							Operation:   "HeadObject",
 | 
				
			||||||
| 
						 | 
					@ -99,6 +111,10 @@ func (c *S3) WaitUntilObjectExists(input *HeadObjectInput) error {
 | 
				
			||||||
	return w.Wait()
 | 
						return w.Wait()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WaitUntilObjectNotExists uses the Amazon S3 API operation
 | 
				
			||||||
 | 
					// HeadObject to wait for a condition to be met before returning.
 | 
				
			||||||
 | 
					// If the condition is not meet within the max attempt window an error will
 | 
				
			||||||
 | 
					// be returned.
 | 
				
			||||||
func (c *S3) WaitUntilObjectNotExists(input *HeadObjectInput) error {
 | 
					func (c *S3) WaitUntilObjectNotExists(input *HeadObjectInput) error {
 | 
				
			||||||
	waiterCfg := waiter.Config{
 | 
						waiterCfg := waiter.Config{
 | 
				
			||||||
		Operation:   "HeadObject",
 | 
							Operation:   "HeadObject",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					package sts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						initRequest = func(r *request.Request) {
 | 
				
			||||||
 | 
							switch r.Operation.Name {
 | 
				
			||||||
 | 
							case opAssumeRoleWithSAML, opAssumeRoleWithWebIdentity:
 | 
				
			||||||
 | 
								r.Handlers.Sign.Clear() // these operations are unsigned
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,135 @@
 | 
				
			||||||
 | 
					// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package sts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/client"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/client/metadata"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/request"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/aws/signer/v4"
 | 
				
			||||||
 | 
						"github.com/aws/aws-sdk-go/private/protocol/query"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The AWS Security Token Service (STS) is a web service that enables you to
 | 
				
			||||||
 | 
					// request temporary, limited-privilege credentials for AWS Identity and Access
 | 
				
			||||||
 | 
					// Management (IAM) users or for users that you authenticate (federated users).
 | 
				
			||||||
 | 
					// This guide provides descriptions of the STS API. For more detailed information
 | 
				
			||||||
 | 
					// about using this service, go to Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html).
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// As an alternative to using the API, you can use one of the AWS SDKs, which
 | 
				
			||||||
 | 
					// consist of libraries and sample code for various programming languages and
 | 
				
			||||||
 | 
					// platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs provide a convenient
 | 
				
			||||||
 | 
					// way to create programmatic access to STS. For example, the SDKs take care
 | 
				
			||||||
 | 
					// of cryptographically signing requests, managing errors, and retrying requests
 | 
				
			||||||
 | 
					// automatically. For information about the AWS SDKs, including how to download
 | 
				
			||||||
 | 
					// and install them, see the Tools for Amazon Web Services page (http://aws.amazon.com/tools/).
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// For information about setting up signatures and authorization through the
 | 
				
			||||||
 | 
					// API, go to Signing AWS API Requests (http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)
 | 
				
			||||||
 | 
					// in the AWS General Reference. For general information about the Query API,
 | 
				
			||||||
 | 
					// go to Making Query Requests (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html)
 | 
				
			||||||
 | 
					// in Using IAM. For information about using security tokens with other AWS
 | 
				
			||||||
 | 
					// products, go to AWS Services That Work with IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html)
 | 
				
			||||||
 | 
					// in the IAM User Guide.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If you're new to AWS and need additional technical information about a specific
 | 
				
			||||||
 | 
					// AWS product, you can find the product's technical documentation at http://aws.amazon.com/documentation/
 | 
				
			||||||
 | 
					// (http://aws.amazon.com/documentation/).
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Endpoints
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The AWS Security Token Service (STS) has a default endpoint of https://sts.amazonaws.com
 | 
				
			||||||
 | 
					// that maps to the US East (N. Virginia) region. Additional regions are available
 | 
				
			||||||
 | 
					// and are activated by default. For more information, see Activating and Deactivating
 | 
				
			||||||
 | 
					// AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
 | 
				
			||||||
 | 
					// in the IAM User Guide.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// For information about STS endpoints, see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region)
 | 
				
			||||||
 | 
					// in the AWS General Reference.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Recording API requests
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// STS supports AWS CloudTrail, which is a service that records AWS calls for
 | 
				
			||||||
 | 
					// your AWS account and delivers log files to an Amazon S3 bucket. By using
 | 
				
			||||||
 | 
					// information collected by CloudTrail, you can determine what requests were
 | 
				
			||||||
 | 
					// successfully made to STS, who made the request, when it was made, and so
 | 
				
			||||||
 | 
					// on. To learn more about CloudTrail, including how to turn it on and find
 | 
				
			||||||
 | 
					// your log files, see the AWS CloudTrail User Guide (http://docs.aws.amazon.com/awscloudtrail/latest/userguide/what_is_cloud_trail_top_level.html).
 | 
				
			||||||
 | 
					// The service client's operations are safe to be used concurrently.
 | 
				
			||||||
 | 
					// It is not safe to mutate any of the client's properties though.
 | 
				
			||||||
 | 
					// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15
 | 
				
			||||||
 | 
					type STS struct {
 | 
				
			||||||
 | 
						*client.Client
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Used for custom client initialization logic
 | 
				
			||||||
 | 
					var initClient func(*client.Client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Used for custom request initialization logic
 | 
				
			||||||
 | 
					var initRequest func(*request.Request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Service information constants
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ServiceName = "sts"       // Service endpoint prefix API calls made to.
 | 
				
			||||||
 | 
						EndpointsID = ServiceName // Service ID for Regions and Endpoints metadata.
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// New creates a new instance of the STS client with a session.
 | 
				
			||||||
 | 
					// If additional configuration is needed for the client instance use the optional
 | 
				
			||||||
 | 
					// aws.Config parameter to add your extra config.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Example:
 | 
				
			||||||
 | 
					//     // Create a STS client from just a session.
 | 
				
			||||||
 | 
					//     svc := sts.New(mySession)
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     // Create a STS client with additional configuration
 | 
				
			||||||
 | 
					//     svc := sts.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
 | 
				
			||||||
 | 
					func New(p client.ConfigProvider, cfgs ...*aws.Config) *STS {
 | 
				
			||||||
 | 
						c := p.ClientConfig(EndpointsID, cfgs...)
 | 
				
			||||||
 | 
						return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// newClient creates, initializes and returns a new service client instance.
 | 
				
			||||||
 | 
					func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *STS {
 | 
				
			||||||
 | 
						svc := &STS{
 | 
				
			||||||
 | 
							Client: client.New(
 | 
				
			||||||
 | 
								cfg,
 | 
				
			||||||
 | 
								metadata.ClientInfo{
 | 
				
			||||||
 | 
									ServiceName:   ServiceName,
 | 
				
			||||||
 | 
									SigningName:   signingName,
 | 
				
			||||||
 | 
									SigningRegion: signingRegion,
 | 
				
			||||||
 | 
									Endpoint:      endpoint,
 | 
				
			||||||
 | 
									APIVersion:    "2011-06-15",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								handlers,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Handlers
 | 
				
			||||||
 | 
						svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
 | 
				
			||||||
 | 
						svc.Handlers.Build.PushBackNamed(query.BuildHandler)
 | 
				
			||||||
 | 
						svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler)
 | 
				
			||||||
 | 
						svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
 | 
				
			||||||
 | 
						svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run custom client initialization if present
 | 
				
			||||||
 | 
						if initClient != nil {
 | 
				
			||||||
 | 
							initClient(svc.Client)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return svc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// newRequest creates a new request for a STS operation and runs any
 | 
				
			||||||
 | 
					// custom request initialization.
 | 
				
			||||||
 | 
					func (c *STS) newRequest(op *request.Operation, params, data interface{}) *request.Request {
 | 
				
			||||||
 | 
						req := c.NewRequest(op, params, data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run custom request initialization if present
 | 
				
			||||||
 | 
						if initRequest != nil {
 | 
				
			||||||
 | 
							initRequest(req)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return req
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue