mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Merge pull request #1085 from mjibson/elb
Add SD for Amazon EC2 instances
This commit is contained in:
commit
be8b83f48f
|
@ -33,7 +33,7 @@ var (
|
||||||
patJobName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
|
patJobName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
|
||||||
patFileSDName = regexp.MustCompile(`^[^*]*(\*[^/]*)?\.(json|yml|yaml|JSON|YML|YAML)$`)
|
patFileSDName = regexp.MustCompile(`^[^*]*(\*[^/]*)?\.(json|yml|yaml|JSON|YML|YAML)$`)
|
||||||
patRulePath = regexp.MustCompile(`^[^*]*(\*[^/]*)?$`)
|
patRulePath = regexp.MustCompile(`^[^*]*(\*[^/]*)?$`)
|
||||||
patAuthLine = regexp.MustCompile(`((?:username|password|bearer_token):\s+)(".+"|'.+'|[^\s]+)`)
|
patAuthLine = regexp.MustCompile(`((?:username|password|bearer_token|secret_key):\s+)(".+"|'.+'|[^\s]+)`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Load parses the YAML input s into a Config.
|
// Load parses the YAML input s into a Config.
|
||||||
|
@ -128,6 +128,12 @@ var (
|
||||||
RequestTimeout: Duration(10 * time.Second),
|
RequestTimeout: Duration(10 * time.Second),
|
||||||
RetryInterval: Duration(1 * time.Second),
|
RetryInterval: Duration(1 * time.Second),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultEC2SDConfig is the default EC2 SD configuration.
|
||||||
|
DefaultEC2SDConfig = EC2SDConfig{
|
||||||
|
Port: 80,
|
||||||
|
RefreshInterval: Duration(60 * time.Second),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// URL is a custom URL type that allows validation at configuration load time.
|
// URL is a custom URL type that allows validation at configuration load time.
|
||||||
|
@ -351,6 +357,8 @@ type ScrapeConfig struct {
|
||||||
MarathonSDConfigs []*MarathonSDConfig `yaml:"marathon_sd_configs,omitempty"`
|
MarathonSDConfigs []*MarathonSDConfig `yaml:"marathon_sd_configs,omitempty"`
|
||||||
// List of Kubernetes service discovery configurations.
|
// List of Kubernetes service discovery configurations.
|
||||||
KubernetesSDConfigs []*KubernetesSDConfig `yaml:"kubernetes_sd_configs,omitempty"`
|
KubernetesSDConfigs []*KubernetesSDConfig `yaml:"kubernetes_sd_configs,omitempty"`
|
||||||
|
// List of EC2 service discovery configurations.
|
||||||
|
EC2SDConfigs []*EC2SDConfig `yaml:"ec2_sd_configs,omitempty"`
|
||||||
|
|
||||||
// List of target relabel configurations.
|
// List of target relabel configurations.
|
||||||
RelabelConfigs []*RelabelConfig `yaml:"relabel_configs,omitempty"`
|
RelabelConfigs []*RelabelConfig `yaml:"relabel_configs,omitempty"`
|
||||||
|
@ -664,6 +672,31 @@ func (c *KubernetesSDConfig) UnmarshalYAML(unmarshal func(interface{}) error) er
|
||||||
return checkOverflow(c.XXX, "kubernetes_sd_config")
|
return checkOverflow(c.XXX, "kubernetes_sd_config")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EC2SDConfig is the configuration for EC2 based service discovery.
|
||||||
|
type EC2SDConfig struct {
|
||||||
|
Region string `yaml:"region"`
|
||||||
|
AccessKey string `yaml:"access_key,omitempty"`
|
||||||
|
SecretKey string `yaml:"secret_key,omitempty"`
|
||||||
|
RefreshInterval Duration `yaml:"refresh_interval,omitempty"`
|
||||||
|
Port int `yaml:"port"`
|
||||||
|
// Catches all undefined fields and must be empty after parsing.
|
||||||
|
XXX map[string]interface{} `yaml:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||||
|
func (c *EC2SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
*c = DefaultEC2SDConfig
|
||||||
|
type plain EC2SDConfig
|
||||||
|
err := unmarshal((*plain)(c))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.Region == "" {
|
||||||
|
return fmt.Errorf("EC2 SD configuration requires a region")
|
||||||
|
}
|
||||||
|
return checkOverflow(c.XXX, "ec2_sd_config")
|
||||||
|
}
|
||||||
|
|
||||||
// RelabelAction is the action to be performed on relabeling.
|
// RelabelAction is the action to be performed on relabeling.
|
||||||
type RelabelAction string
|
type RelabelAction string
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,25 @@ var expectedConf = &Config{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
JobName: "service-ec2",
|
||||||
|
|
||||||
|
ScrapeInterval: Duration(15 * time.Second),
|
||||||
|
ScrapeTimeout: DefaultGlobalConfig.ScrapeTimeout,
|
||||||
|
|
||||||
|
MetricsPath: DefaultScrapeConfig.MetricsPath,
|
||||||
|
Scheme: DefaultScrapeConfig.Scheme,
|
||||||
|
|
||||||
|
EC2SDConfigs: []*EC2SDConfig{
|
||||||
|
{
|
||||||
|
Region: "us-east-1",
|
||||||
|
AccessKey: "access",
|
||||||
|
SecretKey: "secret",
|
||||||
|
RefreshInterval: Duration(60 * time.Second),
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
original: "",
|
original: "",
|
||||||
}
|
}
|
||||||
|
|
6
config/testdata/conf.good.yml
vendored
6
config/testdata/conf.good.yml
vendored
|
@ -114,3 +114,9 @@ scrape_configs:
|
||||||
marathon_sd_configs:
|
marathon_sd_configs:
|
||||||
- servers:
|
- servers:
|
||||||
- 'http://marathon.example.com:8080'
|
- 'http://marathon.example.com:8080'
|
||||||
|
|
||||||
|
- job_name: service-ec2
|
||||||
|
ec2_sd_configs:
|
||||||
|
- region: us-east-1
|
||||||
|
access_key: access
|
||||||
|
secret_key: secret
|
||||||
|
|
131
retrieval/discovery/ec2.go
Normal file
131
retrieval/discovery/ec2.go
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
// Copyright 2015 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package discovery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/prometheus/common/log"
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/prometheus/prometheus/config"
|
||||||
|
"github.com/prometheus/prometheus/util/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ec2Label = model.MetaLabelPrefix + "ec2_"
|
||||||
|
ec2LabelInstanceID = ec2Label + "instance_id"
|
||||||
|
ec2LabelPublicIP = ec2Label + "public_ip"
|
||||||
|
ec2LabelPrivateIP = ec2Label + "private_ip"
|
||||||
|
ec2LabelTag = ec2Label + "tag_"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EC2Discovery periodically performs EC2-SD requests. It implements
|
||||||
|
// the TargetProvider interface.
|
||||||
|
type EC2Discovery struct {
|
||||||
|
aws *aws.Config
|
||||||
|
done chan struct{}
|
||||||
|
interval time.Duration
|
||||||
|
port int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEC2Discovery returns a new EC2Discovery which periodically refreshes its targets.
|
||||||
|
func NewEC2Discovery(conf *config.EC2SDConfig) *EC2Discovery {
|
||||||
|
creds := credentials.NewStaticCredentials(conf.AccessKey, conf.SecretKey, "")
|
||||||
|
if conf.AccessKey == "" && conf.SecretKey == "" {
|
||||||
|
creds = credentials.NewEnvCredentials()
|
||||||
|
}
|
||||||
|
return &EC2Discovery{
|
||||||
|
aws: &aws.Config{
|
||||||
|
Region: &conf.Region,
|
||||||
|
Credentials: creds,
|
||||||
|
},
|
||||||
|
done: make(chan struct{}),
|
||||||
|
interval: time.Duration(conf.RefreshInterval),
|
||||||
|
port: conf.Port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run implements the TargetProvider interface.
|
||||||
|
func (ed *EC2Discovery) Run(ch chan<- *config.TargetGroup, done <-chan struct{}) {
|
||||||
|
defer close(ch)
|
||||||
|
|
||||||
|
ticker := time.NewTicker(ed.interval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
// Get an initial set right away.
|
||||||
|
tg, err := ed.refresh()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
} else {
|
||||||
|
ch <- tg
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
tg, err := ed.refresh()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
} else {
|
||||||
|
ch <- tg
|
||||||
|
}
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sources implements the TargetProvider interface.
|
||||||
|
func (ed *EC2Discovery) Sources() []string {
|
||||||
|
return []string{*ed.aws.Region}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ed *EC2Discovery) refresh() (*config.TargetGroup, error) {
|
||||||
|
ec2s := ec2.New(ed.aws)
|
||||||
|
tg := &config.TargetGroup{
|
||||||
|
Source: *ed.aws.Region,
|
||||||
|
}
|
||||||
|
if err := ec2s.DescribeInstancesPages(nil, func(p *ec2.DescribeInstancesOutput, lastPage bool) bool {
|
||||||
|
for _, r := range p.Reservations {
|
||||||
|
for _, inst := range r.Instances {
|
||||||
|
if inst.PrivateIpAddress == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
labels := model.LabelSet{
|
||||||
|
ec2LabelInstanceID: model.LabelValue(*inst.InstanceId),
|
||||||
|
}
|
||||||
|
if inst.PublicIpAddress != nil {
|
||||||
|
labels[ec2LabelPublicIP] = model.LabelValue(*inst.PublicIpAddress)
|
||||||
|
}
|
||||||
|
labels[ec2LabelPrivateIP] = model.LabelValue(*inst.PrivateIpAddress)
|
||||||
|
addr := fmt.Sprintf("%s:%d", *inst.PrivateIpAddress, ed.port)
|
||||||
|
labels[model.AddressLabel] = model.LabelValue(addr)
|
||||||
|
for _, t := range inst.Tags {
|
||||||
|
name := strutil.SanitizeLabelName(*t.Key)
|
||||||
|
labels[ec2LabelTag+model.LabelName(name)] = model.LabelValue(*t.Value)
|
||||||
|
}
|
||||||
|
tg.Targets = append(tg.Targets, labels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}); err != nil {
|
||||||
|
return nil, fmt.Errorf("could not describe instances: %s", err)
|
||||||
|
}
|
||||||
|
return tg, nil
|
||||||
|
}
|
|
@ -438,6 +438,9 @@ func providersFromConfig(cfg *config.ScrapeConfig) []TargetProvider {
|
||||||
for i, c := range cfg.ServersetSDConfigs {
|
for i, c := range cfg.ServersetSDConfigs {
|
||||||
app("serverset", i, discovery.NewServersetDiscovery(c))
|
app("serverset", i, discovery.NewServersetDiscovery(c))
|
||||||
}
|
}
|
||||||
|
for i, c := range cfg.EC2SDConfigs {
|
||||||
|
app("ec2", i, discovery.NewEC2Discovery(c))
|
||||||
|
}
|
||||||
if len(cfg.TargetGroups) > 0 {
|
if len(cfg.TargetGroups) > 0 {
|
||||||
app("static", 0, NewStaticProvider(cfg.TargetGroups))
|
app("static", 0, NewStaticProvider(cfg.TargetGroups))
|
||||||
}
|
}
|
||||||
|
|
105
vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go
generated
vendored
Normal file
105
vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// Package awserr represents API error interface accessors for the SDK.
|
||||||
|
package awserr
|
||||||
|
|
||||||
|
// An Error wraps lower level errors with code, message and an original error.
|
||||||
|
// The underlying concrete error type may also satisfy other interfaces which
|
||||||
|
// can be to used to obtain more specific information about the error.
|
||||||
|
//
|
||||||
|
// Calling Error() or String() will always include the full information about
|
||||||
|
// an error based on its underlying type.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// output, err := s3manage.Upload(svc, input, opts)
|
||||||
|
// if err != nil {
|
||||||
|
// if awsErr, ok := err.(awserr.Error); ok {
|
||||||
|
// // Get error details
|
||||||
|
// log.Println("Error:", err.Code(), err.Message())
|
||||||
|
//
|
||||||
|
// // Prints out full error message, including original error if there was one.
|
||||||
|
// log.Println("Error:", err.Error())
|
||||||
|
//
|
||||||
|
// // Get original error
|
||||||
|
// if origErr := err.Err(); origErr != nil {
|
||||||
|
// // operate on original error.
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// fmt.Println(err.Error())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
type Error interface {
|
||||||
|
// Satisfy the generic error interface.
|
||||||
|
error
|
||||||
|
|
||||||
|
// Returns the short phrase depicting the classification of the error.
|
||||||
|
Code() string
|
||||||
|
|
||||||
|
// Returns the error details message.
|
||||||
|
Message() string
|
||||||
|
|
||||||
|
// Returns the original error if one was set. Nil is returned if not set.
|
||||||
|
OrigErr() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns an Error object described by the code, message, and origErr.
|
||||||
|
//
|
||||||
|
// If origErr satisfies the Error interface it will not be wrapped within a new
|
||||||
|
// Error object and will instead be returned.
|
||||||
|
func New(code, message string, origErr error) Error {
|
||||||
|
if e, ok := origErr.(Error); ok && e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return newBaseError(code, message, origErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A RequestFailure is an interface to extract request failure information from
|
||||||
|
// an Error such as the request ID of the failed request returned by a service.
|
||||||
|
// RequestFailures may not always have a requestID value if the request failed
|
||||||
|
// prior to reaching the service such as a connection error.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// output, err := s3manage.Upload(svc, input, opts)
|
||||||
|
// if err != nil {
|
||||||
|
// if reqerr, ok := err.(RequestFailure); ok {
|
||||||
|
// log.Printf("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID())
|
||||||
|
// } else {
|
||||||
|
// log.Printf("Error:", err.Error()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Combined with awserr.Error:
|
||||||
|
//
|
||||||
|
// output, err := s3manage.Upload(svc, input, opts)
|
||||||
|
// if err != nil {
|
||||||
|
// if awsErr, ok := err.(awserr.Error); ok {
|
||||||
|
// // Generic AWS Error with Code, Message, and original error (if any)
|
||||||
|
// fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
|
||||||
|
//
|
||||||
|
// if reqErr, ok := err.(awserr.RequestFailure); ok {
|
||||||
|
// // A service error occurred
|
||||||
|
// fmt.Println(reqErr.StatusCode(), reqErr.RequestID())
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// fmt.Println(err.Error())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
type RequestFailure interface {
|
||||||
|
Error
|
||||||
|
|
||||||
|
// The status code of the HTTP response.
|
||||||
|
StatusCode() int
|
||||||
|
|
||||||
|
// The request ID returned by the service for a request failure. This will
|
||||||
|
// be empty if no request ID is available such as the request failed due
|
||||||
|
// to a connection error.
|
||||||
|
RequestID() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequestFailure returns a new request error wrapper for the given Error
|
||||||
|
// provided.
|
||||||
|
func NewRequestFailure(err Error, statusCode int, reqID string) RequestFailure {
|
||||||
|
return newRequestError(err, statusCode, reqID)
|
||||||
|
}
|
135
vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go
generated
vendored
Normal file
135
vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go
generated
vendored
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package awserr
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// SprintError returns a string of the formatted error code.
|
||||||
|
//
|
||||||
|
// Both extra and origErr are optional. If they are included their lines
|
||||||
|
// will be added, but if they are not included their lines will be ignored.
|
||||||
|
func SprintError(code, message, extra string, origErr error) string {
|
||||||
|
msg := fmt.Sprintf("%s: %s", code, message)
|
||||||
|
if extra != "" {
|
||||||
|
msg = fmt.Sprintf("%s\n\t%s", msg, extra)
|
||||||
|
}
|
||||||
|
if origErr != nil {
|
||||||
|
msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error())
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// A baseError wraps the code and message which defines an error. It also
|
||||||
|
// can be used to wrap an original error object.
|
||||||
|
//
|
||||||
|
// Should be used as the root for errors satisfying the awserr.Error. Also
|
||||||
|
// for any error which does not fit into a specific error wrapper type.
|
||||||
|
type baseError struct {
|
||||||
|
// Classification of error
|
||||||
|
code string
|
||||||
|
|
||||||
|
// Detailed information about error
|
||||||
|
message string
|
||||||
|
|
||||||
|
// Optional original error this error is based off of. Allows building
|
||||||
|
// chained errors.
|
||||||
|
origErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBaseError returns an error object for the code, message, and err.
|
||||||
|
//
|
||||||
|
// code is a short no whitespace phrase depicting the classification of
|
||||||
|
// the error that is being created.
|
||||||
|
//
|
||||||
|
// message is the free flow string containing detailed information about the error.
|
||||||
|
//
|
||||||
|
// origErr is the error object which will be nested under the new error to be returned.
|
||||||
|
func newBaseError(code, message string, origErr error) *baseError {
|
||||||
|
return &baseError{
|
||||||
|
code: code,
|
||||||
|
message: message,
|
||||||
|
origErr: origErr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns the string representation of the error.
|
||||||
|
//
|
||||||
|
// See ErrorWithExtra for formatting.
|
||||||
|
//
|
||||||
|
// Satisfies the error interface.
|
||||||
|
func (b baseError) Error() string {
|
||||||
|
return SprintError(b.code, b.message, "", b.origErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the error.
|
||||||
|
// Alias for Error to satisfy the stringer interface.
|
||||||
|
func (b baseError) String() string {
|
||||||
|
return b.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code returns the short phrase depicting the classification of the error.
|
||||||
|
func (b baseError) Code() string {
|
||||||
|
return b.code
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message returns the error details message.
|
||||||
|
func (b baseError) Message() string {
|
||||||
|
return b.message
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrigErr returns the original error if one was set. Nil is returned if no error
|
||||||
|
// was set.
|
||||||
|
func (b baseError) OrigErr() error {
|
||||||
|
return b.origErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 Error
|
||||||
|
|
||||||
|
// A requestError wraps a request or service error.
|
||||||
|
//
|
||||||
|
// Composed of baseError for code, message, and original error.
|
||||||
|
type requestError struct {
|
||||||
|
awsError
|
||||||
|
statusCode int
|
||||||
|
requestID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// newRequestError returns a wrapped error with additional information for request
|
||||||
|
// status code, and service requestID.
|
||||||
|
//
|
||||||
|
// Should be used to wrap all request which involve service requests. Even if
|
||||||
|
// the request failed without a service response, but had an HTTP status code
|
||||||
|
// that may be meaningful.
|
||||||
|
//
|
||||||
|
// Also wraps original errors via the baseError.
|
||||||
|
func newRequestError(err Error, statusCode int, requestID string) *requestError {
|
||||||
|
return &requestError{
|
||||||
|
awsError: err,
|
||||||
|
statusCode: statusCode,
|
||||||
|
requestID: requestID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns the string representation of the error.
|
||||||
|
// Satisfies the error interface.
|
||||||
|
func (r requestError) Error() string {
|
||||||
|
extra := fmt.Sprintf("status code: %d, request id: [%s]",
|
||||||
|
r.statusCode, r.requestID)
|
||||||
|
return SprintError(r.Code(), r.Message(), extra, r.OrigErr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the error.
|
||||||
|
// Alias for Error to satisfy the stringer interface.
|
||||||
|
func (r requestError) String() string {
|
||||||
|
return r.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatusCode returns the wrapped status code for the error
|
||||||
|
func (r requestError) StatusCode() int {
|
||||||
|
return r.statusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestID returns the wrapped requestID
|
||||||
|
func (r requestError) RequestID() string {
|
||||||
|
return r.requestID
|
||||||
|
}
|
103
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
Normal file
103
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package awsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Copy deeply copies a src structure to dst. Useful for copying request and
|
||||||
|
// response structures.
|
||||||
|
//
|
||||||
|
// Can copy between structs of different type, but will only copy fields which
|
||||||
|
// are assignable, and exist in both structs. Fields which are not assignable,
|
||||||
|
// or do not exist in both structs are ignored.
|
||||||
|
func Copy(dst, src interface{}) {
|
||||||
|
dstval := reflect.ValueOf(dst)
|
||||||
|
if !dstval.IsValid() {
|
||||||
|
panic("Copy dst cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
rcopy(dstval, reflect.ValueOf(src), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyOf returns a copy of src while also allocating the memory for dst.
|
||||||
|
// src must be a pointer type or this operation will fail.
|
||||||
|
func CopyOf(src interface{}) (dst interface{}) {
|
||||||
|
dsti := reflect.New(reflect.TypeOf(src).Elem())
|
||||||
|
dst = dsti.Interface()
|
||||||
|
rcopy(dsti, reflect.ValueOf(src), true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// rcopy performs a recursive copy of values from the source to destination.
|
||||||
|
//
|
||||||
|
// root is used to skip certain aspects of the copy which are not valid
|
||||||
|
// for the root node of a object.
|
||||||
|
func rcopy(dst, src reflect.Value, root bool) {
|
||||||
|
if !src.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch src.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
if _, ok := src.Interface().(io.Reader); ok {
|
||||||
|
if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() {
|
||||||
|
dst.Elem().Set(src)
|
||||||
|
} else if dst.CanSet() {
|
||||||
|
dst.Set(src)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
e := src.Type().Elem()
|
||||||
|
if dst.CanSet() && !src.IsNil() {
|
||||||
|
dst.Set(reflect.New(e))
|
||||||
|
}
|
||||||
|
if src.Elem().IsValid() {
|
||||||
|
// Keep the current root state since the depth hasn't changed
|
||||||
|
rcopy(dst.Elem(), src.Elem(), root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
if !root {
|
||||||
|
dst.Set(reflect.New(src.Type()).Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
t := dst.Type()
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
name := t.Field(i).Name
|
||||||
|
srcval := src.FieldByName(name)
|
||||||
|
if srcval.IsValid() {
|
||||||
|
rcopy(dst.FieldByName(name), srcval, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
if src.IsNil() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
|
||||||
|
dst.Set(s)
|
||||||
|
for i := 0; i < src.Len(); i++ {
|
||||||
|
rcopy(dst.Index(i), src.Index(i), false)
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
if src.IsNil() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
s := reflect.MakeMap(src.Type())
|
||||||
|
dst.Set(s)
|
||||||
|
for _, k := range src.MapKeys() {
|
||||||
|
v := src.MapIndex(k)
|
||||||
|
v2 := reflect.New(v.Type()).Elem()
|
||||||
|
rcopy(v2, v, false)
|
||||||
|
dst.SetMapIndex(k, v2)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Assign the value if possible. If its not assignable, the value would
|
||||||
|
// need to be converted and the impact of that may be unexpected, or is
|
||||||
|
// not compatible with the dst type.
|
||||||
|
if src.Type().AssignableTo(dst.Type()) {
|
||||||
|
dst.Set(src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
187
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
Normal file
187
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
package awsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
|
||||||
|
|
||||||
|
// rValuesAtPath returns a slice of values found in value v. The values
|
||||||
|
// in v are explored recursively so all nested values are collected.
|
||||||
|
func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool) []reflect.Value {
|
||||||
|
pathparts := strings.Split(path, "||")
|
||||||
|
if len(pathparts) > 1 {
|
||||||
|
for _, pathpart := range pathparts {
|
||||||
|
vals := rValuesAtPath(v, pathpart, create, caseSensitive)
|
||||||
|
if vals != nil && len(vals) > 0 {
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))}
|
||||||
|
components := strings.Split(path, ".")
|
||||||
|
for len(values) > 0 && len(components) > 0 {
|
||||||
|
var index *int64
|
||||||
|
var indexStar bool
|
||||||
|
c := strings.TrimSpace(components[0])
|
||||||
|
if c == "" { // no actual component, illegal syntax
|
||||||
|
return nil
|
||||||
|
} else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] {
|
||||||
|
// TODO normalize case for user
|
||||||
|
return nil // don't support unexported fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse this component
|
||||||
|
if m := indexRe.FindStringSubmatch(c); m != nil {
|
||||||
|
c = m[1]
|
||||||
|
if m[2] == "" {
|
||||||
|
index = nil
|
||||||
|
indexStar = true
|
||||||
|
} else {
|
||||||
|
i, _ := strconv.ParseInt(m[2], 10, 32)
|
||||||
|
index = &i
|
||||||
|
indexStar = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextvals := []reflect.Value{}
|
||||||
|
for _, value := range values {
|
||||||
|
// pull component name out of struct member
|
||||||
|
if value.Kind() != reflect.Struct {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == "*" { // pull all members
|
||||||
|
for i := 0; i < value.NumField(); i++ {
|
||||||
|
if f := reflect.Indirect(value.Field(i)); f.IsValid() {
|
||||||
|
nextvals = append(nextvals, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value.FieldByNameFunc(func(name string) bool {
|
||||||
|
if c == name {
|
||||||
|
return true
|
||||||
|
} else if !caseSensitive && strings.ToLower(name) == strings.ToLower(c) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if create && value.Kind() == reflect.Ptr && value.IsNil() {
|
||||||
|
value.Set(reflect.New(value.Type().Elem()))
|
||||||
|
value = value.Elem()
|
||||||
|
} else {
|
||||||
|
value = reflect.Indirect(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||||
|
if !create && value.IsNil() {
|
||||||
|
value = reflect.ValueOf(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.IsValid() {
|
||||||
|
nextvals = append(nextvals, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
values = nextvals
|
||||||
|
|
||||||
|
if indexStar || index != nil {
|
||||||
|
nextvals = []reflect.Value{}
|
||||||
|
for _, value := range values {
|
||||||
|
value := reflect.Indirect(value)
|
||||||
|
if value.Kind() != reflect.Slice {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if indexStar { // grab all indices
|
||||||
|
for i := 0; i < value.Len(); i++ {
|
||||||
|
idx := reflect.Indirect(value.Index(i))
|
||||||
|
if idx.IsValid() {
|
||||||
|
nextvals = append(nextvals, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// pull out index
|
||||||
|
i := int(*index)
|
||||||
|
if i >= value.Len() { // check out of bounds
|
||||||
|
if create {
|
||||||
|
// TODO resize slice
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if i < 0 { // support negative indexing
|
||||||
|
i = value.Len() + i
|
||||||
|
}
|
||||||
|
value = reflect.Indirect(value.Index(i))
|
||||||
|
|
||||||
|
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||||
|
if !create && value.IsNil() {
|
||||||
|
value = reflect.ValueOf(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.IsValid() {
|
||||||
|
nextvals = append(nextvals, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
values = nextvals
|
||||||
|
}
|
||||||
|
|
||||||
|
components = components[1:]
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValuesAtPath returns a list of objects at the lexical path inside of a structure
|
||||||
|
func ValuesAtPath(i interface{}, path string) []interface{} {
|
||||||
|
if rvals := rValuesAtPath(i, path, false, true); rvals != nil {
|
||||||
|
vals := make([]interface{}, len(rvals))
|
||||||
|
for i, rval := range rvals {
|
||||||
|
vals[i] = rval.Interface()
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValuesAtAnyPath returns a list of objects at the case-insensitive lexical
|
||||||
|
// path inside of a structure
|
||||||
|
func ValuesAtAnyPath(i interface{}, path string) []interface{} {
|
||||||
|
if rvals := rValuesAtPath(i, path, false, false); rvals != nil {
|
||||||
|
vals := make([]interface{}, len(rvals))
|
||||||
|
for i, rval := range rvals {
|
||||||
|
vals[i] = rval.Interface()
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetValueAtPath sets an object at the lexical path inside of a structure
|
||||||
|
func SetValueAtPath(i interface{}, path string, v interface{}) {
|
||||||
|
if rvals := rValuesAtPath(i, path, true, true); rvals != nil {
|
||||||
|
for _, rval := range rvals {
|
||||||
|
rval.Set(reflect.ValueOf(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetValueAtAnyPath sets an object at the case insensitive lexical path inside
|
||||||
|
// of a structure
|
||||||
|
func SetValueAtAnyPath(i interface{}, path string, v interface{}) {
|
||||||
|
if rvals := rValuesAtPath(i, path, true, false); rvals != nil {
|
||||||
|
for _, rval := range rvals {
|
||||||
|
rval.Set(reflect.ValueOf(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
103
vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
Normal file
103
vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package awsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Prettify returns the string representation of a value.
|
||||||
|
func Prettify(i interface{}) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
prettify(reflect.ValueOf(i), 0, &buf)
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// prettify will recursively walk value v to build a textual
|
||||||
|
// representation of the value.
|
||||||
|
func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
|
||||||
|
for v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
strtype := v.Type().String()
|
||||||
|
if strtype == "time.Time" {
|
||||||
|
fmt.Fprintf(buf, "%s", v.Interface())
|
||||||
|
break
|
||||||
|
} else if strings.HasPrefix(strtype, "io.") {
|
||||||
|
buf.WriteString("<buffer>")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("{\n")
|
||||||
|
|
||||||
|
names := []string{}
|
||||||
|
for i := 0; i < v.Type().NumField(); i++ {
|
||||||
|
name := v.Type().Field(i).Name
|
||||||
|
f := v.Field(i)
|
||||||
|
if name[0:1] == strings.ToLower(name[0:1]) {
|
||||||
|
continue // ignore unexported fields
|
||||||
|
}
|
||||||
|
if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() {
|
||||||
|
continue // ignore unset fields
|
||||||
|
}
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, n := range names {
|
||||||
|
val := v.FieldByName(n)
|
||||||
|
buf.WriteString(strings.Repeat(" ", indent+2))
|
||||||
|
buf.WriteString(n + ": ")
|
||||||
|
prettify(val, indent+2, buf)
|
||||||
|
|
||||||
|
if i < len(names)-1 {
|
||||||
|
buf.WriteString(",\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||||
|
case reflect.Slice:
|
||||||
|
nl, id, id2 := "", "", ""
|
||||||
|
if v.Len() > 3 {
|
||||||
|
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
|
||||||
|
}
|
||||||
|
buf.WriteString("[" + nl)
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
buf.WriteString(id2)
|
||||||
|
prettify(v.Index(i), indent+2, buf)
|
||||||
|
|
||||||
|
if i < v.Len()-1 {
|
||||||
|
buf.WriteString("," + nl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString(nl + id + "]")
|
||||||
|
case reflect.Map:
|
||||||
|
buf.WriteString("{\n")
|
||||||
|
|
||||||
|
for i, k := range v.MapKeys() {
|
||||||
|
buf.WriteString(strings.Repeat(" ", indent+2))
|
||||||
|
buf.WriteString(k.String() + ": ")
|
||||||
|
prettify(v.MapIndex(k), indent+2, buf)
|
||||||
|
|
||||||
|
if i < v.Len()-1 {
|
||||||
|
buf.WriteString(",\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||||
|
default:
|
||||||
|
format := "%v"
|
||||||
|
switch v.Interface().(type) {
|
||||||
|
case string:
|
||||||
|
format = "%q"
|
||||||
|
case io.ReadSeeker, io.Reader:
|
||||||
|
format = "buffer(%p)"
|
||||||
|
}
|
||||||
|
fmt.Fprintf(buf, format, v.Interface())
|
||||||
|
}
|
||||||
|
}
|
239
vendor/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
Normal file
239
vendor/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The default number of retries for a service. The value of -1 indicates that
|
||||||
|
// the service specific retry default will be used.
|
||||||
|
const DefaultRetries = -1
|
||||||
|
|
||||||
|
// A Config provides service configuration for service clients. By default,
|
||||||
|
// all clients will use the {DefaultConfig} structure.
|
||||||
|
type Config struct {
|
||||||
|
// The credentials object to use when signing requests. Defaults to
|
||||||
|
// {DefaultChainCredentials}.
|
||||||
|
Credentials *credentials.Credentials
|
||||||
|
|
||||||
|
// An optional endpoint URL (hostname only or fully qualified URI)
|
||||||
|
// that overrides the default generated endpoint for a client. Set this
|
||||||
|
// to `""` to use the default generated endpoint.
|
||||||
|
//
|
||||||
|
// @note You must still provide a `Region` value when specifying an
|
||||||
|
// endpoint for a client.
|
||||||
|
Endpoint *string
|
||||||
|
|
||||||
|
// The region to send requests to. This parameter is required and must
|
||||||
|
// be configured globally or on a per-client basis unless otherwise
|
||||||
|
// noted. A full list of regions is found in the "Regions and Endpoints"
|
||||||
|
// document.
|
||||||
|
//
|
||||||
|
// @see http://docs.aws.amazon.com/general/latest/gr/rande.html
|
||||||
|
// AWS Regions and Endpoints
|
||||||
|
Region *string
|
||||||
|
|
||||||
|
// Set this to `true` to disable SSL when sending requests. Defaults
|
||||||
|
// to `false`.
|
||||||
|
DisableSSL *bool
|
||||||
|
|
||||||
|
// The HTTP client to use when sending requests. Defaults to
|
||||||
|
// `http.DefaultClient`.
|
||||||
|
HTTPClient *http.Client
|
||||||
|
|
||||||
|
// An integer value representing the logging level. The default log level
|
||||||
|
// is zero (LogOff), which represents no logging. To enable logging set
|
||||||
|
// to a LogLevel Value.
|
||||||
|
LogLevel *LogLevelType
|
||||||
|
|
||||||
|
// The logger writer interface to write logging messages to. Defaults to
|
||||||
|
// standard out.
|
||||||
|
Logger Logger
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// configuration.
|
||||||
|
MaxRetries *int
|
||||||
|
|
||||||
|
// Disables semantic parameter validation, which validates input for missing
|
||||||
|
// required fields and/or other semantic request input errors.
|
||||||
|
DisableParamValidation *bool
|
||||||
|
|
||||||
|
// Disables the computation of request and response checksums, e.g.,
|
||||||
|
// CRC32 checksums in Amazon DynamoDB.
|
||||||
|
DisableComputeChecksums *bool
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// use virtual hosted bucket addressing when possible
|
||||||
|
// (`http://BUCKET.s3.amazonaws.com/KEY`).
|
||||||
|
//
|
||||||
|
// @note This configuration option is specific to the Amazon S3 service.
|
||||||
|
// @see http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html
|
||||||
|
// Amazon S3: Virtual Hosting of Buckets
|
||||||
|
S3ForcePathStyle *bool
|
||||||
|
|
||||||
|
SleepDelay func(time.Duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConfig returns a new Config pointer that can be chained with builder methods to
|
||||||
|
// set multiple configuration values inline without using pointers.
|
||||||
|
//
|
||||||
|
// svc := s3.New(aws.NewConfig().WithRegion("us-west-2").WithMaxRetries(10))
|
||||||
|
//
|
||||||
|
func NewConfig() *Config {
|
||||||
|
return &Config{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCredentials sets a config Credentials value returning a Config pointer
|
||||||
|
// for chaining.
|
||||||
|
func (c *Config) WithCredentials(creds *credentials.Credentials) *Config {
|
||||||
|
c.Credentials = creds
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithEndpoint sets a config Endpoint value returning a Config pointer for
|
||||||
|
// chaining.
|
||||||
|
func (c *Config) WithEndpoint(endpoint string) *Config {
|
||||||
|
c.Endpoint = &endpoint
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRegion sets a config Region value returning a Config pointer for
|
||||||
|
// chaining.
|
||||||
|
func (c *Config) WithRegion(region string) *Config {
|
||||||
|
c.Region = ®ion
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDisableSSL sets a config DisableSSL value returning a Config pointer
|
||||||
|
// for chaining.
|
||||||
|
func (c *Config) WithDisableSSL(disable bool) *Config {
|
||||||
|
c.DisableSSL = &disable
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHTTPClient sets a config HTTPClient value returning a Config pointer
|
||||||
|
// for chaining.
|
||||||
|
func (c *Config) WithHTTPClient(client *http.Client) *Config {
|
||||||
|
c.HTTPClient = client
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxRetries sets a config MaxRetries value returning a Config pointer
|
||||||
|
// for chaining.
|
||||||
|
func (c *Config) WithMaxRetries(max int) *Config {
|
||||||
|
c.MaxRetries = &max
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDisableParamValidation sets a config DisableParamValidation value
|
||||||
|
// returning a Config pointer for chaining.
|
||||||
|
func (c *Config) WithDisableParamValidation(disable bool) *Config {
|
||||||
|
c.DisableParamValidation = &disable
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDisableComputeChecksums sets a config DisableComputeChecksums value
|
||||||
|
// returning a Config pointer for chaining.
|
||||||
|
func (c *Config) WithDisableComputeChecksums(disable bool) *Config {
|
||||||
|
c.DisableComputeChecksums = &disable
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLogLevel sets a config LogLevel value returning a Config pointer for
|
||||||
|
// chaining.
|
||||||
|
func (c *Config) WithLogLevel(level LogLevelType) *Config {
|
||||||
|
c.LogLevel = &level
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLogger sets a config Logger value returning a Config pointer for
|
||||||
|
// chaining.
|
||||||
|
func (c *Config) WithLogger(logger Logger) *Config {
|
||||||
|
c.Logger = logger
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithS3ForcePathStyle sets a config S3ForcePathStyle value returning a Config
|
||||||
|
// pointer for chaining.
|
||||||
|
func (c *Config) WithS3ForcePathStyle(force bool) *Config {
|
||||||
|
c.S3ForcePathStyle = &force
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSleepDelay overrides the function used to sleep while waiting for the
|
||||||
|
// next retry. Defaults to time.Sleep.
|
||||||
|
func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
|
||||||
|
c.SleepDelay = fn
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge returns a new Config with the other Config's attribute values merged into
|
||||||
|
// this Config. If the other Config's attribute is nil it will not be merged into
|
||||||
|
// the new Config to be returned.
|
||||||
|
func (c Config) Merge(other *Config) *Config {
|
||||||
|
if other == nil {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := c
|
||||||
|
|
||||||
|
if other.Credentials != nil {
|
||||||
|
dst.Credentials = other.Credentials
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.Endpoint != nil {
|
||||||
|
dst.Endpoint = other.Endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.Region != nil {
|
||||||
|
dst.Region = other.Region
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.DisableSSL != nil {
|
||||||
|
dst.DisableSSL = other.DisableSSL
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.HTTPClient != nil {
|
||||||
|
dst.HTTPClient = other.HTTPClient
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.LogLevel != nil {
|
||||||
|
dst.LogLevel = other.LogLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.Logger != nil {
|
||||||
|
dst.Logger = other.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.MaxRetries != nil {
|
||||||
|
dst.MaxRetries = other.MaxRetries
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.DisableParamValidation != nil {
|
||||||
|
dst.DisableParamValidation = other.DisableParamValidation
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.DisableComputeChecksums != nil {
|
||||||
|
dst.DisableComputeChecksums = other.DisableComputeChecksums
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.S3ForcePathStyle != nil {
|
||||||
|
dst.S3ForcePathStyle = other.S3ForcePathStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.SleepDelay != nil {
|
||||||
|
dst.SleepDelay = other.SleepDelay
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy will return a shallow copy of the Config object.
|
||||||
|
func (c Config) Copy() *Config {
|
||||||
|
dst := c
|
||||||
|
return &dst
|
||||||
|
}
|
357
vendor/github.com/aws/aws-sdk-go/aws/convert_types.go
generated
vendored
Normal file
357
vendor/github.com/aws/aws-sdk-go/aws/convert_types.go
generated
vendored
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// String returns a pointer to of the string value passed in.
|
||||||
|
func String(v string) *string {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringValue returns the value of the string pointer passed in or
|
||||||
|
// "" if the pointer is nil.
|
||||||
|
func StringValue(v *string) string {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSlice converts a slice of string values into a slice of
|
||||||
|
// string pointers
|
||||||
|
func StringSlice(src []string) []*string {
|
||||||
|
dst := make([]*string, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = &(src[i])
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringValueSlice converts a slice of string pointers into a slice of
|
||||||
|
// string values
|
||||||
|
func StringValueSlice(src []*string) []string {
|
||||||
|
dst := make([]string, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
if src[i] != nil {
|
||||||
|
dst[i] = *(src[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringMap converts a string map of string values into a string
|
||||||
|
// map of string pointers
|
||||||
|
func StringMap(src map[string]string) map[string]*string {
|
||||||
|
dst := make(map[string]*string)
|
||||||
|
for k, val := range src {
|
||||||
|
v := val
|
||||||
|
dst[k] = &v
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringValueMap converts a string map of string pointers into a string
|
||||||
|
// map of string values
|
||||||
|
func StringValueMap(src map[string]*string) map[string]string {
|
||||||
|
dst := make(map[string]string)
|
||||||
|
for k, val := range src {
|
||||||
|
if val != nil {
|
||||||
|
dst[k] = *val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool returns a pointer to of the bool value passed in.
|
||||||
|
func Bool(v bool) *bool {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolValue returns the value of the bool pointer passed in or
|
||||||
|
// false if the pointer is nil.
|
||||||
|
func BoolValue(v *bool) bool {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSlice converts a slice of bool values into a slice of
|
||||||
|
// bool pointers
|
||||||
|
func BoolSlice(src []bool) []*bool {
|
||||||
|
dst := make([]*bool, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = &(src[i])
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolValueSlice converts a slice of bool pointers into a slice of
|
||||||
|
// bool values
|
||||||
|
func BoolValueSlice(src []*bool) []bool {
|
||||||
|
dst := make([]bool, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
if src[i] != nil {
|
||||||
|
dst[i] = *(src[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolMap converts a string map of bool values into a string
|
||||||
|
// map of bool pointers
|
||||||
|
func BoolMap(src map[string]bool) map[string]*bool {
|
||||||
|
dst := make(map[string]*bool)
|
||||||
|
for k, val := range src {
|
||||||
|
v := val
|
||||||
|
dst[k] = &v
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolValueMap converts a string map of bool pointers into a string
|
||||||
|
// map of bool values
|
||||||
|
func BoolValueMap(src map[string]*bool) map[string]bool {
|
||||||
|
dst := make(map[string]bool)
|
||||||
|
for k, val := range src {
|
||||||
|
if val != nil {
|
||||||
|
dst[k] = *val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int returns a pointer to of the int value passed in.
|
||||||
|
func Int(v int) *int {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntValue returns the value of the int pointer passed in or
|
||||||
|
// 0 if the pointer is nil.
|
||||||
|
func IntValue(v *int) int {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntSlice converts a slice of int values into a slice of
|
||||||
|
// int pointers
|
||||||
|
func IntSlice(src []int) []*int {
|
||||||
|
dst := make([]*int, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = &(src[i])
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntValueSlice converts a slice of int pointers into a slice of
|
||||||
|
// int values
|
||||||
|
func IntValueSlice(src []*int) []int {
|
||||||
|
dst := make([]int, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
if src[i] != nil {
|
||||||
|
dst[i] = *(src[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntMap converts a string map of int values into a string
|
||||||
|
// map of int pointers
|
||||||
|
func IntMap(src map[string]int) map[string]*int {
|
||||||
|
dst := make(map[string]*int)
|
||||||
|
for k, val := range src {
|
||||||
|
v := val
|
||||||
|
dst[k] = &v
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntValueMap converts a string map of int pointers into a string
|
||||||
|
// map of int values
|
||||||
|
func IntValueMap(src map[string]*int) map[string]int {
|
||||||
|
dst := make(map[string]int)
|
||||||
|
for k, val := range src {
|
||||||
|
if val != nil {
|
||||||
|
dst[k] = *val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns a pointer to of the int64 value passed in.
|
||||||
|
func Int64(v int64) *int64 {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Value returns the value of the int64 pointer passed in or
|
||||||
|
// 0 if the pointer is nil.
|
||||||
|
func Int64Value(v *int64) int64 {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Slice converts a slice of int64 values into a slice of
|
||||||
|
// int64 pointers
|
||||||
|
func Int64Slice(src []int64) []*int64 {
|
||||||
|
dst := make([]*int64, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = &(src[i])
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64ValueSlice converts a slice of int64 pointers into a slice of
|
||||||
|
// int64 values
|
||||||
|
func Int64ValueSlice(src []*int64) []int64 {
|
||||||
|
dst := make([]int64, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
if src[i] != nil {
|
||||||
|
dst[i] = *(src[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Map converts a string map of int64 values into a string
|
||||||
|
// map of int64 pointers
|
||||||
|
func Int64Map(src map[string]int64) map[string]*int64 {
|
||||||
|
dst := make(map[string]*int64)
|
||||||
|
for k, val := range src {
|
||||||
|
v := val
|
||||||
|
dst[k] = &v
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64ValueMap converts a string map of int64 pointers into a string
|
||||||
|
// map of int64 values
|
||||||
|
func Int64ValueMap(src map[string]*int64) map[string]int64 {
|
||||||
|
dst := make(map[string]int64)
|
||||||
|
for k, val := range src {
|
||||||
|
if val != nil {
|
||||||
|
dst[k] = *val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 returns a pointer to of the float64 value passed in.
|
||||||
|
func Float64(v float64) *float64 {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Value returns the value of the float64 pointer passed in or
|
||||||
|
// 0 if the pointer is nil.
|
||||||
|
func Float64Value(v *float64) float64 {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Slice converts a slice of float64 values into a slice of
|
||||||
|
// float64 pointers
|
||||||
|
func Float64Slice(src []float64) []*float64 {
|
||||||
|
dst := make([]*float64, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = &(src[i])
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64ValueSlice converts a slice of float64 pointers into a slice of
|
||||||
|
// float64 values
|
||||||
|
func Float64ValueSlice(src []*float64) []float64 {
|
||||||
|
dst := make([]float64, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
if src[i] != nil {
|
||||||
|
dst[i] = *(src[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Map converts a string map of float64 values into a string
|
||||||
|
// map of float64 pointers
|
||||||
|
func Float64Map(src map[string]float64) map[string]*float64 {
|
||||||
|
dst := make(map[string]*float64)
|
||||||
|
for k, val := range src {
|
||||||
|
v := val
|
||||||
|
dst[k] = &v
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64ValueMap converts a string map of float64 pointers into a string
|
||||||
|
// map of float64 values
|
||||||
|
func Float64ValueMap(src map[string]*float64) map[string]float64 {
|
||||||
|
dst := make(map[string]float64)
|
||||||
|
for k, val := range src {
|
||||||
|
if val != nil {
|
||||||
|
dst[k] = *val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time returns a pointer to of the time.Time value passed in.
|
||||||
|
func Time(v time.Time) *time.Time {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeValue returns the value of the time.Time pointer passed in or
|
||||||
|
// time.Time{} if the pointer is nil.
|
||||||
|
func TimeValue(v *time.Time) time.Time {
|
||||||
|
if v != nil {
|
||||||
|
return *v
|
||||||
|
}
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeSlice converts a slice of time.Time values into a slice of
|
||||||
|
// time.Time pointers
|
||||||
|
func TimeSlice(src []time.Time) []*time.Time {
|
||||||
|
dst := make([]*time.Time, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
dst[i] = &(src[i])
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeValueSlice converts a slice of time.Time pointers into a slice of
|
||||||
|
// time.Time values
|
||||||
|
func TimeValueSlice(src []*time.Time) []time.Time {
|
||||||
|
dst := make([]time.Time, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
if src[i] != nil {
|
||||||
|
dst[i] = *(src[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeMap converts a string map of time.Time values into a string
|
||||||
|
// map of time.Time pointers
|
||||||
|
func TimeMap(src map[string]time.Time) map[string]*time.Time {
|
||||||
|
dst := make(map[string]*time.Time)
|
||||||
|
for k, val := range src {
|
||||||
|
v := val
|
||||||
|
dst[k] = &v
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeValueMap converts a string map of time.Time pointers into a string
|
||||||
|
// map of time.Time values
|
||||||
|
func TimeValueMap(src map[string]*time.Time) map[string]time.Time {
|
||||||
|
dst := make(map[string]time.Time)
|
||||||
|
for k, val := range src {
|
||||||
|
if val != nil {
|
||||||
|
dst[k] = *val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
137
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
generated
vendored
Normal file
137
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
package corehandlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface for matching types which also have a Len method.
|
||||||
|
type lener interface {
|
||||||
|
Len() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildContentLength builds the content length of a request based on the body,
|
||||||
|
// or will use the HTTPRequest.Header's "Content-Length" if defined. If unable
|
||||||
|
// to determine request body length and no "Content-Length" was specified it will panic.
|
||||||
|
var BuildContentLengthHandler = request.NamedHandler{"core.BuildContentLengthHandler", func(r *request.Request) {
|
||||||
|
if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
|
||||||
|
length, _ := strconv.ParseInt(slength, 10, 64)
|
||||||
|
r.HTTPRequest.ContentLength = length
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var length int64
|
||||||
|
switch body := r.Body.(type) {
|
||||||
|
case nil:
|
||||||
|
length = 0
|
||||||
|
case lener:
|
||||||
|
length = int64(body.Len())
|
||||||
|
case io.Seeker:
|
||||||
|
r.BodyStart, _ = body.Seek(0, 1)
|
||||||
|
end, _ := body.Seek(0, 2)
|
||||||
|
body.Seek(r.BodyStart, 0) // make sure to seek back to original location
|
||||||
|
length = end - r.BodyStart
|
||||||
|
default:
|
||||||
|
panic("Cannot get length of body, must provide `ContentLength`")
|
||||||
|
}
|
||||||
|
|
||||||
|
r.HTTPRequest.ContentLength = length
|
||||||
|
r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
|
||||||
|
}}
|
||||||
|
|
||||||
|
// UserAgentHandler is a request handler for injecting User agent into requests.
|
||||||
|
var UserAgentHandler = request.NamedHandler{"core.UserAgentHandler", func(r *request.Request) {
|
||||||
|
r.HTTPRequest.Header.Set("User-Agent", aws.SDKName+"/"+aws.SDKVersion)
|
||||||
|
}}
|
||||||
|
|
||||||
|
var reStatusCode = regexp.MustCompile(`^(\d{3})`)
|
||||||
|
|
||||||
|
// SendHandler is a request handler to send service request using HTTP client.
|
||||||
|
var SendHandler = request.NamedHandler{"core.SendHandler", func(r *request.Request) {
|
||||||
|
var err error
|
||||||
|
r.HTTPResponse, err = r.Service.Config.HTTPClient.Do(r.HTTPRequest)
|
||||||
|
if err != nil {
|
||||||
|
// Capture the case where url.Error is returned for error processing
|
||||||
|
// response. e.g. 301 without location header comes back as string
|
||||||
|
// error and r.HTTPResponse is nil. Other url redirect errors will
|
||||||
|
// comeback in a similar method.
|
||||||
|
if e, ok := err.(*url.Error); ok && e.Err != nil {
|
||||||
|
if s := reStatusCode.FindStringSubmatch(e.Err.Error()); s != nil {
|
||||||
|
code, _ := strconv.ParseInt(s[1], 10, 64)
|
||||||
|
r.HTTPResponse = &http.Response{
|
||||||
|
StatusCode: int(code),
|
||||||
|
Status: http.StatusText(int(code)),
|
||||||
|
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.HTTPResponse == nil {
|
||||||
|
// Add a dummy request response object to ensure the HTTPResponse
|
||||||
|
// value is consistent.
|
||||||
|
r.HTTPResponse = &http.Response{
|
||||||
|
StatusCode: int(0),
|
||||||
|
Status: http.StatusText(int(0)),
|
||||||
|
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Catch all other request errors.
|
||||||
|
r.Error = awserr.New("RequestError", "send request failed", err)
|
||||||
|
r.Retryable = aws.Bool(true) // network errors are retryable
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
// ValidateResponseHandler is a request handler to validate service response.
|
||||||
|
var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler", func(r *request.Request) {
|
||||||
|
if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 {
|
||||||
|
// this may be replaced by an UnmarshalError handler
|
||||||
|
r.Error = awserr.New("UnknownError", "unknown error", nil)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
// AfterRetryHandler performs final checks to determine if the request should
|
||||||
|
// be retried and how long to delay.
|
||||||
|
var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *request.Request) {
|
||||||
|
// If one of the other handlers already set the retry state
|
||||||
|
// we don't want to override it based on the service's state
|
||||||
|
if r.Retryable == nil {
|
||||||
|
r.Retryable = aws.Bool(r.ShouldRetry(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.WillRetry() {
|
||||||
|
r.RetryDelay = r.RetryRules(r)
|
||||||
|
fmt.Println(r.Service.Config.SleepDelay)
|
||||||
|
r.Service.Config.SleepDelay(r.RetryDelay)
|
||||||
|
|
||||||
|
// when the expired token exception occurs the credentials
|
||||||
|
// need to be expired locally so that the next request to
|
||||||
|
// get credentials will trigger a credentials refresh.
|
||||||
|
if r.IsErrorExpired() {
|
||||||
|
r.Service.Config.Credentials.Expire()
|
||||||
|
}
|
||||||
|
|
||||||
|
r.RetryCount++
|
||||||
|
r.Error = nil
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
// ValidateEndpointHandler is a request handler to validate a request had the
|
||||||
|
// appropriate Region and Endpoint set. Will set r.Error if the endpoint or
|
||||||
|
// region is not valid.
|
||||||
|
var ValidateEndpointHandler = request.NamedHandler{"core.ValidateEndpointHandler", func(r *request.Request) {
|
||||||
|
if r.Service.SigningRegion == "" && aws.StringValue(r.Service.Config.Region) == "" {
|
||||||
|
r.Error = aws.ErrMissingRegion
|
||||||
|
} else if r.Service.Endpoint == "" {
|
||||||
|
r.Error = aws.ErrMissingEndpoint
|
||||||
|
}
|
||||||
|
}}
|
90
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
generated
vendored
Normal file
90
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
package corehandlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidateParameters is a request handler to validate the input parameters.
|
||||||
|
// Validating parameters only has meaning if done prior to the request being sent.
|
||||||
|
var ValidateParametersHandler = request.NamedHandler{"core.ValidateParametersHandler", func(r *request.Request) {
|
||||||
|
if r.ParamsFilled() {
|
||||||
|
v := validator{errors: []string{}}
|
||||||
|
v.validateAny(reflect.ValueOf(r.Params), "")
|
||||||
|
|
||||||
|
if count := len(v.errors); count > 0 {
|
||||||
|
format := "%d validation errors:\n- %s"
|
||||||
|
msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- "))
|
||||||
|
r.Error = awserr.New("InvalidParameter", msg, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
// A validator validates values. Collects validations errors which occurs.
|
||||||
|
type validator struct {
|
||||||
|
errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateAny will validate any struct, slice or map type. All validations
|
||||||
|
// are also performed recursively for nested types.
|
||||||
|
func (v *validator) validateAny(value reflect.Value, path string) {
|
||||||
|
value = reflect.Indirect(value)
|
||||||
|
if !value.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
v.validateStruct(value, path)
|
||||||
|
case reflect.Slice:
|
||||||
|
for i := 0; i < value.Len(); i++ {
|
||||||
|
v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i))
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
for _, n := range value.MapKeys() {
|
||||||
|
v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateStruct will validate the struct value's fields. If the structure has
|
||||||
|
// nested types those types will be validated also.
|
||||||
|
func (v *validator) validateStruct(value reflect.Value, path string) {
|
||||||
|
prefix := "."
|
||||||
|
if path == "" {
|
||||||
|
prefix = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < value.Type().NumField(); i++ {
|
||||||
|
f := value.Type().Field(i)
|
||||||
|
if strings.ToLower(f.Name[0:1]) == f.Name[0:1] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fvalue := value.FieldByName(f.Name)
|
||||||
|
|
||||||
|
notset := false
|
||||||
|
if f.Tag.Get("required") != "" {
|
||||||
|
switch fvalue.Kind() {
|
||||||
|
case reflect.Ptr, reflect.Slice, reflect.Map:
|
||||||
|
if fvalue.IsNil() {
|
||||||
|
notset = true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if !fvalue.IsValid() {
|
||||||
|
notset = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if notset {
|
||||||
|
msg := "missing required parameter: " + path + prefix + f.Name
|
||||||
|
v.errors = append(v.errors, msg)
|
||||||
|
} else {
|
||||||
|
v.validateAny(fvalue, path+prefix+f.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
Normal file
85
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNoValidProvidersFoundInChain Is returned when there are no valid
|
||||||
|
// providers in the ChainProvider.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
ErrNoValidProvidersFoundInChain = awserr.New("NoCredentialProviders", "no valid providers in chain", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ChainProvider will search for a provider which returns credentials
|
||||||
|
// and cache that provider until Retrieve is called again.
|
||||||
|
//
|
||||||
|
// The ChainProvider provides a way of chaining multiple providers together
|
||||||
|
// which will pick the first available using priority order of the Providers
|
||||||
|
// in the list.
|
||||||
|
//
|
||||||
|
// If none of the Providers retrieve valid credentials Value, ChainProvider's
|
||||||
|
// Retrieve() will return the error ErrNoValidProvidersFoundInChain.
|
||||||
|
//
|
||||||
|
// If a Provider is found which returns valid credentials Value ChainProvider
|
||||||
|
// will cache that Provider for all calls to IsExpired(), until Retrieve is
|
||||||
|
// called again.
|
||||||
|
//
|
||||||
|
// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
|
||||||
|
// In this example EnvProvider will first check if any credentials are available
|
||||||
|
// vai the environment variables. If there are none ChainProvider will check
|
||||||
|
// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
|
||||||
|
// does not return any credentials ChainProvider will return the error
|
||||||
|
// ErrNoValidProvidersFoundInChain
|
||||||
|
//
|
||||||
|
// creds := NewChainCredentials(
|
||||||
|
// []Provider{
|
||||||
|
// &EnvProvider{},
|
||||||
|
// &EC2RoleProvider{},
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// // Usage of ChainCredentials with aws.Config
|
||||||
|
// svc := ec2.New(&aws.Config{Credentials: creds})
|
||||||
|
//
|
||||||
|
type ChainProvider struct {
|
||||||
|
Providers []Provider
|
||||||
|
curr Provider
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewChainCredentials returns a pointer to a new Credentials object
|
||||||
|
// wrapping a chain of providers.
|
||||||
|
func NewChainCredentials(providers []Provider) *Credentials {
|
||||||
|
return NewCredentials(&ChainProvider{
|
||||||
|
Providers: append([]Provider{}, providers...),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve returns the credentials value or error if no provider returned
|
||||||
|
// without error.
|
||||||
|
//
|
||||||
|
// If a provider is found it will be cached and any calls to IsExpired()
|
||||||
|
// will return the expired state of the cached provider.
|
||||||
|
func (c *ChainProvider) Retrieve() (Value, error) {
|
||||||
|
for _, p := range c.Providers {
|
||||||
|
if creds, err := p.Retrieve(); err == nil {
|
||||||
|
c.curr = p
|
||||||
|
return creds, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.curr = nil
|
||||||
|
|
||||||
|
// TODO better error reporting. maybe report error for each failed retrieve?
|
||||||
|
|
||||||
|
return Value{}, ErrNoValidProvidersFoundInChain
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired will returned the expired state of the currently cached provider
|
||||||
|
// if there is one. If there is no current provider, true will be returned.
|
||||||
|
func (c *ChainProvider) IsExpired() bool {
|
||||||
|
if c.curr != nil {
|
||||||
|
return c.curr.IsExpired()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
220
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
generated
vendored
Normal file
220
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
generated
vendored
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
// Package credentials provides credential retrieval and management
|
||||||
|
//
|
||||||
|
// The Credentials is the primary method of getting access to and managing
|
||||||
|
// credentials Values. Using dependency injection retrieval of the credential
|
||||||
|
// values is handled by a object which satisfies the Provider interface.
|
||||||
|
//
|
||||||
|
// By default the Credentials.Get() will cache the successful result of a
|
||||||
|
// Provider's Retrieve() until Provider.IsExpired() returns true. At which
|
||||||
|
// point Credentials will call Provider's Retrieve() to get new credential Value.
|
||||||
|
//
|
||||||
|
// The Provider is responsible for determining when credentials Value have expired.
|
||||||
|
// It is also important to note that Credentials will always call Retrieve the
|
||||||
|
// first time Credentials.Get() is called.
|
||||||
|
//
|
||||||
|
// Example of using the environment variable credentials.
|
||||||
|
//
|
||||||
|
// creds := NewEnvCredentials()
|
||||||
|
//
|
||||||
|
// // Retrieve the credentials value
|
||||||
|
// credValue, err := creds.Get()
|
||||||
|
// if err != nil {
|
||||||
|
// // handle error
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Example of forcing credentials to expire and be refreshed on the next Get().
|
||||||
|
// This may be helpful to proactively expire credentials and refresh them sooner
|
||||||
|
// than they would naturally expire on their own.
|
||||||
|
//
|
||||||
|
// creds := NewCredentials(&EC2RoleProvider{})
|
||||||
|
// creds.Expire()
|
||||||
|
// credsValue, err := creds.Get()
|
||||||
|
// // New credentials will be retrieved instead of from cache.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Custom Provider
|
||||||
|
//
|
||||||
|
// Each Provider built into this package also provides a helper method to generate
|
||||||
|
// a Credentials pointer setup with the provider. To use a custom Provider just
|
||||||
|
// create a type which satisfies the Provider interface and pass it to the
|
||||||
|
// NewCredentials method.
|
||||||
|
//
|
||||||
|
// type MyProvider struct{}
|
||||||
|
// func (m *MyProvider) Retrieve() (Value, error) {...}
|
||||||
|
// func (m *MyProvider) IsExpired() bool {...}
|
||||||
|
//
|
||||||
|
// creds := NewCredentials(&MyProvider{})
|
||||||
|
// credValue, err := creds.Get()
|
||||||
|
//
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create an empty Credential object that can be used as dummy placeholder
|
||||||
|
// credentials for requests that do not need signed.
|
||||||
|
//
|
||||||
|
// This Credentials can be used to configure a service to not sign requests
|
||||||
|
// when making service API calls. For example, when accessing public
|
||||||
|
// s3 buckets.
|
||||||
|
//
|
||||||
|
// svc := s3.New(&aws.Config{Credentials: AnonymousCredentials})
|
||||||
|
// // Access public S3 buckets.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
var AnonymousCredentials = NewStaticCredentials("", "", "")
|
||||||
|
|
||||||
|
// A Value is the AWS credentials value for individual credential fields.
|
||||||
|
type Value struct {
|
||||||
|
// AWS Access key ID
|
||||||
|
AccessKeyID string
|
||||||
|
|
||||||
|
// AWS Secret Access Key
|
||||||
|
SecretAccessKey string
|
||||||
|
|
||||||
|
// AWS Session Token
|
||||||
|
SessionToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Provider is the interface for any component which will provide credentials
|
||||||
|
// Value. A provider is required to manage its own Expired state, and what to
|
||||||
|
// be expired means.
|
||||||
|
//
|
||||||
|
// The Provider should not need to implement its own mutexes, because
|
||||||
|
// that will be managed by Credentials.
|
||||||
|
type Provider interface {
|
||||||
|
// Refresh returns nil if it successfully retrieved the value.
|
||||||
|
// Error is returned if the value were not obtainable, or empty.
|
||||||
|
Retrieve() (Value, error)
|
||||||
|
|
||||||
|
// IsExpired returns if the credentials are no longer valid, and need
|
||||||
|
// to be retrieved.
|
||||||
|
IsExpired() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Expiry provides shared expiration logic to be used by credentials
|
||||||
|
// providers to implement expiry functionality.
|
||||||
|
//
|
||||||
|
// The best method to use this struct is as an anonymous field within the
|
||||||
|
// provider's struct.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// type EC2RoleProvider struct {
|
||||||
|
// Expiry
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
type Expiry struct {
|
||||||
|
// The date/time when to expire on
|
||||||
|
expiration time.Time
|
||||||
|
|
||||||
|
// If set will be used by IsExpired to determine the current time.
|
||||||
|
// Defaults to time.Now if CurrentTime is not set. Available for testing
|
||||||
|
// to be able to mock out the current time.
|
||||||
|
CurrentTime func() time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExpiration sets the expiration IsExpired will check when called.
|
||||||
|
//
|
||||||
|
// If window is greater than 0 the expiration time will be reduced by the
|
||||||
|
// window value.
|
||||||
|
//
|
||||||
|
// Using a window is helpful to trigger credentials to expire sooner than
|
||||||
|
// the expiration time given to ensure no requests are made with expired
|
||||||
|
// tokens.
|
||||||
|
func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
|
||||||
|
e.expiration = expiration
|
||||||
|
if window > 0 {
|
||||||
|
e.expiration = e.expiration.Add(-window)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired returns if the credentials are expired.
|
||||||
|
func (e *Expiry) IsExpired() bool {
|
||||||
|
if e.CurrentTime == nil {
|
||||||
|
e.CurrentTime = time.Now
|
||||||
|
}
|
||||||
|
return e.expiration.Before(e.CurrentTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Credentials provides synchronous safe retrieval of AWS credentials Value.
|
||||||
|
// Credentials will cache the credentials value until they expire. Once the value
|
||||||
|
// expires the next Get will attempt to retrieve valid credentials.
|
||||||
|
//
|
||||||
|
// Credentials is safe to use across multiple goroutines and will manage the
|
||||||
|
// synchronous state so the Providers do not need to implement their own
|
||||||
|
// synchronization.
|
||||||
|
//
|
||||||
|
// The first Credentials.Get() will always call Provider.Retrieve() to get the
|
||||||
|
// first instance of the credentials Value. All calls to Get() after that
|
||||||
|
// will return the cached credentials Value until IsExpired() returns true.
|
||||||
|
type Credentials struct {
|
||||||
|
creds Value
|
||||||
|
forceRefresh bool
|
||||||
|
m sync.Mutex
|
||||||
|
|
||||||
|
provider Provider
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCredentials returns a pointer to a new Credentials with the provider set.
|
||||||
|
func NewCredentials(provider Provider) *Credentials {
|
||||||
|
return &Credentials{
|
||||||
|
provider: provider,
|
||||||
|
forceRefresh: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the credentials value, or error if the credentials Value failed
|
||||||
|
// to be retrieved.
|
||||||
|
//
|
||||||
|
// Will return the cached credentials Value if it has not expired. If the
|
||||||
|
// credentials Value has expired the Provider's Retrieve() will be called
|
||||||
|
// to refresh the credentials.
|
||||||
|
//
|
||||||
|
// If Credentials.Expire() was called the credentials Value will be force
|
||||||
|
// expired, and the next call to Get() will cause them to be refreshed.
|
||||||
|
func (c *Credentials) Get() (Value, error) {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
|
||||||
|
if c.isExpired() {
|
||||||
|
creds, err := c.provider.Retrieve()
|
||||||
|
if err != nil {
|
||||||
|
return Value{}, err
|
||||||
|
}
|
||||||
|
c.creds = creds
|
||||||
|
c.forceRefresh = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.creds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expire expires the credentials and forces them to be retrieved on the
|
||||||
|
// next call to Get().
|
||||||
|
//
|
||||||
|
// This will override the Provider's expired state, and force Credentials
|
||||||
|
// to call the Provider's Retrieve().
|
||||||
|
func (c *Credentials) Expire() {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
|
||||||
|
c.forceRefresh = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired returns if the credentials are no longer valid, and need
|
||||||
|
// to be retrieved.
|
||||||
|
//
|
||||||
|
// If the Credentials were forced to be expired with Expire() this will
|
||||||
|
// reflect that override.
|
||||||
|
func (c *Credentials) IsExpired() bool {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
|
||||||
|
return c.isExpired()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isExpired helper method wrapping the definition of expired credentials.
|
||||||
|
func (c *Credentials) isExpired() bool {
|
||||||
|
return c.forceRefresh || c.provider.IsExpired()
|
||||||
|
}
|
168
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
generated
vendored
Normal file
168
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
generated
vendored
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
package ec2rolecreds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A EC2RoleProvider retrieves credentials from the EC2 service, and keeps track if
|
||||||
|
// those credentials are expired.
|
||||||
|
//
|
||||||
|
// Example how to configure the EC2RoleProvider with custom http Client, Endpoint
|
||||||
|
// or ExpiryWindow
|
||||||
|
//
|
||||||
|
// p := &ec2rolecreds.EC2RoleProvider{
|
||||||
|
// // Pass in a custom timeout to be used when requesting
|
||||||
|
// // IAM EC2 Role credentials.
|
||||||
|
// Client: &http.Client{
|
||||||
|
// Timeout: 10 * time.Second,
|
||||||
|
// },
|
||||||
|
// // Use default EC2 Role metadata endpoint, Alternate endpoints can be
|
||||||
|
// // specified setting Endpoint to something else.
|
||||||
|
// Endpoint: "",
|
||||||
|
// // Do not use early expiry of credentials. If a non zero value is
|
||||||
|
// // specified the credentials will be expired early
|
||||||
|
// ExpiryWindow: 0,
|
||||||
|
// }
|
||||||
|
type EC2RoleProvider struct {
|
||||||
|
credentials.Expiry
|
||||||
|
|
||||||
|
// EC2Metadata client to use when connecting to EC2 metadata service
|
||||||
|
Client *ec2metadata.Client
|
||||||
|
|
||||||
|
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
||||||
|
// the credentials actually expiring. This is beneficial so race conditions
|
||||||
|
// 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 EC2RoleProvider.
|
||||||
|
//
|
||||||
|
// Takes a custom http.Client which can be configured for custom handling of
|
||||||
|
// things such as timeout.
|
||||||
|
//
|
||||||
|
// Endpoint is the URL that the EC2RoleProvider will connect to when retrieving
|
||||||
|
// role and credentials.
|
||||||
|
//
|
||||||
|
// Window is the expiry window that will be subtracted from the expiry returned
|
||||||
|
// by the role credential request. This is done so that the credentials will
|
||||||
|
// expire sooner than their actual lifespan.
|
||||||
|
func NewCredentials(client *ec2metadata.Client, window time.Duration) *credentials.Credentials {
|
||||||
|
return credentials.NewCredentials(&EC2RoleProvider{
|
||||||
|
Client: client,
|
||||||
|
ExpiryWindow: window,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve retrieves credentials from the EC2 service.
|
||||||
|
// Error will be returned if the request fails, or unable to extract
|
||||||
|
// the desired credentials.
|
||||||
|
func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
|
||||||
|
if m.Client == nil {
|
||||||
|
m.Client = ec2metadata.New(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
credsList, err := requestCredList(m.Client)
|
||||||
|
if err != nil {
|
||||||
|
return credentials.Value{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(credsList) == 0 {
|
||||||
|
return credentials.Value{}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil)
|
||||||
|
}
|
||||||
|
credsName := credsList[0]
|
||||||
|
|
||||||
|
roleCreds, err := requestCred(m.Client, credsName)
|
||||||
|
if err != nil {
|
||||||
|
return credentials.Value{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow)
|
||||||
|
|
||||||
|
return credentials.Value{
|
||||||
|
AccessKeyID: roleCreds.AccessKeyID,
|
||||||
|
SecretAccessKey: roleCreds.SecretAccessKey,
|
||||||
|
SessionToken: roleCreds.Token,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ec2RoleCredRespBody provides the shape for deserializing credential
|
||||||
|
// request responses.
|
||||||
|
type ec2RoleCredRespBody struct {
|
||||||
|
// Success State
|
||||||
|
Expiration time.Time
|
||||||
|
AccessKeyID string
|
||||||
|
SecretAccessKey string
|
||||||
|
Token string
|
||||||
|
|
||||||
|
// Error state
|
||||||
|
Code string
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
const iamSecurityCredsPath = "/iam/security-credentials"
|
||||||
|
|
||||||
|
// requestCredList requests a list of credentials from the EC2 service.
|
||||||
|
// If there are no credentials, or there is an error making or receiving the request
|
||||||
|
func requestCredList(client *ec2metadata.Client) ([]string, error) {
|
||||||
|
resp, err := client.GetMetadata(iamSecurityCredsPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, awserr.New("EC2RoleRequestError", "failed to list EC2 Roles", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
credsList := []string{}
|
||||||
|
s := bufio.NewScanner(strings.NewReader(resp))
|
||||||
|
for s.Scan() {
|
||||||
|
credsList = append(credsList, s.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, awserr.New("SerializationError", "failed to read list of EC2 Roles", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return credsList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// requestCred requests the credentials for a specific credentials from the EC2 service.
|
||||||
|
//
|
||||||
|
// If the credentials cannot be found, or there is an error reading the response
|
||||||
|
// and error will be returned.
|
||||||
|
func requestCred(client *ec2metadata.Client, credsName string) (ec2RoleCredRespBody, error) {
|
||||||
|
resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName))
|
||||||
|
if err != nil {
|
||||||
|
return ec2RoleCredRespBody{},
|
||||||
|
awserr.New("EC2RoleRequestError",
|
||||||
|
fmt.Sprintf("failed to get %s EC2 Role credentials", credsName),
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
|
||||||
|
respCreds := ec2RoleCredRespBody{}
|
||||||
|
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil {
|
||||||
|
return ec2RoleCredRespBody{},
|
||||||
|
awserr.New("SerializationError",
|
||||||
|
fmt.Sprintf("failed to decode %s EC2 Role credentials", credsName),
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if respCreds.Code != "Success" {
|
||||||
|
// If an error code was returned something failed requesting the role.
|
||||||
|
return ec2RoleCredRespBody{}, awserr.New(respCreds.Code, respCreds.Message, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return respCreds, nil
|
||||||
|
}
|
73
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go
generated
vendored
Normal file
73
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be
|
||||||
|
// found in the process's environment.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
ErrAccessKeyIDNotFound = awserr.New("EnvAccessKeyNotFound", "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment", nil)
|
||||||
|
|
||||||
|
// ErrSecretAccessKeyNotFound is returned when the AWS Secret Access Key
|
||||||
|
// can't be found in the process's environment.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
ErrSecretAccessKeyNotFound = awserr.New("EnvSecretNotFound", "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// A EnvProvider retrieves credentials from the environment variables of the
|
||||||
|
// running process. Environment credentials never expire.
|
||||||
|
//
|
||||||
|
// Environment variables used:
|
||||||
|
//
|
||||||
|
// * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY
|
||||||
|
// * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
|
||||||
|
type EnvProvider struct {
|
||||||
|
retrieved bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEnvCredentials returns a pointer to a new Credentials object
|
||||||
|
// wrapping the environment variable provider.
|
||||||
|
func NewEnvCredentials() *Credentials {
|
||||||
|
return NewCredentials(&EnvProvider{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve retrieves the keys from the environment.
|
||||||
|
func (e *EnvProvider) Retrieve() (Value, error) {
|
||||||
|
e.retrieved = false
|
||||||
|
|
||||||
|
id := os.Getenv("AWS_ACCESS_KEY_ID")
|
||||||
|
if id == "" {
|
||||||
|
id = os.Getenv("AWS_ACCESS_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
|
secret := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||||
|
if secret == "" {
|
||||||
|
secret = os.Getenv("AWS_SECRET_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
|
if id == "" {
|
||||||
|
return Value{}, ErrAccessKeyIDNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if secret == "" {
|
||||||
|
return Value{}, ErrSecretAccessKeyNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
e.retrieved = true
|
||||||
|
return Value{
|
||||||
|
AccessKeyID: id,
|
||||||
|
SecretAccessKey: secret,
|
||||||
|
SessionToken: os.Getenv("AWS_SESSION_TOKEN"),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired returns if the credentials have been retrieved.
|
||||||
|
func (e *EnvProvider) IsExpired() bool {
|
||||||
|
return !e.retrieved
|
||||||
|
}
|
8
vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini
generated
vendored
Normal file
8
vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[default]
|
||||||
|
aws_access_key_id = accessKey
|
||||||
|
aws_secret_access_key = secret
|
||||||
|
aws_session_token = token
|
||||||
|
|
||||||
|
[no_token]
|
||||||
|
aws_access_key_id = accessKey
|
||||||
|
aws_secret_access_key = secret
|
143
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go
generated
vendored
Normal file
143
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go
generated
vendored
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/vaughan0/go-ini"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// A SharedCredentialsProvider retrieves credentials from the current user's home
|
||||||
|
// directory, and keeps track if those credentials are expired.
|
||||||
|
//
|
||||||
|
// Profile ini file example: $HOME/.aws/credentials
|
||||||
|
type SharedCredentialsProvider struct {
|
||||||
|
// Path to the shared credentials file.
|
||||||
|
//
|
||||||
|
// If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the
|
||||||
|
// env value is empty will default to current user's home directory.
|
||||||
|
// Linux/OSX: "$HOME/.aws/credentials"
|
||||||
|
// Windows: "%USERPROFILE%\.aws\credentials"
|
||||||
|
Filename string
|
||||||
|
|
||||||
|
// AWS Profile to extract credentials from the shared credentials file. If empty
|
||||||
|
// will default to environment variable "AWS_PROFILE" or "default" if
|
||||||
|
// environment variable is also not set.
|
||||||
|
Profile string
|
||||||
|
|
||||||
|
// retrieved states if the credentials have been successfully retrieved.
|
||||||
|
retrieved bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSharedCredentials returns a pointer to a new Credentials object
|
||||||
|
// wrapping the Profile file provider.
|
||||||
|
func NewSharedCredentials(filename, profile string) *Credentials {
|
||||||
|
return NewCredentials(&SharedCredentialsProvider{
|
||||||
|
Filename: filename,
|
||||||
|
Profile: profile,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve reads and extracts the shared credentials from the current
|
||||||
|
// users home directory.
|
||||||
|
func (p *SharedCredentialsProvider) Retrieve() (Value, error) {
|
||||||
|
p.retrieved = false
|
||||||
|
|
||||||
|
filename, err := p.filename()
|
||||||
|
if err != nil {
|
||||||
|
return Value{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := loadProfile(filename, p.profile())
|
||||||
|
if err != nil {
|
||||||
|
return Value{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.retrieved = true
|
||||||
|
return creds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired returns if the shared credentials have expired.
|
||||||
|
func (p *SharedCredentialsProvider) IsExpired() bool {
|
||||||
|
return !p.retrieved
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadProfiles loads from the file pointed to by shared credentials filename for profile.
|
||||||
|
// The credentials retrieved from the profile will be returned or error. Error will be
|
||||||
|
// returned if it fails to read from the file, or the data is invalid.
|
||||||
|
func loadProfile(filename, profile string) (Value, error) {
|
||||||
|
config, err := ini.LoadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return Value{}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err)
|
||||||
|
}
|
||||||
|
iniProfile := config.Section(profile)
|
||||||
|
|
||||||
|
id, ok := iniProfile["aws_access_key_id"]
|
||||||
|
if !ok {
|
||||||
|
return Value{}, awserr.New("SharedCredsAccessKey",
|
||||||
|
fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename),
|
||||||
|
nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, ok := iniProfile["aws_secret_access_key"]
|
||||||
|
if !ok {
|
||||||
|
return Value{}, awserr.New("SharedCredsSecret",
|
||||||
|
fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename),
|
||||||
|
nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
token := iniProfile["aws_session_token"]
|
||||||
|
|
||||||
|
return Value{
|
||||||
|
AccessKeyID: id,
|
||||||
|
SecretAccessKey: secret,
|
||||||
|
SessionToken: token,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// filename returns the filename to use to read AWS shared credentials.
|
||||||
|
//
|
||||||
|
// Will return an error if the user's home directory path cannot be found.
|
||||||
|
func (p *SharedCredentialsProvider) filename() (string, error) {
|
||||||
|
if p.Filename == "" {
|
||||||
|
if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); p.Filename != "" {
|
||||||
|
return p.Filename, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
homeDir := os.Getenv("HOME") // *nix
|
||||||
|
if homeDir == "" { // Windows
|
||||||
|
homeDir = os.Getenv("USERPROFILE")
|
||||||
|
}
|
||||||
|
if homeDir == "" {
|
||||||
|
return "", ErrSharedCredentialsHomeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Filename = filepath.Join(homeDir, ".aws", "credentials")
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.Filename, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// profile returns the AWS shared credentials profile. If empty will read
|
||||||
|
// environment variable "AWS_PROFILE". If that is not set profile will
|
||||||
|
// return "default".
|
||||||
|
func (p *SharedCredentialsProvider) profile() string {
|
||||||
|
if p.Profile == "" {
|
||||||
|
p.Profile = os.Getenv("AWS_PROFILE")
|
||||||
|
}
|
||||||
|
if p.Profile == "" {
|
||||||
|
p.Profile = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.Profile
|
||||||
|
}
|
44
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go
generated
vendored
Normal file
44
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrStaticCredentialsEmpty is emitted when static credentials are empty.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
ErrStaticCredentialsEmpty = awserr.New("EmptyStaticCreds", "static credentials are empty", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// A StaticProvider is a set of credentials which are set pragmatically,
|
||||||
|
// and will never expire.
|
||||||
|
type StaticProvider struct {
|
||||||
|
Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStaticCredentials returns a pointer to a new Credentials object
|
||||||
|
// wrapping a static credentials value provider.
|
||||||
|
func NewStaticCredentials(id, secret, token string) *Credentials {
|
||||||
|
return NewCredentials(&StaticProvider{Value: Value{
|
||||||
|
AccessKeyID: id,
|
||||||
|
SecretAccessKey: secret,
|
||||||
|
SessionToken: token,
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve returns the credentials or error if the credentials are invalid.
|
||||||
|
func (s *StaticProvider) Retrieve() (Value, error) {
|
||||||
|
if s.AccessKeyID == "" || s.SecretAccessKey == "" {
|
||||||
|
return Value{}, ErrStaticCredentialsEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired returns if the credentials are expired.
|
||||||
|
//
|
||||||
|
// For StaticProvider, the credentials never expired.
|
||||||
|
func (s *StaticProvider) IsExpired() bool {
|
||||||
|
return false
|
||||||
|
}
|
39
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
Normal file
39
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package defaults
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultChainCredentials is a Credentials which will find the first available
|
||||||
|
// credentials Value from the list of Providers.
|
||||||
|
//
|
||||||
|
// This should be used in the default case. Once the type of credentials are
|
||||||
|
// known switching to the specific Credentials will be more efficient.
|
||||||
|
var DefaultChainCredentials = credentials.NewChainCredentials(
|
||||||
|
[]credentials.Provider{
|
||||||
|
&credentials.EnvProvider{},
|
||||||
|
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
|
||||||
|
&ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
|
||||||
|
})
|
||||||
|
|
||||||
|
// DefaultConfig is the default all service configuration will be based off of.
|
||||||
|
// By default, all clients use this structure for initialization options unless
|
||||||
|
// a custom configuration object is passed in.
|
||||||
|
//
|
||||||
|
// You may modify this global structure to change all default configuration
|
||||||
|
// in the SDK. Note that configuration options are copied by value, so any
|
||||||
|
// modifications must happen before constructing a client.
|
||||||
|
var DefaultConfig = aws.NewConfig().
|
||||||
|
WithCredentials(DefaultChainCredentials).
|
||||||
|
WithRegion(os.Getenv("AWS_REGION")).
|
||||||
|
WithHTTPClient(http.DefaultClient).
|
||||||
|
WithMaxRetries(aws.DefaultRetries).
|
||||||
|
WithLogger(aws.NewDefaultLogger()).
|
||||||
|
WithLogLevel(aws.LogOff).
|
||||||
|
WithSleepDelay(time.Sleep)
|
43
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
generated
vendored
Normal file
43
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package ec2metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetMetadata uses the path provided to request
|
||||||
|
func (c *Client) GetMetadata(p string) (string, error) {
|
||||||
|
op := &request.Operation{
|
||||||
|
Name: "GetMetadata",
|
||||||
|
HTTPMethod: "GET",
|
||||||
|
HTTPPath: path.Join("/", "meta-data", p),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := &metadataOutput{}
|
||||||
|
req := request.New(c.Service.ServiceInfo, c.Service.Handlers, c.Service.Retryer, op, nil, output)
|
||||||
|
|
||||||
|
return output.Content, req.Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Region returns the region the instance is running in.
|
||||||
|
func (c *Client) Region() (string, error) {
|
||||||
|
resp, err := c.GetMetadata("placement/availability-zone")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns region without the suffix. Eg: us-west-2a becomes us-west-2
|
||||||
|
return resp[:len(resp)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Available returns if the application has access to the EC2 Metadata service.
|
||||||
|
// Can be used to determine if application is running within an EC2 Instance and
|
||||||
|
// the metadata service is available.
|
||||||
|
func (c *Client) Available() bool {
|
||||||
|
if _, err := c.GetMetadata("instance-id"); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
135
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
generated
vendored
Normal file
135
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
generated
vendored
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package ec2metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/service"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultRetries states the default number of times the service client will
|
||||||
|
// attempt to retry a failed request before failing.
|
||||||
|
const DefaultRetries = 3
|
||||||
|
|
||||||
|
// A Config provides the configuration for the EC2 Metadata service.
|
||||||
|
type Config struct {
|
||||||
|
// An optional endpoint URL (hostname only or fully qualified URI)
|
||||||
|
// that overrides the default service endpoint for a client. Set this
|
||||||
|
// to nil, or `""` to use the default service endpoint.
|
||||||
|
Endpoint *string
|
||||||
|
|
||||||
|
// The HTTP client to use when sending requests. Defaults to
|
||||||
|
// `http.DefaultClient`.
|
||||||
|
HTTPClient *http.Client
|
||||||
|
|
||||||
|
// An integer value representing the logging level. The default log level
|
||||||
|
// is zero (LogOff), which represents no logging. To enable logging set
|
||||||
|
// to a LogLevel Value.
|
||||||
|
Logger aws.Logger
|
||||||
|
|
||||||
|
// The logger writer interface to write logging messages to. Defaults to
|
||||||
|
// standard out.
|
||||||
|
LogLevel *aws.LogLevelType
|
||||||
|
|
||||||
|
// The maximum number of times that a request will be retried for failures.
|
||||||
|
// Defaults to DefaultRetries for the number of retries to be performed
|
||||||
|
// per request.
|
||||||
|
MaxRetries *int
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Client is an EC2 Metadata service Client.
|
||||||
|
type Client struct {
|
||||||
|
*service.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new instance of the EC2 Metadata service client.
|
||||||
|
//
|
||||||
|
// In the general use case the configuration for this service client should not
|
||||||
|
// be needed and `nil` can be provided. Configuration is only needed if the
|
||||||
|
// `ec2metadata.Config` defaults need to be overridden. Eg. Setting LogLevel.
|
||||||
|
//
|
||||||
|
// @note This configuration will NOT be merged with the default AWS service
|
||||||
|
// client configuration `defaults.DefaultConfig`. Due to circular dependencies
|
||||||
|
// with the defaults package and credentials EC2 Role Provider.
|
||||||
|
func New(config *Config) *Client {
|
||||||
|
service := &service.Service{
|
||||||
|
ServiceInfo: serviceinfo.ServiceInfo{
|
||||||
|
Config: copyConfig(config),
|
||||||
|
ServiceName: "Client",
|
||||||
|
Endpoint: "http://169.254.169.254/latest",
|
||||||
|
APIVersion: "latest",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
service.Initialize()
|
||||||
|
service.Handlers.Unmarshal.PushBack(unmarshalHandler)
|
||||||
|
service.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||||
|
service.Handlers.Validate.Clear()
|
||||||
|
service.Handlers.Validate.PushBack(validateEndpointHandler)
|
||||||
|
|
||||||
|
return &Client{service}
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyConfig(config *Config) *aws.Config {
|
||||||
|
if config == nil {
|
||||||
|
config = &Config{}
|
||||||
|
}
|
||||||
|
c := &aws.Config{
|
||||||
|
Credentials: credentials.AnonymousCredentials,
|
||||||
|
Endpoint: config.Endpoint,
|
||||||
|
HTTPClient: config.HTTPClient,
|
||||||
|
Logger: config.Logger,
|
||||||
|
LogLevel: config.LogLevel,
|
||||||
|
MaxRetries: config.MaxRetries,
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.HTTPClient == nil {
|
||||||
|
c.HTTPClient = http.DefaultClient
|
||||||
|
}
|
||||||
|
if c.Logger == nil {
|
||||||
|
c.Logger = aws.NewDefaultLogger()
|
||||||
|
}
|
||||||
|
if c.LogLevel == nil {
|
||||||
|
c.LogLevel = aws.LogLevel(aws.LogOff)
|
||||||
|
}
|
||||||
|
if c.MaxRetries == nil {
|
||||||
|
c.MaxRetries = aws.Int(DefaultRetries)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
type metadataOutput struct {
|
||||||
|
Content string
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalHandler(r *request.Request) {
|
||||||
|
defer r.HTTPResponse.Body.Close()
|
||||||
|
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := r.Data.(*metadataOutput)
|
||||||
|
data.Content = string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalError(r *request.Request) {
|
||||||
|
defer r.HTTPResponse.Body.Close()
|
||||||
|
_, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO extract the error...
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateEndpointHandler(r *request.Request) {
|
||||||
|
if r.Service.Endpoint == "" {
|
||||||
|
r.Error = aws.ErrMissingEndpoint
|
||||||
|
}
|
||||||
|
}
|
17
vendor/github.com/aws/aws-sdk-go/aws/errors.go
generated
vendored
Normal file
17
vendor/github.com/aws/aws-sdk-go/aws/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import "github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrMissingRegion is an error that is returned if region configuration is
|
||||||
|
// not found.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
ErrMissingRegion error = awserr.New("MissingRegion", "could not find region configuration", nil)
|
||||||
|
|
||||||
|
// ErrMissingEndpoint is an error that is returned if an endpoint cannot be
|
||||||
|
// resolved for a service.
|
||||||
|
//
|
||||||
|
// @readonly
|
||||||
|
ErrMissingEndpoint error = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil)
|
||||||
|
)
|
98
vendor/github.com/aws/aws-sdk-go/aws/logger.go
generated
vendored
Normal file
98
vendor/github.com/aws/aws-sdk-go/aws/logger.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A LogLevelType defines the level logging should be performed at. Used to instruct
|
||||||
|
// the SDK which statements should be logged.
|
||||||
|
type LogLevelType uint
|
||||||
|
|
||||||
|
// LogLevel returns the pointer to a LogLevel. Should be used to workaround
|
||||||
|
// not being able to take the address of a non-composite literal.
|
||||||
|
func LogLevel(l LogLevelType) *LogLevelType {
|
||||||
|
return &l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the LogLevel value or the default value LogOff if the LogLevel
|
||||||
|
// is nil. Safe to use on nil value LogLevelTypes.
|
||||||
|
func (l *LogLevelType) Value() LogLevelType {
|
||||||
|
if l != nil {
|
||||||
|
return *l
|
||||||
|
}
|
||||||
|
return LogOff
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches returns true if the v LogLevel is enabled by this LogLevel. Should be
|
||||||
|
// used with logging sub levels. Is safe to use on nil value LogLevelTypes. If
|
||||||
|
// LogLevel is nill, will default to LogOff comparison.
|
||||||
|
func (l *LogLevelType) Matches(v LogLevelType) bool {
|
||||||
|
c := l.Value()
|
||||||
|
return c&v == v
|
||||||
|
}
|
||||||
|
|
||||||
|
// AtLeast returns true if this LogLevel is at least high enough to satisfies v.
|
||||||
|
// Is safe to use on nil value LogLevelTypes. If LogLevel is nill, will default
|
||||||
|
// to LogOff comparison.
|
||||||
|
func (l *LogLevelType) AtLeast(v LogLevelType) bool {
|
||||||
|
c := l.Value()
|
||||||
|
return c >= v
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LogOff states that no logging should be performed by the SDK. This is the
|
||||||
|
// default state of the SDK, and should be use to disable all logging.
|
||||||
|
LogOff LogLevelType = iota * 0x1000
|
||||||
|
|
||||||
|
// LogDebug state that debug output should be logged by the SDK. This should
|
||||||
|
// be used to inspect request made and responses received.
|
||||||
|
LogDebug
|
||||||
|
)
|
||||||
|
|
||||||
|
// Debug Logging Sub Levels
|
||||||
|
const (
|
||||||
|
// LogDebugWithSigning states that the SDK should log request signing and
|
||||||
|
// presigning events. This should be used to log the signing details of
|
||||||
|
// requests for debugging. Will also enable LogDebug.
|
||||||
|
LogDebugWithSigning LogLevelType = LogDebug | (1 << iota)
|
||||||
|
|
||||||
|
// LogDebugWithHTTPBody states the SDK should log HTTP request and response
|
||||||
|
// HTTP bodys in addition to the headers and path. This should be used to
|
||||||
|
// see the body content of requests and responses made while using the SDK
|
||||||
|
// Will also enable LogDebug.
|
||||||
|
LogDebugWithHTTPBody
|
||||||
|
|
||||||
|
// LogDebugWithRequestRetries states the SDK should log when service requests will
|
||||||
|
// be retried. This should be used to log when you want to log when service
|
||||||
|
// requests are being retried. Will also enable LogDebug.
|
||||||
|
LogDebugWithRequestRetries
|
||||||
|
|
||||||
|
// LogDebugWithRequestErrors states the SDK should log when service requests fail
|
||||||
|
// to build, send, validate, or unmarshal.
|
||||||
|
LogDebugWithRequestErrors
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Logger is a minimalistic interface for the SDK to log messages to. Should
|
||||||
|
// be used to provide custom logging writers for the SDK to use.
|
||||||
|
type Logger interface {
|
||||||
|
Log(...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDefaultLogger returns a Logger which will write log messages to stdout, and
|
||||||
|
// use same formatting runes as the stdlib log.Logger
|
||||||
|
func NewDefaultLogger() Logger {
|
||||||
|
return &defaultLogger{
|
||||||
|
logger: log.New(os.Stdout, "", log.LstdFlags),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A defaultLogger provides a minimalistic logger satisfying the Logger interface.
|
||||||
|
type defaultLogger struct {
|
||||||
|
logger *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log logs the parameters to the stdlib logger. See log.Println.
|
||||||
|
func (l defaultLogger) Log(args ...interface{}) {
|
||||||
|
l.logger.Println(args...)
|
||||||
|
}
|
112
vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
generated
vendored
Normal file
112
vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package request
|
||||||
|
|
||||||
|
// A Handlers provides a collection of request handlers for various
|
||||||
|
// stages of handling requests.
|
||||||
|
type Handlers struct {
|
||||||
|
Validate HandlerList
|
||||||
|
Build HandlerList
|
||||||
|
Sign HandlerList
|
||||||
|
Send HandlerList
|
||||||
|
ValidateResponse HandlerList
|
||||||
|
Unmarshal HandlerList
|
||||||
|
UnmarshalMeta HandlerList
|
||||||
|
UnmarshalError HandlerList
|
||||||
|
Retry HandlerList
|
||||||
|
AfterRetry HandlerList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns of this handler's lists.
|
||||||
|
func (h *Handlers) Copy() Handlers {
|
||||||
|
return Handlers{
|
||||||
|
Validate: h.Validate.copy(),
|
||||||
|
Build: h.Build.copy(),
|
||||||
|
Sign: h.Sign.copy(),
|
||||||
|
Send: h.Send.copy(),
|
||||||
|
ValidateResponse: h.ValidateResponse.copy(),
|
||||||
|
Unmarshal: h.Unmarshal.copy(),
|
||||||
|
UnmarshalError: h.UnmarshalError.copy(),
|
||||||
|
UnmarshalMeta: h.UnmarshalMeta.copy(),
|
||||||
|
Retry: h.Retry.copy(),
|
||||||
|
AfterRetry: h.AfterRetry.copy(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes callback functions for all handlers
|
||||||
|
func (h *Handlers) Clear() {
|
||||||
|
h.Validate.Clear()
|
||||||
|
h.Build.Clear()
|
||||||
|
h.Send.Clear()
|
||||||
|
h.Sign.Clear()
|
||||||
|
h.Unmarshal.Clear()
|
||||||
|
h.UnmarshalMeta.Clear()
|
||||||
|
h.UnmarshalError.Clear()
|
||||||
|
h.ValidateResponse.Clear()
|
||||||
|
h.Retry.Clear()
|
||||||
|
h.AfterRetry.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A HandlerList manages zero or more handlers in a list.
|
||||||
|
type HandlerList struct {
|
||||||
|
list []NamedHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// A NamedHandler is a struct that contains a name and function callback.
|
||||||
|
type NamedHandler struct {
|
||||||
|
Name string
|
||||||
|
Fn func(*Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy creates a copy of the handler list.
|
||||||
|
func (l *HandlerList) copy() HandlerList {
|
||||||
|
var n HandlerList
|
||||||
|
n.list = append([]NamedHandler{}, l.list...)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears the handler list.
|
||||||
|
func (l *HandlerList) Clear() {
|
||||||
|
l.list = []NamedHandler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of handlers in the list.
|
||||||
|
func (l *HandlerList) Len() int {
|
||||||
|
return len(l.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushBack pushes handler f to the back of the handler list.
|
||||||
|
func (l *HandlerList) PushBack(f func(*Request)) {
|
||||||
|
l.list = append(l.list, NamedHandler{"__anonymous", f})
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushFront pushes handler f to the front of the handler list.
|
||||||
|
func (l *HandlerList) PushFront(f func(*Request)) {
|
||||||
|
l.list = append([]NamedHandler{{"__anonymous", f}}, l.list...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushBackNamed pushes named handler f to the back of the handler list.
|
||||||
|
func (l *HandlerList) PushBackNamed(n NamedHandler) {
|
||||||
|
l.list = append(l.list, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushFrontNamed pushes named handler f to the front of the handler list.
|
||||||
|
func (l *HandlerList) PushFrontNamed(n NamedHandler) {
|
||||||
|
l.list = append([]NamedHandler{n}, l.list...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes a NamedHandler n
|
||||||
|
func (l *HandlerList) Remove(n NamedHandler) {
|
||||||
|
newlist := []NamedHandler{}
|
||||||
|
for _, m := range l.list {
|
||||||
|
if m.Name != n.Name {
|
||||||
|
newlist = append(newlist, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l.list = newlist
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes all handlers in the list with a given request object.
|
||||||
|
func (l *HandlerList) Run(r *Request) {
|
||||||
|
for _, f := range l.list {
|
||||||
|
f.Fn(r)
|
||||||
|
}
|
||||||
|
}
|
348
vendor/github.com/aws/aws-sdk-go/aws/request/request.go
generated
vendored
Normal file
348
vendor/github.com/aws/aws-sdk-go/aws/request/request.go
generated
vendored
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
package request
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Request is the service request to be made.
|
||||||
|
type Request struct {
|
||||||
|
Retryer
|
||||||
|
Service serviceinfo.ServiceInfo
|
||||||
|
Handlers Handlers
|
||||||
|
Time time.Time
|
||||||
|
ExpireTime time.Duration
|
||||||
|
Operation *Operation
|
||||||
|
HTTPRequest *http.Request
|
||||||
|
HTTPResponse *http.Response
|
||||||
|
Body io.ReadSeeker
|
||||||
|
BodyStart int64 // offset from beginning of Body that the request body starts
|
||||||
|
Params interface{}
|
||||||
|
Error error
|
||||||
|
Data interface{}
|
||||||
|
RequestID string
|
||||||
|
RetryCount uint
|
||||||
|
Retryable *bool
|
||||||
|
RetryDelay time.Duration
|
||||||
|
|
||||||
|
built bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Operation is the service API operation to be made.
|
||||||
|
type Operation struct {
|
||||||
|
Name string
|
||||||
|
HTTPMethod string
|
||||||
|
HTTPPath string
|
||||||
|
*Paginator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paginator keeps track of pagination configuration for an API operation.
|
||||||
|
type Paginator struct {
|
||||||
|
InputTokens []string
|
||||||
|
OutputTokens []string
|
||||||
|
LimitToken string
|
||||||
|
TruncationToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new Request pointer for the service API
|
||||||
|
// operation and parameters.
|
||||||
|
//
|
||||||
|
// Params is any value of input parameters to be the request payload.
|
||||||
|
// Data is pointer value to an object which the request's response
|
||||||
|
// payload will be deserialized to.
|
||||||
|
func New(service serviceinfo.ServiceInfo, handlers Handlers, retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request {
|
||||||
|
method := operation.HTTPMethod
|
||||||
|
if method == "" {
|
||||||
|
method = "POST"
|
||||||
|
}
|
||||||
|
p := operation.HTTPPath
|
||||||
|
if p == "" {
|
||||||
|
p = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
httpReq, _ := http.NewRequest(method, "", nil)
|
||||||
|
httpReq.URL, _ = url.Parse(service.Endpoint + p)
|
||||||
|
|
||||||
|
r := &Request{
|
||||||
|
Retryer: retryer,
|
||||||
|
Service: service,
|
||||||
|
Handlers: handlers.Copy(),
|
||||||
|
Time: time.Now(),
|
||||||
|
ExpireTime: 0,
|
||||||
|
Operation: operation,
|
||||||
|
HTTPRequest: httpReq,
|
||||||
|
Body: nil,
|
||||||
|
Params: params,
|
||||||
|
Error: nil,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
r.SetBufferBody([]byte{})
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// WillRetry returns if the request's can be retried.
|
||||||
|
func (r *Request) WillRetry() bool {
|
||||||
|
return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParamsFilled returns if the request's parameters have been populated
|
||||||
|
// and the parameters are valid. False is returned if no parameters are
|
||||||
|
// provided or invalid.
|
||||||
|
func (r *Request) ParamsFilled() bool {
|
||||||
|
return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataFilled returns true if the request's data for response deserialization
|
||||||
|
// target has been set and is a valid. False is returned if data is not
|
||||||
|
// set, or is invalid.
|
||||||
|
func (r *Request) DataFilled() bool {
|
||||||
|
return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBufferBody will set the request's body bytes that will be sent to
|
||||||
|
// the service API.
|
||||||
|
func (r *Request) SetBufferBody(buf []byte) {
|
||||||
|
r.SetReaderBody(bytes.NewReader(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStringBody sets the body of the request to be backed by a string.
|
||||||
|
func (r *Request) SetStringBody(s string) {
|
||||||
|
r.SetReaderBody(strings.NewReader(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReaderBody will set the request's body reader.
|
||||||
|
func (r *Request) SetReaderBody(reader io.ReadSeeker) {
|
||||||
|
r.HTTPRequest.Body = ioutil.NopCloser(reader)
|
||||||
|
r.Body = reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Presign returns the request's signed URL. Error will be returned
|
||||||
|
// if the signing fails.
|
||||||
|
func (r *Request) Presign(expireTime time.Duration) (string, error) {
|
||||||
|
r.ExpireTime = expireTime
|
||||||
|
r.Sign()
|
||||||
|
if r.Error != nil {
|
||||||
|
return "", r.Error
|
||||||
|
}
|
||||||
|
return r.HTTPRequest.URL.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func debugLogReqError(r *Request, stage string, retrying bool, err error) {
|
||||||
|
if !r.Service.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
retryStr := "not retrying"
|
||||||
|
if retrying {
|
||||||
|
retryStr = "will retry"
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Service.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v",
|
||||||
|
stage, r.Service.ServiceName, r.Operation.Name, retryStr, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build will build the request's object so it can be signed and sent
|
||||||
|
// to the service. Build will also validate all the request's parameters.
|
||||||
|
// Anny additional build Handlers set on this request will be run
|
||||||
|
// in the order they were set.
|
||||||
|
//
|
||||||
|
// The request will only be built once. Multiple calls to build will have
|
||||||
|
// no effect.
|
||||||
|
//
|
||||||
|
// If any Validate or Build errors occur the build will stop and the error
|
||||||
|
// which occurred will be returned.
|
||||||
|
func (r *Request) Build() error {
|
||||||
|
if !r.built {
|
||||||
|
r.Error = nil
|
||||||
|
r.Handlers.Validate.Run(r)
|
||||||
|
if r.Error != nil {
|
||||||
|
debugLogReqError(r, "Validate Request", false, r.Error)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
r.Handlers.Build.Run(r)
|
||||||
|
r.built = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign will sign the request retuning error if errors are encountered.
|
||||||
|
//
|
||||||
|
// Send will build the request prior to signing. All Sign Handlers will
|
||||||
|
// be executed in the order they were set.
|
||||||
|
func (r *Request) Sign() error {
|
||||||
|
r.Build()
|
||||||
|
if r.Error != nil {
|
||||||
|
debugLogReqError(r, "Build Request", false, r.Error)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Handlers.Sign.Run(r)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send will send the request returning error if errors are encountered.
|
||||||
|
//
|
||||||
|
// Send will sign the request prior to sending. All Send Handlers will
|
||||||
|
// be executed in the order they were set.
|
||||||
|
func (r *Request) Send() error {
|
||||||
|
for {
|
||||||
|
r.Sign()
|
||||||
|
if r.Error != nil {
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if aws.BoolValue(r.Retryable) {
|
||||||
|
if r.Service.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
|
||||||
|
r.Service.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
|
||||||
|
r.Service.ServiceName, r.Operation.Name, r.RetryCount))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-seek the body back to the original point in for a retry so that
|
||||||
|
// send will send the body's contents again in the upcoming request.
|
||||||
|
r.Body.Seek(r.BodyStart, 0)
|
||||||
|
r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
|
||||||
|
}
|
||||||
|
r.Retryable = nil
|
||||||
|
|
||||||
|
r.Handlers.Send.Run(r)
|
||||||
|
if r.Error != nil {
|
||||||
|
err := r.Error
|
||||||
|
r.Handlers.Retry.Run(r)
|
||||||
|
r.Handlers.AfterRetry.Run(r)
|
||||||
|
if r.Error != nil {
|
||||||
|
debugLogReqError(r, "Send Request", false, r.Error)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
debugLogReqError(r, "Send Request", true, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Handlers.UnmarshalMeta.Run(r)
|
||||||
|
r.Handlers.ValidateResponse.Run(r)
|
||||||
|
if r.Error != nil {
|
||||||
|
err := r.Error
|
||||||
|
r.Handlers.UnmarshalError.Run(r)
|
||||||
|
r.Handlers.Retry.Run(r)
|
||||||
|
r.Handlers.AfterRetry.Run(r)
|
||||||
|
if r.Error != nil {
|
||||||
|
debugLogReqError(r, "Validate Response", false, r.Error)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
debugLogReqError(r, "Validate Response", true, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Handlers.Unmarshal.Run(r)
|
||||||
|
if r.Error != nil {
|
||||||
|
err := r.Error
|
||||||
|
r.Handlers.Retry.Run(r)
|
||||||
|
r.Handlers.AfterRetry.Run(r)
|
||||||
|
if r.Error != nil {
|
||||||
|
debugLogReqError(r, "Unmarshal Response", false, r.Error)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
debugLogReqError(r, "Unmarshal Response", true, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasNextPage returns true if this request has more pages of data available.
|
||||||
|
func (r *Request) HasNextPage() bool {
|
||||||
|
return r.nextPageTokens() != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// nextPageTokens returns the tokens to use when asking for the next page of
|
||||||
|
// data.
|
||||||
|
func (r *Request) nextPageTokens() []interface{} {
|
||||||
|
if r.Operation.Paginator == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Operation.TruncationToken != "" {
|
||||||
|
tr := awsutil.ValuesAtAnyPath(r.Data, r.Operation.TruncationToken)
|
||||||
|
if tr == nil || len(tr) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch v := tr[0].(type) {
|
||||||
|
case bool:
|
||||||
|
if v == false {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
tokens := make([]interface{}, len(r.Operation.OutputTokens))
|
||||||
|
|
||||||
|
for i, outtok := range r.Operation.OutputTokens {
|
||||||
|
v := awsutil.ValuesAtAnyPath(r.Data, outtok)
|
||||||
|
if v != nil && len(v) > 0 {
|
||||||
|
found = true
|
||||||
|
tokens[i] = v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found {
|
||||||
|
return tokens
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPage returns a new Request that can be executed to return the next
|
||||||
|
// page of result data. Call .Send() on this request to execute it.
|
||||||
|
func (r *Request) NextPage() *Request {
|
||||||
|
tokens := r.nextPageTokens()
|
||||||
|
if tokens == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface()
|
||||||
|
nr := New(r.Service, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data)
|
||||||
|
for i, intok := range nr.Operation.InputTokens {
|
||||||
|
awsutil.SetValueAtAnyPath(nr.Params, intok, tokens[i])
|
||||||
|
}
|
||||||
|
return nr
|
||||||
|
}
|
||||||
|
|
||||||
|
// EachPage iterates over each page of a paginated request object. The fn
|
||||||
|
// parameter should be a function with the following sample signature:
|
||||||
|
//
|
||||||
|
// func(page *T, lastPage bool) bool {
|
||||||
|
// return true // return false to stop iterating
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Where "T" is the structure type matching the output structure of the given
|
||||||
|
// operation. For example, a request object generated by
|
||||||
|
// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput
|
||||||
|
// as the structure "T". The lastPage value represents whether the page is
|
||||||
|
// the last page of data or not. The return value of this function should
|
||||||
|
// return true to keep iterating or false to stop.
|
||||||
|
func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
|
||||||
|
for page := r; page != nil; page = page.NextPage() {
|
||||||
|
page.Send()
|
||||||
|
shouldContinue := fn(page.Data, !page.HasNextPage())
|
||||||
|
if page.Error != nil || !shouldContinue {
|
||||||
|
return page.Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
71
vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
generated
vendored
Normal file
71
vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package request
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Retryer is an interface to control retry logic for a given service.
|
||||||
|
// The default implementation used by most services is the service.DefaultRetryer
|
||||||
|
// structure, which contains basic retry logic using exponential backoff.
|
||||||
|
type Retryer interface {
|
||||||
|
RetryRules(*Request) time.Duration
|
||||||
|
ShouldRetry(*Request) bool
|
||||||
|
MaxRetries() uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// retryableCodes is a collection of service response codes which are retry-able
|
||||||
|
// without any further action.
|
||||||
|
var retryableCodes = map[string]struct{}{
|
||||||
|
"RequestError": {},
|
||||||
|
"ProvisionedThroughputExceededException": {},
|
||||||
|
"Throttling": {},
|
||||||
|
"ThrottlingException": {},
|
||||||
|
"RequestLimitExceeded": {},
|
||||||
|
"RequestThrottled": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// credsExpiredCodes is a collection of error codes which signify the credentials
|
||||||
|
// need to be refreshed. Expired tokens require refreshing of credentials, and
|
||||||
|
// resigning before the request can be retried.
|
||||||
|
var credsExpiredCodes = map[string]struct{}{
|
||||||
|
"ExpiredToken": {},
|
||||||
|
"ExpiredTokenException": {},
|
||||||
|
"RequestExpired": {}, // EC2 Only
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCodeRetryable(code string) bool {
|
||||||
|
if _, ok := retryableCodes[code]; ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCodeExpiredCreds(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCodeExpiredCreds(code string) bool {
|
||||||
|
_, ok := credsExpiredCodes[code]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrorRetryable returns whether the error is retryable, based on its Code.
|
||||||
|
// Returns false if the request has no Error set.
|
||||||
|
func (r *Request) IsErrorRetryable() bool {
|
||||||
|
if r.Error != nil {
|
||||||
|
if err, ok := r.Error.(awserr.Error); ok {
|
||||||
|
return isCodeRetryable(err.Code())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrorExpired returns whether the error code is a credential expiry error.
|
||||||
|
// Returns false if the request has no Error set.
|
||||||
|
func (r *Request) IsErrorExpired() bool {
|
||||||
|
if r.Error != nil {
|
||||||
|
if err, ok := r.Error.(awserr.Error); ok {
|
||||||
|
return isCodeExpiredCreds(err.Code())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
51
vendor/github.com/aws/aws-sdk-go/aws/service/default_retryer.go
generated
vendored
Normal file
51
vendor/github.com/aws/aws-sdk-go/aws/service/default_retryer.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultRetryer implements basic retry logic using exponential backoff for
|
||||||
|
// most services. If you want to implement custom retry logic, implement the
|
||||||
|
// request.Retryer interface or create a structure type that composes this
|
||||||
|
// struct and override the specific methods. For example, to override only
|
||||||
|
// the MaxRetries method:
|
||||||
|
//
|
||||||
|
// type retryer struct {
|
||||||
|
// service.DefaultRetryer
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // This implementation always has 100 max retries
|
||||||
|
// func (d retryer) MaxRetries() uint { return 100 }
|
||||||
|
type DefaultRetryer struct {
|
||||||
|
*Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxRetries returns the number of maximum returns the service will use to make
|
||||||
|
// an individual API request.
|
||||||
|
func (d DefaultRetryer) MaxRetries() uint {
|
||||||
|
if aws.IntValue(d.Service.Config.MaxRetries) < 0 {
|
||||||
|
return d.DefaultMaxRetries
|
||||||
|
}
|
||||||
|
return uint(aws.IntValue(d.Service.Config.MaxRetries))
|
||||||
|
}
|
||||||
|
|
||||||
|
var seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
|
// RetryRules returns the delay duration before retrying this request again
|
||||||
|
func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
|
||||||
|
delay := int(math.Pow(2, float64(r.RetryCount))) * (seededRand.Intn(30) + 30)
|
||||||
|
return time.Duration(delay) * time.Millisecond
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShouldRetry returns if the request should be retried.
|
||||||
|
func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
|
||||||
|
if r.HTTPResponse.StatusCode >= 500 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return r.IsErrorRetryable()
|
||||||
|
}
|
133
vendor/github.com/aws/aws-sdk-go/aws/service/service.go
generated
vendored
Normal file
133
vendor/github.com/aws/aws-sdk-go/aws/service/service.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"regexp"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||||
|
"github.com/aws/aws-sdk-go/internal/endpoints"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Service implements the base service request and response handling
|
||||||
|
// used by all services.
|
||||||
|
type Service struct {
|
||||||
|
serviceinfo.ServiceInfo
|
||||||
|
request.Retryer
|
||||||
|
DefaultMaxRetries uint
|
||||||
|
Handlers request.Handlers
|
||||||
|
}
|
||||||
|
|
||||||
|
var schemeRE = regexp.MustCompile("^([^:]+)://")
|
||||||
|
|
||||||
|
// New will return a pointer to a new Server object initialized.
|
||||||
|
func New(config *aws.Config) *Service {
|
||||||
|
svc := &Service{ServiceInfo: serviceinfo.ServiceInfo{Config: config}}
|
||||||
|
svc.Initialize()
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize initializes the service.
|
||||||
|
func (s *Service) Initialize() {
|
||||||
|
if s.Config == nil {
|
||||||
|
s.Config = &aws.Config{}
|
||||||
|
}
|
||||||
|
if s.Config.HTTPClient == nil {
|
||||||
|
s.Config.HTTPClient = http.DefaultClient
|
||||||
|
}
|
||||||
|
if s.Config.SleepDelay == nil {
|
||||||
|
s.Config.SleepDelay = time.Sleep
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Retryer = DefaultRetryer{s}
|
||||||
|
s.DefaultMaxRetries = 3
|
||||||
|
s.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
|
||||||
|
s.Handlers.Build.PushBackNamed(corehandlers.UserAgentHandler)
|
||||||
|
s.Handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
|
||||||
|
s.Handlers.Send.PushBackNamed(corehandlers.SendHandler)
|
||||||
|
s.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
|
||||||
|
s.Handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
|
||||||
|
if !aws.BoolValue(s.Config.DisableParamValidation) {
|
||||||
|
s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
|
||||||
|
}
|
||||||
|
s.AddDebugHandlers()
|
||||||
|
s.buildEndpoint()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest returns a new Request pointer for the service API
|
||||||
|
// operation and parameters.
|
||||||
|
func (s *Service) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
|
||||||
|
return request.New(s.ServiceInfo, s.Handlers, s.Retryer, operation, params, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildEndpoint builds the endpoint values the service will use to make requests with.
|
||||||
|
func (s *Service) buildEndpoint() {
|
||||||
|
if aws.StringValue(s.Config.Endpoint) != "" {
|
||||||
|
s.Endpoint = *s.Config.Endpoint
|
||||||
|
} else if s.Endpoint == "" {
|
||||||
|
s.Endpoint, s.SigningRegion =
|
||||||
|
endpoints.EndpointForRegion(s.ServiceName, aws.StringValue(s.Config.Region))
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Endpoint != "" && !schemeRE.MatchString(s.Endpoint) {
|
||||||
|
scheme := "https"
|
||||||
|
if aws.BoolValue(s.Config.DisableSSL) {
|
||||||
|
scheme = "http"
|
||||||
|
}
|
||||||
|
s.Endpoint = scheme + "://" + s.Endpoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDebugHandlers injects debug logging handlers into the service to log request
|
||||||
|
// debug information.
|
||||||
|
func (s *Service) AddDebugHandlers() {
|
||||||
|
if !s.Config.LogLevel.AtLeast(aws.LogDebug) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Handlers.Send.PushFront(logRequest)
|
||||||
|
s.Handlers.Send.PushBack(logResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
const logReqMsg = `DEBUG: Request %s/%s Details:
|
||||||
|
---[ REQUEST POST-SIGN ]-----------------------------
|
||||||
|
%s
|
||||||
|
-----------------------------------------------------`
|
||||||
|
|
||||||
|
func logRequest(r *request.Request) {
|
||||||
|
logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||||
|
dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
|
||||||
|
|
||||||
|
if logBody {
|
||||||
|
// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
|
||||||
|
// Body as a NoOpCloser and will not be reset after read by the HTTP
|
||||||
|
// client reader.
|
||||||
|
r.Body.Seek(r.BodyStart, 0)
|
||||||
|
r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Service.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.Service.ServiceName, r.Operation.Name, string(dumpedBody)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const logRespMsg = `DEBUG: Response %s/%s Details:
|
||||||
|
---[ RESPONSE ]--------------------------------------
|
||||||
|
%s
|
||||||
|
-----------------------------------------------------`
|
||||||
|
|
||||||
|
func logResponse(r *request.Request) {
|
||||||
|
var msg = "no reponse data"
|
||||||
|
if r.HTTPResponse != nil {
|
||||||
|
logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||||
|
dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
|
||||||
|
msg = string(dumpedBody)
|
||||||
|
} else if r.Error != nil {
|
||||||
|
msg = r.Error.Error()
|
||||||
|
}
|
||||||
|
r.Service.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.Service.ServiceName, r.Operation.Name, msg))
|
||||||
|
}
|
15
vendor/github.com/aws/aws-sdk-go/aws/service/serviceinfo/service_info.go
generated
vendored
Normal file
15
vendor/github.com/aws/aws-sdk-go/aws/service/serviceinfo/service_info.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package serviceinfo
|
||||||
|
|
||||||
|
import "github.com/aws/aws-sdk-go/aws"
|
||||||
|
|
||||||
|
// ServiceInfo wraps immutable data from the service.Service structure.
|
||||||
|
type ServiceInfo struct {
|
||||||
|
Config *aws.Config
|
||||||
|
ServiceName string
|
||||||
|
APIVersion string
|
||||||
|
Endpoint string
|
||||||
|
SigningName string
|
||||||
|
SigningRegion string
|
||||||
|
JSONVersion string
|
||||||
|
TargetPrefix string
|
||||||
|
}
|
88
vendor/github.com/aws/aws-sdk-go/aws/types.go
generated
vendored
Normal file
88
vendor/github.com/aws/aws-sdk-go/aws/types.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadSeekCloser wraps a io.Reader returning a ReaderSeakerCloser
|
||||||
|
func ReadSeekCloser(r io.Reader) ReaderSeekerCloser {
|
||||||
|
return ReaderSeekerCloser{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReaderSeekerCloser represents a reader that can also delegate io.Seeker and
|
||||||
|
// io.Closer interfaces to the underlying object if they are available.
|
||||||
|
type ReaderSeekerCloser struct {
|
||||||
|
r io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads from the reader up to size of p. The number of bytes read, and
|
||||||
|
// error if it occurred will be returned.
|
||||||
|
//
|
||||||
|
// If the reader is not an io.Reader zero bytes read, and nil error will be returned.
|
||||||
|
//
|
||||||
|
// Performs the same functionality as io.Reader Read
|
||||||
|
func (r ReaderSeekerCloser) Read(p []byte) (int, error) {
|
||||||
|
switch t := r.r.(type) {
|
||||||
|
case io.Reader:
|
||||||
|
return t.Read(p)
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek sets the offset for the next Read to offset, interpreted according to
|
||||||
|
// whence: 0 means relative to the origin of the file, 1 means relative to the
|
||||||
|
// current offset, and 2 means relative to the end. Seek returns the new offset
|
||||||
|
// and an error, if any.
|
||||||
|
//
|
||||||
|
// If the ReaderSeekerCloser is not an io.Seeker nothing will be done.
|
||||||
|
func (r ReaderSeekerCloser) Seek(offset int64, whence int) (int64, error) {
|
||||||
|
switch t := r.r.(type) {
|
||||||
|
case io.Seeker:
|
||||||
|
return t.Seek(offset, whence)
|
||||||
|
}
|
||||||
|
return int64(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the ReaderSeekerCloser.
|
||||||
|
//
|
||||||
|
// If the ReaderSeekerCloser is not an io.Closer nothing will be done.
|
||||||
|
func (r ReaderSeekerCloser) Close() error {
|
||||||
|
switch t := r.r.(type) {
|
||||||
|
case io.Closer:
|
||||||
|
return t.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A WriteAtBuffer provides a in memory buffer supporting the io.WriterAt interface
|
||||||
|
// Can be used with the s3manager.Downloader to download content to a buffer
|
||||||
|
// in memory. Safe to use concurrently.
|
||||||
|
type WriteAtBuffer struct {
|
||||||
|
buf []byte
|
||||||
|
m sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteAt writes a slice of bytes to a buffer starting at the position provided
|
||||||
|
// The number of bytes written will be returned, or error. Can overwrite previous
|
||||||
|
// written slices if the write ats overlap.
|
||||||
|
func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) {
|
||||||
|
b.m.Lock()
|
||||||
|
defer b.m.Unlock()
|
||||||
|
|
||||||
|
expLen := pos + int64(len(p))
|
||||||
|
if int64(len(b.buf)) < expLen {
|
||||||
|
newBuf := make([]byte, expLen)
|
||||||
|
copy(newBuf, b.buf)
|
||||||
|
b.buf = newBuf
|
||||||
|
}
|
||||||
|
copy(b.buf[pos:], p)
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns a slice of bytes written to the buffer.
|
||||||
|
func (b *WriteAtBuffer) Bytes() []byte {
|
||||||
|
b.m.Lock()
|
||||||
|
defer b.m.Unlock()
|
||||||
|
return b.buf[:len(b.buf):len(b.buf)]
|
||||||
|
}
|
8
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
Normal file
8
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// Package aws provides core functionality for making requests to AWS services.
|
||||||
|
package aws
|
||||||
|
|
||||||
|
// SDKName is the name of this AWS SDK
|
||||||
|
const SDKName = "aws-sdk-go"
|
||||||
|
|
||||||
|
// SDKVersion is the version of this SDK
|
||||||
|
const SDKVersion = "0.9.1rc2"
|
31
vendor/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.go
generated
vendored
Normal file
31
vendor/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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 "strings"
|
||||||
|
|
||||||
|
// 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) (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
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
77
vendor/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.json
generated
vendored
Normal file
77
vendor/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.json
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"endpoints": {
|
||||||
|
"*/*": {
|
||||||
|
"endpoint": "{service}.{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"cn-north-1/*": {
|
||||||
|
"endpoint": "{service}.{region}.amazonaws.com.cn",
|
||||||
|
"signatureVersion": "v4"
|
||||||
|
},
|
||||||
|
"us-gov-west-1/iam": {
|
||||||
|
"endpoint": "iam.us-gov.amazonaws.com"
|
||||||
|
},
|
||||||
|
"us-gov-west-1/sts": {
|
||||||
|
"endpoint": "sts.us-gov-west-1.amazonaws.com"
|
||||||
|
},
|
||||||
|
"us-gov-west-1/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"*/cloudfront": {
|
||||||
|
"endpoint": "cloudfront.amazonaws.com",
|
||||||
|
"signingRegion": "us-east-1"
|
||||||
|
},
|
||||||
|
"*/cloudsearchdomain": {
|
||||||
|
"endpoint": "",
|
||||||
|
"signingRegion": "us-east-1"
|
||||||
|
},
|
||||||
|
"*/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"
|
||||||
|
},
|
||||||
|
"*/sts": {
|
||||||
|
"endpoint": "sts.amazonaws.com",
|
||||||
|
"signingRegion": "us-east-1"
|
||||||
|
},
|
||||||
|
"us-east-1/sdb": {
|
||||||
|
"endpoint": "sdb.amazonaws.com",
|
||||||
|
"signingRegion": "us-east-1"
|
||||||
|
},
|
||||||
|
"us-east-1/s3": {
|
||||||
|
"endpoint": "s3.amazonaws.com"
|
||||||
|
},
|
||||||
|
"us-west-1/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"us-west-2/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"eu-west-1/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"ap-southeast-1/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"ap-southeast-2/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"ap-northeast-1/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"sa-east-1/s3": {
|
||||||
|
"endpoint": "s3-{region}.amazonaws.com"
|
||||||
|
},
|
||||||
|
"eu-central-1/s3": {
|
||||||
|
"endpoint": "{service}.{region}.amazonaws.com",
|
||||||
|
"signatureVersion": "v4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
vendor/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_map.go
generated
vendored
Normal file
89
vendor/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_map.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
"*/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",
|
||||||
|
},
|
||||||
|
"*/sts": {
|
||||||
|
Endpoint: "sts.amazonaws.com",
|
||||||
|
SigningRegion: "us-east-1",
|
||||||
|
},
|
||||||
|
"ap-northeast-1/s3": {
|
||||||
|
Endpoint: "s3-{region}.amazonaws.com",
|
||||||
|
},
|
||||||
|
"ap-southeast-1/s3": {
|
||||||
|
Endpoint: "s3-{region}.amazonaws.com",
|
||||||
|
},
|
||||||
|
"ap-southeast-2/s3": {
|
||||||
|
Endpoint: "s3-{region}.amazonaws.com",
|
||||||
|
},
|
||||||
|
"cn-north-1/*": {
|
||||||
|
Endpoint: "{service}.{region}.amazonaws.com.cn",
|
||||||
|
},
|
||||||
|
"eu-central-1/s3": {
|
||||||
|
Endpoint: "{service}.{region}.amazonaws.com",
|
||||||
|
},
|
||||||
|
"eu-west-1/s3": {
|
||||||
|
Endpoint: "s3-{region}.amazonaws.com",
|
||||||
|
},
|
||||||
|
"sa-east-1/s3": {
|
||||||
|
Endpoint: "s3-{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/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",
|
||||||
|
},
|
||||||
|
"us-west-1/s3": {
|
||||||
|
Endpoint: "s3-{region}.amazonaws.com",
|
||||||
|
},
|
||||||
|
"us-west-2/s3": {
|
||||||
|
Endpoint: "s3-{region}.amazonaws.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
32
vendor/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build.go
generated
vendored
Normal file
32
vendor/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// Package ec2query provides serialisation of AWS EC2 requests and responses.
|
||||||
|
package ec2query
|
||||||
|
|
||||||
|
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/ec2.json build_test.go
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/internal/protocol/query/queryutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Build builds a request for the EC2 protocol.
|
||||||
|
func Build(r *request.Request) {
|
||||||
|
body := url.Values{
|
||||||
|
"Action": {r.Operation.Name},
|
||||||
|
"Version": {r.Service.APIVersion},
|
||||||
|
}
|
||||||
|
if err := queryutil.Parse(body, r.Params, true); err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.ExpireTime == 0 {
|
||||||
|
r.HTTPRequest.Method = "POST"
|
||||||
|
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
|
||||||
|
r.SetBufferBody([]byte(body.Encode()))
|
||||||
|
} else { // This is a pre-signed request
|
||||||
|
r.HTTPRequest.Method = "GET"
|
||||||
|
r.HTTPRequest.URL.RawQuery = body.Encode()
|
||||||
|
}
|
||||||
|
}
|
54
vendor/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal.go
generated
vendored
Normal file
54
vendor/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package ec2query
|
||||||
|
|
||||||
|
//go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/ec2.json unmarshal_test.go
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Unmarshal unmarshals a response body for the EC2 protocol.
|
||||||
|
func Unmarshal(r *request.Request) {
|
||||||
|
defer r.HTTPResponse.Body.Close()
|
||||||
|
if r.DataFilled() {
|
||||||
|
decoder := xml.NewDecoder(r.HTTPResponse.Body)
|
||||||
|
err := xmlutil.UnmarshalXML(r.Data, decoder, "")
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed decoding EC2 Query response", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalMeta unmarshals response headers for the EC2 protocol.
|
||||||
|
func UnmarshalMeta(r *request.Request) {
|
||||||
|
// TODO implement unmarshaling of request IDs
|
||||||
|
}
|
||||||
|
|
||||||
|
type xmlErrorResponse struct {
|
||||||
|
XMLName xml.Name `xml:"Response"`
|
||||||
|
Code string `xml:"Errors>Error>Code"`
|
||||||
|
Message string `xml:"Errors>Error>Message"`
|
||||||
|
RequestID string `xml:"RequestId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalError unmarshals a response error for the EC2 protocol.
|
||||||
|
func UnmarshalError(r *request.Request) {
|
||||||
|
defer r.HTTPResponse.Body.Close()
|
||||||
|
|
||||||
|
resp := &xmlErrorResponse{}
|
||||||
|
err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed decoding EC2 Query error response", err)
|
||||||
|
} else {
|
||||||
|
r.Error = awserr.NewRequestFailure(
|
||||||
|
awserr.New(resp.Code, resp.Message, nil),
|
||||||
|
r.HTTPResponse.StatusCode,
|
||||||
|
resp.RequestID,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
223
vendor/github.com/aws/aws-sdk-go/internal/protocol/query/queryutil/queryutil.go
generated
vendored
Normal file
223
vendor/github.com/aws/aws-sdk-go/internal/protocol/query/queryutil/queryutil.go
generated
vendored
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
package queryutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Parse parses an object i and fills a url.Values object. The isEC2 flag
|
||||||
|
// indicates if this is the EC2 Query sub-protocol.
|
||||||
|
func Parse(body url.Values, i interface{}, isEC2 bool) error {
|
||||||
|
q := queryParser{isEC2: isEC2}
|
||||||
|
return q.parseValue(body, reflect.ValueOf(i), "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func elemOf(value reflect.Value) reflect.Value {
|
||||||
|
for value.Kind() == reflect.Ptr {
|
||||||
|
value = value.Elem()
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryParser struct {
|
||||||
|
isEC2 bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryParser) parseValue(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
|
||||||
|
value = elemOf(value)
|
||||||
|
|
||||||
|
// no need to handle zero values
|
||||||
|
if !value.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t := tag.Get("type")
|
||||||
|
if t == "" {
|
||||||
|
switch value.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
t = "structure"
|
||||||
|
case reflect.Slice:
|
||||||
|
t = "list"
|
||||||
|
case reflect.Map:
|
||||||
|
t = "map"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t {
|
||||||
|
case "structure":
|
||||||
|
return q.parseStruct(v, value, prefix)
|
||||||
|
case "list":
|
||||||
|
return q.parseList(v, value, prefix, tag)
|
||||||
|
case "map":
|
||||||
|
return q.parseMap(v, value, prefix, tag)
|
||||||
|
default:
|
||||||
|
return q.parseScalar(v, value, prefix, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix string) error {
|
||||||
|
if !value.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t := value.Type()
|
||||||
|
for i := 0; i < value.NumField(); i++ {
|
||||||
|
if c := t.Field(i).Name[0:1]; strings.ToLower(c) == c {
|
||||||
|
continue // ignore unexported fields
|
||||||
|
}
|
||||||
|
|
||||||
|
value := elemOf(value.Field(i))
|
||||||
|
field := t.Field(i)
|
||||||
|
var name string
|
||||||
|
|
||||||
|
if q.isEC2 {
|
||||||
|
name = field.Tag.Get("queryName")
|
||||||
|
}
|
||||||
|
if name == "" {
|
||||||
|
if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" {
|
||||||
|
name = field.Tag.Get("locationNameList")
|
||||||
|
} else if locName := field.Tag.Get("locationName"); locName != "" {
|
||||||
|
name = locName
|
||||||
|
}
|
||||||
|
if name != "" && q.isEC2 {
|
||||||
|
name = strings.ToUpper(name[0:1]) + name[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if name == "" {
|
||||||
|
name = field.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if prefix != "" {
|
||||||
|
name = prefix + "." + name
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.parseValue(v, value, name, field.Tag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
|
||||||
|
// If it's empty, generate an empty value
|
||||||
|
if !value.IsNil() && value.Len() == 0 {
|
||||||
|
v.Set(prefix, "")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for unflattened list member
|
||||||
|
if !q.isEC2 && tag.Get("flattened") == "" {
|
||||||
|
prefix += ".member"
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < value.Len(); i++ {
|
||||||
|
slicePrefix := prefix
|
||||||
|
if slicePrefix == "" {
|
||||||
|
slicePrefix = strconv.Itoa(i + 1)
|
||||||
|
} else {
|
||||||
|
slicePrefix = slicePrefix + "." + strconv.Itoa(i+1)
|
||||||
|
}
|
||||||
|
if err := q.parseValue(v, value.Index(i), slicePrefix, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryParser) parseMap(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
|
||||||
|
// If it's empty, generate an empty value
|
||||||
|
if !value.IsNil() && value.Len() == 0 {
|
||||||
|
v.Set(prefix, "")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for unflattened list member
|
||||||
|
if !q.isEC2 && tag.Get("flattened") == "" {
|
||||||
|
prefix += ".entry"
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort keys for improved serialization consistency.
|
||||||
|
// this is not strictly necessary for protocol support.
|
||||||
|
mapKeyValues := value.MapKeys()
|
||||||
|
mapKeys := map[string]reflect.Value{}
|
||||||
|
mapKeyNames := make([]string, len(mapKeyValues))
|
||||||
|
for i, mapKey := range mapKeyValues {
|
||||||
|
name := mapKey.String()
|
||||||
|
mapKeys[name] = mapKey
|
||||||
|
mapKeyNames[i] = name
|
||||||
|
}
|
||||||
|
sort.Strings(mapKeyNames)
|
||||||
|
|
||||||
|
for i, mapKeyName := range mapKeyNames {
|
||||||
|
mapKey := mapKeys[mapKeyName]
|
||||||
|
mapValue := value.MapIndex(mapKey)
|
||||||
|
|
||||||
|
kname := tag.Get("locationNameKey")
|
||||||
|
if kname == "" {
|
||||||
|
kname = "key"
|
||||||
|
}
|
||||||
|
vname := tag.Get("locationNameValue")
|
||||||
|
if vname == "" {
|
||||||
|
vname = "value"
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize key
|
||||||
|
var keyName string
|
||||||
|
if prefix == "" {
|
||||||
|
keyName = strconv.Itoa(i+1) + "." + kname
|
||||||
|
} else {
|
||||||
|
keyName = prefix + "." + strconv.Itoa(i+1) + "." + kname
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.parseValue(v, mapKey, keyName, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize value
|
||||||
|
var valueName string
|
||||||
|
if prefix == "" {
|
||||||
|
valueName = strconv.Itoa(i+1) + "." + vname
|
||||||
|
} else {
|
||||||
|
valueName = prefix + "." + strconv.Itoa(i+1) + "." + vname
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.parseValue(v, mapValue, valueName, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryParser) parseScalar(v url.Values, r reflect.Value, name string, tag reflect.StructTag) error {
|
||||||
|
switch value := r.Interface().(type) {
|
||||||
|
case string:
|
||||||
|
v.Set(name, value)
|
||||||
|
case []byte:
|
||||||
|
if !r.IsNil() {
|
||||||
|
v.Set(name, base64.StdEncoding.EncodeToString(value))
|
||||||
|
}
|
||||||
|
case bool:
|
||||||
|
v.Set(name, strconv.FormatBool(value))
|
||||||
|
case int64:
|
||||||
|
v.Set(name, strconv.FormatInt(value, 10))
|
||||||
|
case int:
|
||||||
|
v.Set(name, strconv.Itoa(value))
|
||||||
|
case float64:
|
||||||
|
v.Set(name, strconv.FormatFloat(value, 'f', -1, 64))
|
||||||
|
case float32:
|
||||||
|
v.Set(name, strconv.FormatFloat(float64(value), 'f', -1, 32))
|
||||||
|
case time.Time:
|
||||||
|
const ISO8601UTC = "2006-01-02T15:04:05Z"
|
||||||
|
v.Set(name, value.UTC().Format(ISO8601UTC))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported value for param %s: %v (%s)", name, r.Interface(), r.Type().Name())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
217
vendor/github.com/aws/aws-sdk-go/internal/protocol/rest/build.go
generated
vendored
Normal file
217
vendor/github.com/aws/aws-sdk-go/internal/protocol/rest/build.go
generated
vendored
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
// Package rest provides RESTful serialization of AWS requests and responses.
|
||||||
|
package rest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RFC822 returns an RFC822 formatted timestamp for AWS protocols
|
||||||
|
const RFC822 = "Mon, 2 Jan 2006 15:04:05 GMT"
|
||||||
|
|
||||||
|
// Whether the byte value can be sent without escaping in AWS URLs
|
||||||
|
var noEscape [256]bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for i := 0; i < len(noEscape); i++ {
|
||||||
|
// AWS expects every character except these to be escaped
|
||||||
|
noEscape[i] = (i >= 'A' && i <= 'Z') ||
|
||||||
|
(i >= 'a' && i <= 'z') ||
|
||||||
|
(i >= '0' && i <= '9') ||
|
||||||
|
i == '-' ||
|
||||||
|
i == '.' ||
|
||||||
|
i == '_' ||
|
||||||
|
i == '~'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build builds the REST component of a service request.
|
||||||
|
func Build(r *request.Request) {
|
||||||
|
if r.ParamsFilled() {
|
||||||
|
v := reflect.ValueOf(r.Params).Elem()
|
||||||
|
buildLocationElements(r, v)
|
||||||
|
buildBody(r, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildLocationElements(r *request.Request, v reflect.Value) {
|
||||||
|
query := r.HTTPRequest.URL.Query()
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
m := v.Field(i)
|
||||||
|
if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.IsValid() {
|
||||||
|
field := v.Type().Field(i)
|
||||||
|
name := field.Tag.Get("locationName")
|
||||||
|
if name == "" {
|
||||||
|
name = field.Name
|
||||||
|
}
|
||||||
|
if m.Kind() == reflect.Ptr {
|
||||||
|
m = m.Elem()
|
||||||
|
}
|
||||||
|
if !m.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch field.Tag.Get("location") {
|
||||||
|
case "headers": // header maps
|
||||||
|
buildHeaderMap(r, m, field.Tag.Get("locationName"))
|
||||||
|
case "header":
|
||||||
|
buildHeader(r, m, name)
|
||||||
|
case "uri":
|
||||||
|
buildURI(r, m, name)
|
||||||
|
case "querystring":
|
||||||
|
buildQueryString(r, m, name, query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.Error != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.HTTPRequest.URL.RawQuery = query.Encode()
|
||||||
|
updatePath(r.HTTPRequest.URL, r.HTTPRequest.URL.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildBody(r *request.Request, v reflect.Value) {
|
||||||
|
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
||||||
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
|
pfield, _ := v.Type().FieldByName(payloadName)
|
||||||
|
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
|
||||||
|
payload := reflect.Indirect(v.FieldByName(payloadName))
|
||||||
|
if payload.IsValid() && payload.Interface() != nil {
|
||||||
|
switch reader := payload.Interface().(type) {
|
||||||
|
case io.ReadSeeker:
|
||||||
|
r.SetReaderBody(reader)
|
||||||
|
case []byte:
|
||||||
|
r.SetBufferBody(reader)
|
||||||
|
case string:
|
||||||
|
r.SetStringBody(reader)
|
||||||
|
default:
|
||||||
|
r.Error = awserr.New("SerializationError",
|
||||||
|
"failed to encode REST request",
|
||||||
|
fmt.Errorf("unknown payload type %s", payload.Type()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHeader(r *request.Request, v reflect.Value, name string) {
|
||||||
|
str, err := convertType(v)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to encode REST request", err)
|
||||||
|
} else if str != nil {
|
||||||
|
r.HTTPRequest.Header.Add(name, *str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHeaderMap(r *request.Request, v reflect.Value, prefix string) {
|
||||||
|
for _, key := range v.MapKeys() {
|
||||||
|
str, err := convertType(v.MapIndex(key))
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to encode REST request", err)
|
||||||
|
} else if str != nil {
|
||||||
|
r.HTTPRequest.Header.Add(prefix+key.String(), *str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildURI(r *request.Request, v reflect.Value, name string) {
|
||||||
|
value, err := convertType(v)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to encode REST request", err)
|
||||||
|
} else if value != nil {
|
||||||
|
uri := r.HTTPRequest.URL.Path
|
||||||
|
uri = strings.Replace(uri, "{"+name+"}", EscapePath(*value, true), -1)
|
||||||
|
uri = strings.Replace(uri, "{"+name+"+}", EscapePath(*value, false), -1)
|
||||||
|
r.HTTPRequest.URL.Path = uri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildQueryString(r *request.Request, v reflect.Value, name string, query url.Values) {
|
||||||
|
str, err := convertType(v)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to encode REST request", err)
|
||||||
|
} else if str != nil {
|
||||||
|
query.Set(name, *str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePath(url *url.URL, urlPath string) {
|
||||||
|
scheme, query := url.Scheme, url.RawQuery
|
||||||
|
|
||||||
|
hasSlash := strings.HasSuffix(urlPath, "/")
|
||||||
|
|
||||||
|
// clean up path
|
||||||
|
urlPath = path.Clean(urlPath)
|
||||||
|
if hasSlash && !strings.HasSuffix(urlPath, "/") {
|
||||||
|
urlPath += "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
// get formatted URL minus scheme so we can build this into Opaque
|
||||||
|
url.Scheme, url.Path, url.RawQuery = "", "", ""
|
||||||
|
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
|
||||||
|
func EscapePath(path string, encodeSep bool) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for i := 0; i < len(path); i++ {
|
||||||
|
c := path[i]
|
||||||
|
if noEscape[c] || (c == '/' && !encodeSep) {
|
||||||
|
buf.WriteByte(c)
|
||||||
|
} else {
|
||||||
|
buf.WriteByte('%')
|
||||||
|
buf.WriteString(strings.ToUpper(strconv.FormatUint(uint64(c), 16)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertType(v reflect.Value) (*string, error) {
|
||||||
|
v = reflect.Indirect(v)
|
||||||
|
if !v.IsValid() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var str string
|
||||||
|
switch value := v.Interface().(type) {
|
||||||
|
case string:
|
||||||
|
str = value
|
||||||
|
case []byte:
|
||||||
|
str = base64.StdEncoding.EncodeToString(value)
|
||||||
|
case bool:
|
||||||
|
str = strconv.FormatBool(value)
|
||||||
|
case int64:
|
||||||
|
str = strconv.FormatInt(value, 10)
|
||||||
|
case float64:
|
||||||
|
str = strconv.FormatFloat(value, 'f', -1, 64)
|
||||||
|
case time.Time:
|
||||||
|
str = value.UTC().Format(RFC822)
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &str, nil
|
||||||
|
}
|
45
vendor/github.com/aws/aws-sdk-go/internal/protocol/rest/payload.go
generated
vendored
Normal file
45
vendor/github.com/aws/aws-sdk-go/internal/protocol/rest/payload.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
package rest
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
// PayloadMember returns the payload field member of i if there is one, or nil.
|
||||||
|
func PayloadMember(i interface{}) interface{} {
|
||||||
|
if i == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.ValueOf(i).Elem()
|
||||||
|
if !v.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
||||||
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
|
field, _ := v.Type().FieldByName(payloadName)
|
||||||
|
if field.Tag.Get("type") != "structure" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := v.FieldByName(payloadName)
|
||||||
|
if payload.IsValid() || (payload.Kind() == reflect.Ptr && !payload.IsNil()) {
|
||||||
|
return payload.Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PayloadType returns the type of a payload field member of i if there is one, or "".
|
||||||
|
func PayloadType(i interface{}) string {
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(i))
|
||||||
|
if !v.IsValid() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
||||||
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
|
if member, ok := v.Type().FieldByName(payloadName); ok {
|
||||||
|
return member.Tag.Get("type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
175
vendor/github.com/aws/aws-sdk-go/internal/protocol/rest/unmarshal.go
generated
vendored
Normal file
175
vendor/github.com/aws/aws-sdk-go/internal/protocol/rest/unmarshal.go
generated
vendored
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
package rest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Unmarshal unmarshals the REST component of a response in a REST service.
|
||||||
|
func Unmarshal(r *request.Request) {
|
||||||
|
if r.DataFilled() {
|
||||||
|
v := reflect.Indirect(reflect.ValueOf(r.Data))
|
||||||
|
unmarshalBody(r, v)
|
||||||
|
unmarshalLocationElements(r, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalBody(r *request.Request, v reflect.Value) {
|
||||||
|
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
||||||
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
|
pfield, _ := v.Type().FieldByName(payloadName)
|
||||||
|
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
|
||||||
|
payload := v.FieldByName(payloadName)
|
||||||
|
if payload.IsValid() {
|
||||||
|
switch payload.Interface().(type) {
|
||||||
|
case []byte:
|
||||||
|
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to decode REST response", err)
|
||||||
|
} else {
|
||||||
|
payload.Set(reflect.ValueOf(b))
|
||||||
|
}
|
||||||
|
case *string:
|
||||||
|
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to decode REST response", err)
|
||||||
|
} else {
|
||||||
|
str := string(b)
|
||||||
|
payload.Set(reflect.ValueOf(&str))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
switch payload.Type().String() {
|
||||||
|
case "io.ReadSeeker":
|
||||||
|
payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body)))
|
||||||
|
case "aws.ReadSeekCloser", "io.ReadCloser":
|
||||||
|
payload.Set(reflect.ValueOf(r.HTTPResponse.Body))
|
||||||
|
default:
|
||||||
|
r.Error = awserr.New("SerializationError",
|
||||||
|
"failed to decode REST response",
|
||||||
|
fmt.Errorf("unknown payload type %s", payload.Type()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalLocationElements(r *request.Request, v reflect.Value) {
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
m, field := v.Field(i), v.Type().Field(i)
|
||||||
|
if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.IsValid() {
|
||||||
|
name := field.Tag.Get("locationName")
|
||||||
|
if name == "" {
|
||||||
|
name = field.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
switch field.Tag.Get("location") {
|
||||||
|
case "statusCode":
|
||||||
|
unmarshalStatusCode(m, r.HTTPResponse.StatusCode)
|
||||||
|
case "header":
|
||||||
|
err := unmarshalHeader(m, r.HTTPResponse.Header.Get(name))
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to decode REST response", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "headers":
|
||||||
|
prefix := field.Tag.Get("locationName")
|
||||||
|
err := unmarshalHeaderMap(m, r.HTTPResponse.Header, prefix)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError", "failed to decode REST response", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.Error != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalStatusCode(v reflect.Value, statusCode int) {
|
||||||
|
if !v.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.Interface().(type) {
|
||||||
|
case *int64:
|
||||||
|
s := int64(statusCode)
|
||||||
|
v.Set(reflect.ValueOf(&s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalHeaderMap(r reflect.Value, headers http.Header, prefix string) error {
|
||||||
|
switch r.Interface().(type) {
|
||||||
|
case map[string]*string: // we only support string map value types
|
||||||
|
out := map[string]*string{}
|
||||||
|
for k, v := range headers {
|
||||||
|
k = http.CanonicalHeaderKey(k)
|
||||||
|
if strings.HasPrefix(strings.ToLower(k), strings.ToLower(prefix)) {
|
||||||
|
out[k[len(prefix):]] = &v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.Set(reflect.ValueOf(out))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalHeader(v reflect.Value, header string) error {
|
||||||
|
if !v.IsValid() || (header == "" && v.Elem().Kind() != reflect.String) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.Interface().(type) {
|
||||||
|
case *string:
|
||||||
|
v.Set(reflect.ValueOf(&header))
|
||||||
|
case []byte:
|
||||||
|
b, err := base64.StdEncoding.DecodeString(header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Set(reflect.ValueOf(&b))
|
||||||
|
case *bool:
|
||||||
|
b, err := strconv.ParseBool(header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Set(reflect.ValueOf(&b))
|
||||||
|
case *int64:
|
||||||
|
i, err := strconv.ParseInt(header, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Set(reflect.ValueOf(&i))
|
||||||
|
case *float64:
|
||||||
|
f, err := strconv.ParseFloat(header, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Set(reflect.ValueOf(&f))
|
||||||
|
case *time.Time:
|
||||||
|
t, err := time.Parse(RFC822, header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Set(reflect.ValueOf(&t))
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
287
vendor/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/build.go
generated
vendored
Normal file
287
vendor/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/build.go
generated
vendored
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
// Package xmlutil provides XML serialisation of AWS requests and responses.
|
||||||
|
package xmlutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BuildXML will serialize params into an xml.Encoder.
|
||||||
|
// Error will be returned if the serialization of any of the params or nested values fails.
|
||||||
|
func BuildXML(params interface{}, e *xml.Encoder) error {
|
||||||
|
b := xmlBuilder{encoder: e, namespaces: map[string]string{}}
|
||||||
|
root := NewXMLElement(xml.Name{})
|
||||||
|
if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, c := range root.Children {
|
||||||
|
for _, v := range c {
|
||||||
|
return StructToXML(e, v, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the reflection element of a value, if it is a pointer.
|
||||||
|
func elemOf(value reflect.Value) reflect.Value {
|
||||||
|
for value.Kind() == reflect.Ptr {
|
||||||
|
value = value.Elem()
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// A xmlBuilder serializes values from Go code to XML
|
||||||
|
type xmlBuilder struct {
|
||||||
|
encoder *xml.Encoder
|
||||||
|
namespaces map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildValue generic XMLNode builder for any type. Will build value for their specific type
|
||||||
|
// struct, list, map, scalar.
|
||||||
|
//
|
||||||
|
// Also takes a "type" tag value to set what type a value should be converted to XMLNode as. If
|
||||||
|
// type is not provided reflect will be used to determine the value's type.
|
||||||
|
func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||||
|
value = elemOf(value)
|
||||||
|
if !value.IsValid() { // no need to handle zero values
|
||||||
|
return nil
|
||||||
|
} else if tag.Get("location") != "" { // don't handle non-body location values
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t := tag.Get("type")
|
||||||
|
if t == "" {
|
||||||
|
switch value.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
t = "structure"
|
||||||
|
case reflect.Slice:
|
||||||
|
t = "list"
|
||||||
|
case reflect.Map:
|
||||||
|
t = "map"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t {
|
||||||
|
case "structure":
|
||||||
|
if field, ok := value.Type().FieldByName("SDKShapeTraits"); ok {
|
||||||
|
tag = tag + reflect.StructTag(" ") + field.Tag
|
||||||
|
}
|
||||||
|
return b.buildStruct(value, current, tag)
|
||||||
|
case "list":
|
||||||
|
return b.buildList(value, current, tag)
|
||||||
|
case "map":
|
||||||
|
return b.buildMap(value, current, tag)
|
||||||
|
default:
|
||||||
|
return b.buildScalar(value, current, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildStruct adds a struct and its fields to the current XMLNode. All fields any any nested
|
||||||
|
// types are converted to XMLNodes also.
|
||||||
|
func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||||
|
if !value.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldAdded := false
|
||||||
|
|
||||||
|
// unwrap payloads
|
||||||
|
if payload := tag.Get("payload"); payload != "" {
|
||||||
|
field, _ := value.Type().FieldByName(payload)
|
||||||
|
tag = field.Tag
|
||||||
|
value = elemOf(value.FieldByName(payload))
|
||||||
|
|
||||||
|
if !value.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
child := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
|
||||||
|
|
||||||
|
// there is an xmlNamespace associated with this struct
|
||||||
|
if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" {
|
||||||
|
ns := xml.Attr{
|
||||||
|
Name: xml.Name{Local: "xmlns"},
|
||||||
|
Value: uri,
|
||||||
|
}
|
||||||
|
if prefix != "" {
|
||||||
|
b.namespaces[prefix] = uri // register the namespace
|
||||||
|
ns.Name.Local = "xmlns:" + prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
child.Attr = append(child.Attr, ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := value.Type()
|
||||||
|
for i := 0; i < value.NumField(); i++ {
|
||||||
|
if c := t.Field(i).Name[0:1]; strings.ToLower(c) == c {
|
||||||
|
continue // ignore unexported fields
|
||||||
|
}
|
||||||
|
|
||||||
|
member := elemOf(value.Field(i))
|
||||||
|
field := t.Field(i)
|
||||||
|
mTag := field.Tag
|
||||||
|
|
||||||
|
if mTag.Get("location") != "" { // skip non-body members
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
memberName := mTag.Get("locationName")
|
||||||
|
if memberName == "" {
|
||||||
|
memberName = field.Name
|
||||||
|
mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`)
|
||||||
|
}
|
||||||
|
if err := b.buildValue(member, child, mTag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldAdded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldAdded { // only append this child if we have one ore more valid members
|
||||||
|
current.AddChild(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildList adds the value's list items to the current XMLNode as children nodes. All
|
||||||
|
// nested values in the list are converted to XMLNodes also.
|
||||||
|
func (b *xmlBuilder) buildList(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||||
|
if value.IsNil() { // don't build omitted lists
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for unflattened list member
|
||||||
|
flattened := tag.Get("flattened") != ""
|
||||||
|
|
||||||
|
xname := xml.Name{Local: tag.Get("locationName")}
|
||||||
|
if flattened {
|
||||||
|
for i := 0; i < value.Len(); i++ {
|
||||||
|
child := NewXMLElement(xname)
|
||||||
|
current.AddChild(child)
|
||||||
|
if err := b.buildValue(value.Index(i), child, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list := NewXMLElement(xname)
|
||||||
|
current.AddChild(list)
|
||||||
|
|
||||||
|
for i := 0; i < value.Len(); i++ {
|
||||||
|
iname := tag.Get("locationNameList")
|
||||||
|
if iname == "" {
|
||||||
|
iname = "member"
|
||||||
|
}
|
||||||
|
|
||||||
|
child := NewXMLElement(xml.Name{Local: iname})
|
||||||
|
list.AddChild(child)
|
||||||
|
if err := b.buildValue(value.Index(i), child, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildMap adds the value's key/value pairs to the current XMLNode as children nodes. All
|
||||||
|
// nested values in the map are converted to XMLNodes also.
|
||||||
|
//
|
||||||
|
// Error will be returned if it is unable to build the map's values into XMLNodes
|
||||||
|
func (b *xmlBuilder) buildMap(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||||
|
if value.IsNil() { // don't build omitted maps
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
maproot := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
|
||||||
|
current.AddChild(maproot)
|
||||||
|
current = maproot
|
||||||
|
|
||||||
|
kname, vname := "key", "value"
|
||||||
|
if n := tag.Get("locationNameKey"); n != "" {
|
||||||
|
kname = n
|
||||||
|
}
|
||||||
|
if n := tag.Get("locationNameValue"); n != "" {
|
||||||
|
vname = n
|
||||||
|
}
|
||||||
|
|
||||||
|
// sorting is not required for compliance, but it makes testing easier
|
||||||
|
keys := make([]string, value.Len())
|
||||||
|
for i, k := range value.MapKeys() {
|
||||||
|
keys[i] = k.String()
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
for _, k := range keys {
|
||||||
|
v := value.MapIndex(reflect.ValueOf(k))
|
||||||
|
|
||||||
|
mapcur := current
|
||||||
|
if tag.Get("flattened") == "" { // add "entry" tag to non-flat maps
|
||||||
|
child := NewXMLElement(xml.Name{Local: "entry"})
|
||||||
|
mapcur.AddChild(child)
|
||||||
|
mapcur = child
|
||||||
|
}
|
||||||
|
|
||||||
|
kchild := NewXMLElement(xml.Name{Local: kname})
|
||||||
|
kchild.Text = k
|
||||||
|
vchild := NewXMLElement(xml.Name{Local: vname})
|
||||||
|
mapcur.AddChild(kchild)
|
||||||
|
mapcur.AddChild(vchild)
|
||||||
|
|
||||||
|
if err := b.buildValue(v, vchild, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildScalar will convert the value into a string and append it as a attribute or child
|
||||||
|
// of the current XMLNode.
|
||||||
|
//
|
||||||
|
// The value will be added as an attribute if tag contains a "xmlAttribute" attribute value.
|
||||||
|
//
|
||||||
|
// Error will be returned if the value type is unsupported.
|
||||||
|
func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||||
|
var str string
|
||||||
|
switch converted := value.Interface().(type) {
|
||||||
|
case string:
|
||||||
|
str = converted
|
||||||
|
case []byte:
|
||||||
|
if !value.IsNil() {
|
||||||
|
str = base64.StdEncoding.EncodeToString(converted)
|
||||||
|
}
|
||||||
|
case bool:
|
||||||
|
str = strconv.FormatBool(converted)
|
||||||
|
case int64:
|
||||||
|
str = strconv.FormatInt(converted, 10)
|
||||||
|
case int:
|
||||||
|
str = strconv.Itoa(converted)
|
||||||
|
case float64:
|
||||||
|
str = strconv.FormatFloat(converted, 'f', -1, 64)
|
||||||
|
case float32:
|
||||||
|
str = strconv.FormatFloat(float64(converted), 'f', -1, 32)
|
||||||
|
case time.Time:
|
||||||
|
const ISO8601UTC = "2006-01-02T15:04:05Z"
|
||||||
|
str = converted.UTC().Format(ISO8601UTC)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported value for param %s: %v (%s)",
|
||||||
|
tag.Get("locationName"), value.Interface(), value.Type().Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
xname := xml.Name{Local: tag.Get("locationName")}
|
||||||
|
if tag.Get("xmlAttribute") != "" { // put into current node's attribute list
|
||||||
|
attr := xml.Attr{Name: xname, Value: str}
|
||||||
|
current.Attr = append(current.Attr, attr)
|
||||||
|
} else { // regular text node
|
||||||
|
current.AddChild(&XMLNode{Name: xname, Text: str})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
260
vendor/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/unmarshal.go
generated
vendored
Normal file
260
vendor/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/unmarshal.go
generated
vendored
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
package xmlutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnmarshalXML deserializes an xml.Decoder into the container v. V
|
||||||
|
// needs to match the shape of the XML expected to be decoded.
|
||||||
|
// If the shape doesn't match unmarshaling will fail.
|
||||||
|
func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error {
|
||||||
|
n, _ := XMLToStruct(d, nil)
|
||||||
|
if n.Children != nil {
|
||||||
|
for _, root := range n.Children {
|
||||||
|
for _, c := range root {
|
||||||
|
if wrappedChild, ok := c.Children[wrapper]; ok {
|
||||||
|
c = wrappedChild[0] // pull out wrapped element
|
||||||
|
}
|
||||||
|
|
||||||
|
err := parse(reflect.ValueOf(v), c, "")
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse deserializes any value from the XMLNode. The type tag is used to infer the type, or reflect
|
||||||
|
// will be used to determine the type from r.
|
||||||
|
func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||||
|
rtype := r.Type()
|
||||||
|
if rtype.Kind() == reflect.Ptr {
|
||||||
|
rtype = rtype.Elem() // check kind of actual element type
|
||||||
|
}
|
||||||
|
|
||||||
|
t := tag.Get("type")
|
||||||
|
if t == "" {
|
||||||
|
switch rtype.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
t = "structure"
|
||||||
|
case reflect.Slice:
|
||||||
|
t = "list"
|
||||||
|
case reflect.Map:
|
||||||
|
t = "map"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t {
|
||||||
|
case "structure":
|
||||||
|
if field, ok := rtype.FieldByName("SDKShapeTraits"); ok {
|
||||||
|
tag = field.Tag
|
||||||
|
}
|
||||||
|
return parseStruct(r, node, tag)
|
||||||
|
case "list":
|
||||||
|
return parseList(r, node, tag)
|
||||||
|
case "map":
|
||||||
|
return parseMap(r, node, tag)
|
||||||
|
default:
|
||||||
|
return parseScalar(r, node, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseStruct deserializes a structure and its fields from an XMLNode. Any nested
|
||||||
|
// types in the structure will also be deserialized.
|
||||||
|
func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||||
|
t := r.Type()
|
||||||
|
if r.Kind() == reflect.Ptr {
|
||||||
|
if r.IsNil() { // create the structure if it's nil
|
||||||
|
s := reflect.New(r.Type().Elem())
|
||||||
|
r.Set(s)
|
||||||
|
r = s
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.Elem()
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
// unwrap any payloads
|
||||||
|
if payload := tag.Get("payload"); payload != "" {
|
||||||
|
field, _ := t.FieldByName(payload)
|
||||||
|
return parseStruct(r.FieldByName(payload), node, field.Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
if c := field.Name[0:1]; strings.ToLower(c) == c {
|
||||||
|
continue // ignore unexported fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out what this field is called
|
||||||
|
name := field.Name
|
||||||
|
if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" {
|
||||||
|
name = field.Tag.Get("locationNameList")
|
||||||
|
} else if locName := field.Tag.Get("locationName"); locName != "" {
|
||||||
|
name = locName
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to find the field by name in elements
|
||||||
|
elems := node.Children[name]
|
||||||
|
|
||||||
|
if elems == nil { // try to find the field in attributes
|
||||||
|
for _, a := range node.Attr {
|
||||||
|
if name == a.Name.Local {
|
||||||
|
// turn this into a text node for de-serializing
|
||||||
|
elems = []*XMLNode{{Text: a.Value}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
member := r.FieldByName(field.Name)
|
||||||
|
for _, elem := range elems {
|
||||||
|
err := parse(member, elem, field.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseList deserializes a list of values from an XML node. Each list entry
|
||||||
|
// will also be deserialized.
|
||||||
|
func parseList(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||||
|
t := r.Type()
|
||||||
|
|
||||||
|
if tag.Get("flattened") == "" { // look at all item entries
|
||||||
|
mname := "member"
|
||||||
|
if name := tag.Get("locationNameList"); name != "" {
|
||||||
|
mname = name
|
||||||
|
}
|
||||||
|
|
||||||
|
if Children, ok := node.Children[mname]; ok {
|
||||||
|
if r.IsNil() {
|
||||||
|
r.Set(reflect.MakeSlice(t, len(Children), len(Children)))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range Children {
|
||||||
|
err := parse(r.Index(i), c, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // flattened list means this is a single element
|
||||||
|
if r.IsNil() {
|
||||||
|
r.Set(reflect.MakeSlice(t, 0, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
childR := reflect.Zero(t.Elem())
|
||||||
|
r.Set(reflect.Append(r, childR))
|
||||||
|
err := parse(r.Index(r.Len()-1), node, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseMap deserializes a map from an XMLNode. The direct children of the XMLNode
|
||||||
|
// will also be deserialized as map entries.
|
||||||
|
func parseMap(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||||
|
if r.IsNil() {
|
||||||
|
r.Set(reflect.MakeMap(r.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag.Get("flattened") == "" { // look at all child entries
|
||||||
|
for _, entry := range node.Children["entry"] {
|
||||||
|
parseMapEntry(r, entry, tag)
|
||||||
|
}
|
||||||
|
} else { // this element is itself an entry
|
||||||
|
parseMapEntry(r, node, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseMapEntry deserializes a map entry from a XML node.
|
||||||
|
func parseMapEntry(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||||
|
kname, vname := "key", "value"
|
||||||
|
if n := tag.Get("locationNameKey"); n != "" {
|
||||||
|
kname = n
|
||||||
|
}
|
||||||
|
if n := tag.Get("locationNameValue"); n != "" {
|
||||||
|
vname = n
|
||||||
|
}
|
||||||
|
|
||||||
|
keys, ok := node.Children[kname]
|
||||||
|
values := node.Children[vname]
|
||||||
|
if ok {
|
||||||
|
for i, key := range keys {
|
||||||
|
keyR := reflect.ValueOf(key.Text)
|
||||||
|
value := values[i]
|
||||||
|
valueR := reflect.New(r.Type().Elem()).Elem()
|
||||||
|
|
||||||
|
parse(valueR, value, "")
|
||||||
|
r.SetMapIndex(keyR, valueR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseScaller deserializes an XMLNode value into a concrete type based on the
|
||||||
|
// interface type of r.
|
||||||
|
//
|
||||||
|
// Error is returned if the deserialization fails due to invalid type conversion,
|
||||||
|
// or unsupported interface type.
|
||||||
|
func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||||
|
switch r.Interface().(type) {
|
||||||
|
case *string:
|
||||||
|
r.Set(reflect.ValueOf(&node.Text))
|
||||||
|
return nil
|
||||||
|
case []byte:
|
||||||
|
b, err := base64.StdEncoding.DecodeString(node.Text)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Set(reflect.ValueOf(b))
|
||||||
|
case *bool:
|
||||||
|
v, err := strconv.ParseBool(node.Text)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Set(reflect.ValueOf(&v))
|
||||||
|
case *int64:
|
||||||
|
v, err := strconv.ParseInt(node.Text, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Set(reflect.ValueOf(&v))
|
||||||
|
case *float64:
|
||||||
|
v, err := strconv.ParseFloat(node.Text, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Set(reflect.ValueOf(&v))
|
||||||
|
case *time.Time:
|
||||||
|
const ISO8601UTC = "2006-01-02T15:04:05Z"
|
||||||
|
t, err := time.Parse(ISO8601UTC, node.Text)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Set(reflect.ValueOf(&t))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported value: %v (%s)", r.Interface(), r.Type())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
105
vendor/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/xml_to_struct.go
generated
vendored
Normal file
105
vendor/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/xml_to_struct.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
package xmlutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"io"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A XMLNode contains the values to be encoded or decoded.
|
||||||
|
type XMLNode struct {
|
||||||
|
Name xml.Name `json:",omitempty"`
|
||||||
|
Children map[string][]*XMLNode `json:",omitempty"`
|
||||||
|
Text string `json:",omitempty"`
|
||||||
|
Attr []xml.Attr `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
|
||||||
|
func NewXMLElement(name xml.Name) *XMLNode {
|
||||||
|
return &XMLNode{
|
||||||
|
Name: name,
|
||||||
|
Children: map[string][]*XMLNode{},
|
||||||
|
Attr: []xml.Attr{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChild adds child to the XMLNode.
|
||||||
|
func (n *XMLNode) AddChild(child *XMLNode) {
|
||||||
|
if _, ok := n.Children[child.Name.Local]; !ok {
|
||||||
|
n.Children[child.Name.Local] = []*XMLNode{}
|
||||||
|
}
|
||||||
|
n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child)
|
||||||
|
}
|
||||||
|
|
||||||
|
// XMLToStruct converts a xml.Decoder stream to XMLNode with nested values.
|
||||||
|
func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
|
||||||
|
out := &XMLNode{}
|
||||||
|
for {
|
||||||
|
tok, err := d.Token()
|
||||||
|
if tok == nil || err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch typed := tok.(type) {
|
||||||
|
case xml.CharData:
|
||||||
|
out.Text = string(typed.Copy())
|
||||||
|
case xml.StartElement:
|
||||||
|
el := typed.Copy()
|
||||||
|
out.Attr = el.Attr
|
||||||
|
if out.Children == nil {
|
||||||
|
out.Children = map[string][]*XMLNode{}
|
||||||
|
}
|
||||||
|
|
||||||
|
name := typed.Name.Local
|
||||||
|
slice := out.Children[name]
|
||||||
|
if slice == nil {
|
||||||
|
slice = []*XMLNode{}
|
||||||
|
}
|
||||||
|
node, e := XMLToStruct(d, &el)
|
||||||
|
if e != nil {
|
||||||
|
return out, e
|
||||||
|
}
|
||||||
|
node.Name = typed.Name
|
||||||
|
slice = append(slice, node)
|
||||||
|
out.Children[name] = slice
|
||||||
|
case xml.EndElement:
|
||||||
|
if s != nil && s.Name.Local == typed.Name.Local { // matching end token
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StructToXML writes an XMLNode to a xml.Encoder as tokens.
|
||||||
|
func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
|
||||||
|
e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})
|
||||||
|
|
||||||
|
if node.Text != "" {
|
||||||
|
e.EncodeToken(xml.CharData([]byte(node.Text)))
|
||||||
|
} else if sorted {
|
||||||
|
sortedNames := []string{}
|
||||||
|
for k := range node.Children {
|
||||||
|
sortedNames = append(sortedNames, k)
|
||||||
|
}
|
||||||
|
sort.Strings(sortedNames)
|
||||||
|
|
||||||
|
for _, k := range sortedNames {
|
||||||
|
for _, v := range node.Children[k] {
|
||||||
|
StructToXML(e, v, sorted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, c := range node.Children {
|
||||||
|
for _, v := range c {
|
||||||
|
StructToXML(e, v, sorted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.EncodeToken(xml.EndElement{Name: node.Name})
|
||||||
|
return e.Flush()
|
||||||
|
}
|
365
vendor/github.com/aws/aws-sdk-go/internal/signer/v4/v4.go
generated
vendored
Normal file
365
vendor/github.com/aws/aws-sdk-go/internal/signer/v4/v4.go
generated
vendored
Normal file
|
@ -0,0 +1,365 @@
|
||||||
|
// Package v4 implements signing for AWS V4 signer
|
||||||
|
package v4
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/internal/protocol/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
authHeaderPrefix = "AWS4-HMAC-SHA256"
|
||||||
|
timeFormat = "20060102T150405Z"
|
||||||
|
shortTimeFormat = "20060102"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ignoredHeaders = map[string]bool{
|
||||||
|
"Authorization": true,
|
||||||
|
"Content-Type": true,
|
||||||
|
"Content-Length": true,
|
||||||
|
"User-Agent": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
type signer struct {
|
||||||
|
Request *http.Request
|
||||||
|
Time time.Time
|
||||||
|
ExpireTime time.Duration
|
||||||
|
ServiceName string
|
||||||
|
Region string
|
||||||
|
CredValues credentials.Value
|
||||||
|
Credentials *credentials.Credentials
|
||||||
|
Query url.Values
|
||||||
|
Body io.ReadSeeker
|
||||||
|
Debug aws.LogLevelType
|
||||||
|
Logger aws.Logger
|
||||||
|
|
||||||
|
isPresign bool
|
||||||
|
formattedTime string
|
||||||
|
formattedShortTime string
|
||||||
|
|
||||||
|
signedHeaders string
|
||||||
|
canonicalHeaders string
|
||||||
|
canonicalString string
|
||||||
|
credentialString string
|
||||||
|
stringToSign string
|
||||||
|
signature string
|
||||||
|
authorization string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign requests with signature version 4.
|
||||||
|
//
|
||||||
|
// Will sign the requests with the service config's Credentials object
|
||||||
|
// Signing is skipped if the credentials is the credentials.AnonymousCredentials
|
||||||
|
// object.
|
||||||
|
func Sign(req *request.Request) {
|
||||||
|
// If the request does not need to be signed ignore the signing of the
|
||||||
|
// request if the AnonymousCredentials object is used.
|
||||||
|
if req.Service.Config.Credentials == credentials.AnonymousCredentials {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
region := req.Service.SigningRegion
|
||||||
|
if region == "" {
|
||||||
|
region = aws.StringValue(req.Service.Config.Region)
|
||||||
|
}
|
||||||
|
|
||||||
|
name := req.Service.SigningName
|
||||||
|
if name == "" {
|
||||||
|
name = req.Service.ServiceName
|
||||||
|
}
|
||||||
|
|
||||||
|
s := signer{
|
||||||
|
Request: req.HTTPRequest,
|
||||||
|
Time: req.Time,
|
||||||
|
ExpireTime: req.ExpireTime,
|
||||||
|
Query: req.HTTPRequest.URL.Query(),
|
||||||
|
Body: req.Body,
|
||||||
|
ServiceName: name,
|
||||||
|
Region: region,
|
||||||
|
Credentials: req.Service.Config.Credentials,
|
||||||
|
Debug: req.Service.Config.LogLevel.Value(),
|
||||||
|
Logger: req.Service.Config.Logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Error = s.sign()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) sign() error {
|
||||||
|
if v4.ExpireTime != 0 {
|
||||||
|
v4.isPresign = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if v4.isRequestSigned() {
|
||||||
|
if !v4.Credentials.IsExpired() {
|
||||||
|
// If the request is already signed, and the credentials have not
|
||||||
|
// expired yet ignore the signing request.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The credentials have expired for this request. The current signing
|
||||||
|
// is invalid, and needs to be request because the request will fail.
|
||||||
|
if v4.isPresign {
|
||||||
|
v4.removePresign()
|
||||||
|
// Update the request's query string to ensure the values stays in
|
||||||
|
// sync in the case retrieving the new credentials fails.
|
||||||
|
v4.Request.URL.RawQuery = v4.Query.Encode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
v4.CredValues, err = v4.Credentials.Get()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v4.isPresign {
|
||||||
|
v4.Query.Set("X-Amz-Algorithm", authHeaderPrefix)
|
||||||
|
if v4.CredValues.SessionToken != "" {
|
||||||
|
v4.Query.Set("X-Amz-Security-Token", v4.CredValues.SessionToken)
|
||||||
|
} else {
|
||||||
|
v4.Query.Del("X-Amz-Security-Token")
|
||||||
|
}
|
||||||
|
} else if v4.CredValues.SessionToken != "" {
|
||||||
|
v4.Request.Header.Set("X-Amz-Security-Token", v4.CredValues.SessionToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
v4.build()
|
||||||
|
|
||||||
|
if v4.Debug.Matches(aws.LogDebugWithSigning) {
|
||||||
|
v4.logSigningInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const logSignInfoMsg = `DEBUG: Request Signiture:
|
||||||
|
---[ CANONICAL STRING ]-----------------------------
|
||||||
|
%s
|
||||||
|
---[ STRING TO SIGN ]--------------------------------
|
||||||
|
%s%s
|
||||||
|
-----------------------------------------------------`
|
||||||
|
const logSignedURLMsg = `
|
||||||
|
---[ SIGNED URL ]------------------------------------
|
||||||
|
%s`
|
||||||
|
|
||||||
|
func (v4 *signer) logSigningInfo() {
|
||||||
|
signedURLMsg := ""
|
||||||
|
if v4.isPresign {
|
||||||
|
signedURLMsg = fmt.Sprintf(logSignedURLMsg, v4.Request.URL.String())
|
||||||
|
}
|
||||||
|
msg := fmt.Sprintf(logSignInfoMsg, v4.canonicalString, v4.stringToSign, signedURLMsg)
|
||||||
|
v4.Logger.Log(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) build() {
|
||||||
|
v4.buildTime() // no depends
|
||||||
|
v4.buildCredentialString() // no depends
|
||||||
|
if v4.isPresign {
|
||||||
|
v4.buildQuery() // no depends
|
||||||
|
}
|
||||||
|
v4.buildCanonicalHeaders() // depends on cred string
|
||||||
|
v4.buildCanonicalString() // depends on canon headers / signed headers
|
||||||
|
v4.buildStringToSign() // depends on canon string
|
||||||
|
v4.buildSignature() // depends on string to sign
|
||||||
|
|
||||||
|
if v4.isPresign {
|
||||||
|
v4.Request.URL.RawQuery += "&X-Amz-Signature=" + v4.signature
|
||||||
|
} else {
|
||||||
|
parts := []string{
|
||||||
|
authHeaderPrefix + " Credential=" + v4.CredValues.AccessKeyID + "/" + v4.credentialString,
|
||||||
|
"SignedHeaders=" + v4.signedHeaders,
|
||||||
|
"Signature=" + v4.signature,
|
||||||
|
}
|
||||||
|
v4.Request.Header.Set("Authorization", strings.Join(parts, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) buildTime() {
|
||||||
|
v4.formattedTime = v4.Time.UTC().Format(timeFormat)
|
||||||
|
v4.formattedShortTime = v4.Time.UTC().Format(shortTimeFormat)
|
||||||
|
|
||||||
|
if v4.isPresign {
|
||||||
|
duration := int64(v4.ExpireTime / time.Second)
|
||||||
|
v4.Query.Set("X-Amz-Date", v4.formattedTime)
|
||||||
|
v4.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10))
|
||||||
|
} else {
|
||||||
|
v4.Request.Header.Set("X-Amz-Date", v4.formattedTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) buildCredentialString() {
|
||||||
|
v4.credentialString = strings.Join([]string{
|
||||||
|
v4.formattedShortTime,
|
||||||
|
v4.Region,
|
||||||
|
v4.ServiceName,
|
||||||
|
"aws4_request",
|
||||||
|
}, "/")
|
||||||
|
|
||||||
|
if v4.isPresign {
|
||||||
|
v4.Query.Set("X-Amz-Credential", v4.CredValues.AccessKeyID+"/"+v4.credentialString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) buildQuery() {
|
||||||
|
for k, h := range v4.Request.Header {
|
||||||
|
if strings.HasPrefix(http.CanonicalHeaderKey(k), "X-Amz-") {
|
||||||
|
continue // never hoist x-amz-* headers, they must be signed
|
||||||
|
}
|
||||||
|
if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
|
||||||
|
continue // never hoist ignored headers
|
||||||
|
}
|
||||||
|
|
||||||
|
v4.Request.Header.Del(k)
|
||||||
|
v4.Query.Del(k)
|
||||||
|
for _, v := range h {
|
||||||
|
v4.Query.Add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) buildCanonicalHeaders() {
|
||||||
|
var headers []string
|
||||||
|
headers = append(headers, "host")
|
||||||
|
for k := range v4.Request.Header {
|
||||||
|
if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
|
||||||
|
continue // ignored header
|
||||||
|
}
|
||||||
|
headers = append(headers, strings.ToLower(k))
|
||||||
|
}
|
||||||
|
sort.Strings(headers)
|
||||||
|
|
||||||
|
v4.signedHeaders = strings.Join(headers, ";")
|
||||||
|
|
||||||
|
if v4.isPresign {
|
||||||
|
v4.Query.Set("X-Amz-SignedHeaders", v4.signedHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
|
headerValues := make([]string, len(headers))
|
||||||
|
for i, k := range headers {
|
||||||
|
if k == "host" {
|
||||||
|
headerValues[i] = "host:" + v4.Request.URL.Host
|
||||||
|
} else {
|
||||||
|
headerValues[i] = k + ":" +
|
||||||
|
strings.Join(v4.Request.Header[http.CanonicalHeaderKey(k)], ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v4.canonicalHeaders = strings.Join(headerValues, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) buildCanonicalString() {
|
||||||
|
v4.Request.URL.RawQuery = strings.Replace(v4.Query.Encode(), "+", "%20", -1)
|
||||||
|
uri := v4.Request.URL.Opaque
|
||||||
|
if uri != "" {
|
||||||
|
uri = "/" + strings.Join(strings.Split(uri, "/")[3:], "/")
|
||||||
|
} else {
|
||||||
|
uri = v4.Request.URL.Path
|
||||||
|
}
|
||||||
|
if uri == "" {
|
||||||
|
uri = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
if v4.ServiceName != "s3" {
|
||||||
|
uri = rest.EscapePath(uri, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
v4.canonicalString = strings.Join([]string{
|
||||||
|
v4.Request.Method,
|
||||||
|
uri,
|
||||||
|
v4.Request.URL.RawQuery,
|
||||||
|
v4.canonicalHeaders + "\n",
|
||||||
|
v4.signedHeaders,
|
||||||
|
v4.bodyDigest(),
|
||||||
|
}, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) buildStringToSign() {
|
||||||
|
v4.stringToSign = strings.Join([]string{
|
||||||
|
authHeaderPrefix,
|
||||||
|
v4.formattedTime,
|
||||||
|
v4.credentialString,
|
||||||
|
hex.EncodeToString(makeSha256([]byte(v4.canonicalString))),
|
||||||
|
}, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) buildSignature() {
|
||||||
|
secret := v4.CredValues.SecretAccessKey
|
||||||
|
date := makeHmac([]byte("AWS4"+secret), []byte(v4.formattedShortTime))
|
||||||
|
region := makeHmac(date, []byte(v4.Region))
|
||||||
|
service := makeHmac(region, []byte(v4.ServiceName))
|
||||||
|
credentials := makeHmac(service, []byte("aws4_request"))
|
||||||
|
signature := makeHmac(credentials, []byte(v4.stringToSign))
|
||||||
|
v4.signature = hex.EncodeToString(signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v4 *signer) bodyDigest() string {
|
||||||
|
hash := v4.Request.Header.Get("X-Amz-Content-Sha256")
|
||||||
|
if hash == "" {
|
||||||
|
if v4.isPresign && v4.ServiceName == "s3" {
|
||||||
|
hash = "UNSIGNED-PAYLOAD"
|
||||||
|
} else if v4.Body == nil {
|
||||||
|
hash = hex.EncodeToString(makeSha256([]byte{}))
|
||||||
|
} else {
|
||||||
|
hash = hex.EncodeToString(makeSha256Reader(v4.Body))
|
||||||
|
}
|
||||||
|
v4.Request.Header.Add("X-Amz-Content-Sha256", hash)
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// isRequestSigned returns if the request is currently signed or presigned
|
||||||
|
func (v4 *signer) isRequestSigned() bool {
|
||||||
|
if v4.isPresign && v4.Query.Get("X-Amz-Signature") != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if v4.Request.Header.Get("Authorization") != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsign removes signing flags for both signed and presigned requests.
|
||||||
|
func (v4 *signer) removePresign() {
|
||||||
|
v4.Query.Del("X-Amz-Algorithm")
|
||||||
|
v4.Query.Del("X-Amz-Signature")
|
||||||
|
v4.Query.Del("X-Amz-Security-Token")
|
||||||
|
v4.Query.Del("X-Amz-Date")
|
||||||
|
v4.Query.Del("X-Amz-Expires")
|
||||||
|
v4.Query.Del("X-Amz-Credential")
|
||||||
|
v4.Query.Del("X-Amz-SignedHeaders")
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeHmac(key []byte, data []byte) []byte {
|
||||||
|
hash := hmac.New(sha256.New, key)
|
||||||
|
hash.Write(data)
|
||||||
|
return hash.Sum(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSha256(data []byte) []byte {
|
||||||
|
hash := sha256.New()
|
||||||
|
hash.Write(data)
|
||||||
|
return hash.Sum(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSha256Reader(reader io.ReadSeeker) []byte {
|
||||||
|
hash := sha256.New()
|
||||||
|
start, _ := reader.Seek(0, 1)
|
||||||
|
defer reader.Seek(start, 0)
|
||||||
|
|
||||||
|
io.Copy(hash, reader)
|
||||||
|
return hash.Sum(nil)
|
||||||
|
}
|
24490
vendor/github.com/aws/aws-sdk-go/service/ec2/api.go
generated
vendored
Normal file
24490
vendor/github.com/aws/aws-sdk-go/service/ec2/api.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
57
vendor/github.com/aws/aws-sdk-go/service/ec2/customizations.go
generated
vendored
Normal file
57
vendor/github.com/aws/aws-sdk-go/service/ec2/customizations.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package ec2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
initRequest = func(r *request.Request) {
|
||||||
|
if r.Operation.Name == opCopySnapshot { // fill the PresignedURL parameter
|
||||||
|
r.Handlers.Build.PushFront(fillPresignedURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fillPresignedURL(r *request.Request) {
|
||||||
|
if !r.ParamsFilled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params := r.Params.(*CopySnapshotInput)
|
||||||
|
|
||||||
|
// Stop if PresignedURL/DestinationRegion is set
|
||||||
|
if params.PresignedUrl != nil || params.DestinationRegion != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// First generate a copy of parameters
|
||||||
|
r.Params = awsutil.CopyOf(r.Params)
|
||||||
|
params = r.Params.(*CopySnapshotInput)
|
||||||
|
|
||||||
|
// Set destination region. Avoids infinite handler loop.
|
||||||
|
// Also needed to sign sub-request.
|
||||||
|
params.DestinationRegion = r.Service.Config.Region
|
||||||
|
|
||||||
|
// Create a new client pointing at source region.
|
||||||
|
// We will use this to presign the CopySnapshot request against
|
||||||
|
// the source region
|
||||||
|
config := r.Service.Config.Copy().
|
||||||
|
WithEndpoint("").
|
||||||
|
WithRegion(*params.SourceRegion)
|
||||||
|
|
||||||
|
client := New(config)
|
||||||
|
|
||||||
|
// Presign a CopySnapshot request with modified params
|
||||||
|
req, _ := client.CopySnapshotRequest(params)
|
||||||
|
url, err := req.Presign(300 * time.Second) // 5 minutes should be enough.
|
||||||
|
|
||||||
|
if err != nil { // bubble error back up to original request
|
||||||
|
r.Error = err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have our URL, set it on params
|
||||||
|
params.PresignedUrl = &url
|
||||||
|
}
|
66
vendor/github.com/aws/aws-sdk-go/service/ec2/service.go
generated
vendored
Normal file
66
vendor/github.com/aws/aws-sdk-go/service/ec2/service.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||||
|
|
||||||
|
package ec2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/defaults"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/service"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
|
||||||
|
"github.com/aws/aws-sdk-go/internal/protocol/ec2query"
|
||||||
|
"github.com/aws/aws-sdk-go/internal/signer/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity
|
||||||
|
// in the Amazon Web Services (AWS) cloud. Using Amazon EC2 eliminates your
|
||||||
|
// need to invest in hardware up front, so you can develop and deploy applications
|
||||||
|
// faster.
|
||||||
|
type EC2 struct {
|
||||||
|
*service.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for custom service initialization logic
|
||||||
|
var initService func(*service.Service)
|
||||||
|
|
||||||
|
// Used for custom request initialization logic
|
||||||
|
var initRequest func(*request.Request)
|
||||||
|
|
||||||
|
// New returns a new EC2 client.
|
||||||
|
func New(config *aws.Config) *EC2 {
|
||||||
|
service := &service.Service{
|
||||||
|
ServiceInfo: serviceinfo.ServiceInfo{
|
||||||
|
Config: defaults.DefaultConfig.Merge(config),
|
||||||
|
ServiceName: "ec2",
|
||||||
|
APIVersion: "2015-04-15",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
service.Initialize()
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
service.Handlers.Sign.PushBack(v4.Sign)
|
||||||
|
service.Handlers.Build.PushBack(ec2query.Build)
|
||||||
|
service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
|
||||||
|
service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
|
||||||
|
service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
|
||||||
|
|
||||||
|
// Run custom service initialization if present
|
||||||
|
if initService != nil {
|
||||||
|
initService(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &EC2{service}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newRequest creates a new request for a EC2 operation and runs any
|
||||||
|
// custom request initialization.
|
||||||
|
func (c *EC2) 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
|
||||||
|
}
|
14
vendor/github.com/vaughan0/go-ini/LICENSE
generated
vendored
Normal file
14
vendor/github.com/vaughan0/go-ini/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Copyright (c) 2013 Vaughan Newton
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
||||||
|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
70
vendor/github.com/vaughan0/go-ini/README.md
generated
vendored
Normal file
70
vendor/github.com/vaughan0/go-ini/README.md
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
go-ini
|
||||||
|
======
|
||||||
|
|
||||||
|
INI parsing library for Go (golang).
|
||||||
|
|
||||||
|
View the API documentation [here](http://godoc.org/github.com/vaughan0/go-ini).
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
Parse an INI file:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/vaughan0/go-ini"
|
||||||
|
|
||||||
|
file, err := ini.LoadFile("myfile.ini")
|
||||||
|
```
|
||||||
|
|
||||||
|
Get data from the parsed file:
|
||||||
|
|
||||||
|
```go
|
||||||
|
name, ok := file.Get("person", "name")
|
||||||
|
if !ok {
|
||||||
|
panic("'name' variable missing from 'person' section")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Iterate through values in a section:
|
||||||
|
|
||||||
|
```go
|
||||||
|
for key, value := range file["mysection"] {
|
||||||
|
fmt.Printf("%s => %s\n", key, value)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Iterate through sections in a file:
|
||||||
|
|
||||||
|
```go
|
||||||
|
for name, section := range file {
|
||||||
|
fmt.Printf("Section name: %s\n", name)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
File Format
|
||||||
|
-----------
|
||||||
|
|
||||||
|
INI files are parsed by go-ini line-by-line. Each line may be one of the following:
|
||||||
|
|
||||||
|
* A section definition: [section-name]
|
||||||
|
* A property: key = value
|
||||||
|
* A comment: #blahblah _or_ ;blahblah
|
||||||
|
* Blank. The line will be ignored.
|
||||||
|
|
||||||
|
Properties defined before any section headers are placed in the default section, which has
|
||||||
|
the empty string as it's key.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# I am a comment
|
||||||
|
; So am I!
|
||||||
|
|
||||||
|
[apples]
|
||||||
|
colour = red or green
|
||||||
|
shape = applish
|
||||||
|
|
||||||
|
[oranges]
|
||||||
|
shape = square
|
||||||
|
colour = blue
|
||||||
|
```
|
123
vendor/github.com/vaughan0/go-ini/ini.go
generated
vendored
Normal file
123
vendor/github.com/vaughan0/go-ini/ini.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
// Package ini provides functions for parsing INI configuration files.
|
||||||
|
package ini
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
sectionRegex = regexp.MustCompile(`^\[(.*)\]$`)
|
||||||
|
assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrSyntax is returned when there is a syntax error in an INI file.
|
||||||
|
type ErrSyntax struct {
|
||||||
|
Line int
|
||||||
|
Source string // The contents of the erroneous line, without leading or trailing whitespace
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrSyntax) Error() string {
|
||||||
|
return fmt.Sprintf("invalid INI syntax on line %d: %s", e.Line, e.Source)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A File represents a parsed INI file.
|
||||||
|
type File map[string]Section
|
||||||
|
|
||||||
|
// A Section represents a single section of an INI file.
|
||||||
|
type Section map[string]string
|
||||||
|
|
||||||
|
// Returns a named Section. A Section will be created if one does not already exist for the given name.
|
||||||
|
func (f File) Section(name string) Section {
|
||||||
|
section := f[name]
|
||||||
|
if section == nil {
|
||||||
|
section = make(Section)
|
||||||
|
f[name] = section
|
||||||
|
}
|
||||||
|
return section
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looks up a value for a key in a section and returns that value, along with a boolean result similar to a map lookup.
|
||||||
|
func (f File) Get(section, key string) (value string, ok bool) {
|
||||||
|
if s := f[section]; s != nil {
|
||||||
|
value, ok = s[key]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads INI data from a reader and stores the data in the File.
|
||||||
|
func (f File) Load(in io.Reader) (err error) {
|
||||||
|
bufin, ok := in.(*bufio.Reader)
|
||||||
|
if !ok {
|
||||||
|
bufin = bufio.NewReader(in)
|
||||||
|
}
|
||||||
|
return parseFile(bufin, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads INI data from a named file and stores the data in the File.
|
||||||
|
func (f File) LoadFile(file string) (err error) {
|
||||||
|
in, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer in.Close()
|
||||||
|
return f.Load(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFile(in *bufio.Reader, file File) (err error) {
|
||||||
|
section := ""
|
||||||
|
lineNum := 0
|
||||||
|
for done := false; !done; {
|
||||||
|
var line string
|
||||||
|
if line, err = in.ReadString('\n'); err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
done = true
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineNum++
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if len(line) == 0 {
|
||||||
|
// Skip blank lines
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if line[0] == ';' || line[0] == '#' {
|
||||||
|
// Skip comments
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
|
||||||
|
key, val := groups[1], groups[2]
|
||||||
|
key, val = strings.TrimSpace(key), strings.TrimSpace(val)
|
||||||
|
file.Section(section)[key] = val
|
||||||
|
} else if groups := sectionRegex.FindStringSubmatch(line); groups != nil {
|
||||||
|
name := strings.TrimSpace(groups[1])
|
||||||
|
section = name
|
||||||
|
// Create the section if it does not exist
|
||||||
|
file.Section(section)
|
||||||
|
} else {
|
||||||
|
return ErrSyntax{lineNum, line}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads and returns a File from a reader.
|
||||||
|
func Load(in io.Reader) (File, error) {
|
||||||
|
file := make(File)
|
||||||
|
err := file.Load(in)
|
||||||
|
return file, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads and returns an INI File from a file on disk.
|
||||||
|
func LoadFile(filename string) (File, error) {
|
||||||
|
file := make(File)
|
||||||
|
err := file.LoadFile(filename)
|
||||||
|
return file, err
|
||||||
|
}
|
2
vendor/github.com/vaughan0/go-ini/test.ini
generated
vendored
Normal file
2
vendor/github.com/vaughan0/go-ini/test.ini
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[default]
|
||||||
|
stuff = things
|
95
vendor/vendor.json
vendored
95
vendor/vendor.json
vendored
|
@ -12,6 +12,96 @@
|
||||||
"revision": "418b41d23a1bf978c06faea5313ba194650ac088",
|
"revision": "418b41d23a1bf978c06faea5313ba194650ac088",
|
||||||
"revisionTime": "2015-09-08T20:46:18Z"
|
"revisionTime": "2015-09-08T20:46:18Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/awserr",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/awsutil",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/credentials",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/defaults",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/request",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/service",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/aws/service/serviceinfo",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/internal/endpoints",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/internal/protocol/ec2query",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/internal/protocol/query/queryutil",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/internal/protocol/rest",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/internal/signer/v4",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/aws/aws-sdk-go/service/ec2",
|
||||||
|
"revision": "a11ddd7a070196035bc94b6c04a2a0114c06a395",
|
||||||
|
"revisionTime": "2015-08-20T12:44:31-07:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "github.com/beorn7/perks/quantile",
|
"path": "github.com/beorn7/perks/quantile",
|
||||||
"revision": "b965b613227fddccbfffe13eae360ed3fa822f8d",
|
"revision": "b965b613227fddccbfffe13eae360ed3fa822f8d",
|
||||||
|
@ -162,6 +252,11 @@
|
||||||
"revision": "1a9d62f03ea92815b46fcaab357cfd4df264b1a0",
|
"revision": "1a9d62f03ea92815b46fcaab357cfd4df264b1a0",
|
||||||
"revisionTime": "2015-08-19T12:16:22+07:00"
|
"revisionTime": "2015-08-19T12:16:22+07:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "github.com/vaughan0/go-ini",
|
||||||
|
"revision": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1",
|
||||||
|
"revisionTime": "2013-09-23T16:52:12+02:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "golang.org/x/net/context",
|
"path": "golang.org/x/net/context",
|
||||||
"revision": "db8e4de5b2d6653f66aea53094624468caad15d2",
|
"revision": "db8e4de5b2d6653f66aea53094624468caad15d2",
|
||||||
|
|
Loading…
Reference in a new issue