mirror of
https://github.com/Luzifer/mondash.git
synced 2024-12-23 04:21:18 +00:00
Switch to dep for vendoring, update libraries
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
51b1faad1f
commit
fd7056f82f
3208 changed files with 2187076 additions and 15606 deletions
163
Godeps/Godeps.json
generated
163
Godeps/Godeps.json
generated
|
@ -1,163 +0,0 @@
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Luzifer/mondash",
|
|
||||||
"GoVersion": "go1.6",
|
|
||||||
"GodepVersion": "v60",
|
|
||||||
"Deps": [
|
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go.text/transform",
|
|
||||||
"Comment": "null-104",
|
|
||||||
"Rev": "'7ab6d3749429e2c62c53eecadf3e4ec5e715c11b'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go.text/unicode/norm",
|
|
||||||
"Comment": "null-104",
|
|
||||||
"Rev": "'7ab6d3749429e2c62c53eecadf3e4ec5e715c11b'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Luzifer/rconfig",
|
|
||||||
"Comment": "v1.0.3-2-g2677653",
|
|
||||||
"Rev": "26776536e61487fdffbd3ce87f827177a5903f98"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/service",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/service/serviceinfo",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/internal/endpoints",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/query",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/query/queryutil",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/rest",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/restxml",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/internal/signer/v4",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
|
|
||||||
"Comment": "v0.9.10",
|
|
||||||
"Rev": "661aeb3339ad9bd5fd420752ebf18a651d40413e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/extemporalgenome/slug",
|
|
||||||
"Rev": "de70af6e24d0e6bdd6eaef276d2e9910e68a1397"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/flosch/go-humanize",
|
|
||||||
"Rev": "3ba51eabe50663842d569003bab93fc256883173"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/flosch/pongo2",
|
|
||||||
"Comment": "v1.0-rc1-174-gf5d79aa",
|
|
||||||
"Rev": "f5d79aa0a914c08eb7f51a96cd7b2dbbe46fca46"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/flosch/pongo2-addons",
|
|
||||||
"Rev": "bb4da1901facc08b4edd9261050143b95e36d0a1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/gorilla/context",
|
|
||||||
"Rev": "1c83b3eabd45b6d76072b66b746c20815fb2872d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/gorilla/mux",
|
|
||||||
"Rev": "49c024275504f0341e5a9971eb7ba7fa3dc7af40"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/russross/blackfriday",
|
|
||||||
"Comment": "v1.3",
|
|
||||||
"Rev": "8cec3a854e68dba10faabbe31c089abf4a3e57a6"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/shurcooL/sanitized_anchor_name",
|
|
||||||
"Rev": "244f5ac324cb97e1987ef901a0081a77bfd8e845"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/spf13/pflag",
|
|
||||||
"Rev": "b084184666e02084b8ccb9b704bf0d79c466eb1d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/vaughan0/go-ini",
|
|
||||||
"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "gopkg.in/yaml.v2",
|
|
||||||
"Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
110
Gopkg.lock
generated
Normal file
110
Gopkg.lock
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/Luzifer/rconfig"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "7aef1d393c1e2d0758901853b59981c7adc67c7e"
|
||||||
|
version = "v1.2.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/aws/aws-sdk-go"
|
||||||
|
packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/credentials","aws/endpoints","aws/request","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/s3"]
|
||||||
|
revision = "991fe2497a95d757bb53f95cbcebf3d26134c9fe"
|
||||||
|
version = "v1.12.32"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/extemporalgenome/slug"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "0320c85e32e0015b090f08a5d1324d5ab6094f07"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/flosch/go-humanize"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "3ba51eabe50663842d569003bab93fc256883173"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/flosch/pongo2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "5e81b817a0c48c1c57cdf1a9056cf76bdee02ca9"
|
||||||
|
version = "v3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/flosch/pongo2-addons"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "86b9b7b8051253fbb41b3fff8a8f5cc9c300305e"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/go-ini/ini"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a"
|
||||||
|
version = "v1.32.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/gorilla/context"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
|
||||||
|
version = "v1.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/gorilla/mux"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "7f08801859139f86dfafd1c296e2cba9a80d292e"
|
||||||
|
version = "v1.6.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/jmespath/go-jmespath"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "0b12d6b5"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/juju/errors"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "c7d06af17c68cd34c835053720b21f6549d9b0ee"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/russross/blackfriday"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "cadec560ec52d93835bf2f15bd794700d3a2473b"
|
||||||
|
version = "v2.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/shurcooL/sanitized_anchor_name"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "86672fcb3f950f35f2e675df2240550f2a50762f"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/spf13/pflag"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/text"
|
||||||
|
packages = ["internal/gen","internal/triegen","internal/ucd","transform","unicode/cldr","unicode/norm"]
|
||||||
|
revision = "88f656faf3f37f690df1a32515b479415e1a6769"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "v2"
|
||||||
|
name = "gopkg.in/validator.v2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "460c83432a98c35224a6fe352acf8b23e067ad06"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "v2"
|
||||||
|
name = "gopkg.in/yaml.v2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "287cf08546ab5e7e37d55a84f7ed3fd1db036de5"
|
||||||
|
|
||||||
|
[solve-meta]
|
||||||
|
analyzer-name = "dep"
|
||||||
|
analyzer-version = 1
|
||||||
|
inputs-digest = "2544efe6d7c15494a53f84f4639759ad68c124eadbd0608faebc66d767db2d3c"
|
||||||
|
solver-name = "gps-cdcl"
|
||||||
|
solver-version = 1
|
42
Gopkg.toml
Normal file
42
Gopkg.toml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
# Gopkg.toml example
|
||||||
|
#
|
||||||
|
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||||
|
# for detailed Gopkg.toml documentation.
|
||||||
|
#
|
||||||
|
# required = ["github.com/user/thing/cmd/thing"]
|
||||||
|
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project"
|
||||||
|
# version = "1.0.0"
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project2"
|
||||||
|
# branch = "dev"
|
||||||
|
# source = "github.com/myfork/project2"
|
||||||
|
#
|
||||||
|
# [[override]]
|
||||||
|
# name = "github.com/x/y"
|
||||||
|
# version = "2.4.0"
|
||||||
|
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/Luzifer/rconfig"
|
||||||
|
version = "1.2.0"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/aws/aws-sdk-go"
|
||||||
|
version = "1.12.32"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/flosch/pongo2"
|
||||||
|
version = "3.0.0"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/flosch/pongo2-addons"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/gorilla/mux"
|
||||||
|
version = "1.6.0"
|
23
vendor/code.google.com/p/go.text/unicode/norm/Makefile
generated
vendored
23
vendor/code.google.com/p/go.text/unicode/norm/Makefile
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
# Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style
|
|
||||||
# license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
maketables: maketables.go triegen.go
|
|
||||||
go build $^
|
|
||||||
|
|
||||||
normregtest: normregtest.go
|
|
||||||
go build $^
|
|
||||||
|
|
||||||
tables: maketables
|
|
||||||
./maketables > tables.go
|
|
||||||
gofmt -w tables.go
|
|
||||||
|
|
||||||
# Downloads from www.unicode.org, so not part
|
|
||||||
# of standard test scripts.
|
|
||||||
test: testtables regtest
|
|
||||||
|
|
||||||
testtables: maketables
|
|
||||||
./maketables -test > data_test.go && go test -tags=test
|
|
||||||
|
|
||||||
regtest: normregtest
|
|
||||||
./normregtest
|
|
7549
vendor/code.google.com/p/go.text/unicode/norm/tables.go
generated
vendored
7549
vendor/code.google.com/p/go.text/unicode/norm/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
4
vendor/github.com/Luzifer/rconfig/.travis.yml
generated
vendored
4
vendor/github.com/Luzifer/rconfig/.travis.yml
generated
vendored
|
@ -1,8 +1,8 @@
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.4
|
- 1.6
|
||||||
- 1.5
|
- 1.7
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
script: go test -v -race -cover ./...
|
script: go test -v -race -cover ./...
|
||||||
|
|
9
vendor/github.com/Luzifer/rconfig/History.md
generated
vendored
Normal file
9
vendor/github.com/Luzifer/rconfig/History.md
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# 1.2.0 / 2017-06-19
|
||||||
|
|
||||||
|
* Add ParseAndValidate method
|
||||||
|
|
||||||
|
# 1.1.0 / 2016-06-28
|
||||||
|
|
||||||
|
* Support time.Duration config parameters
|
||||||
|
* Added goreportcard badge
|
||||||
|
* Added testcase for using bool with ENV and default
|
47
vendor/github.com/Luzifer/rconfig/README.md
generated
vendored
47
vendor/github.com/Luzifer/rconfig/README.md
generated
vendored
|
@ -29,34 +29,31 @@ go test -v -race -cover github.com/Luzifer/rconfig
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
As a first step define a struct holding your configuration:
|
A very simple usecase is to just configure a struct inside the vars section of your `main.go` and to parse the commandline flags from the `main()` function:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type config struct {
|
package main
|
||||||
Username string `default:"unknown" flag:"user" description:"Your name"`
|
|
||||||
Details struct {
|
|
||||||
Age int `default:"25" flag:"age" env:"age" description:"Your age"`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Next create an instance of that struct and let `rconfig` fill that config:
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/Luzifer/rconfig"
|
||||||
|
)
|
||||||
|
|
||||||
```go
|
var (
|
||||||
var cfg config
|
cfg = struct {
|
||||||
func init() {
|
Username string `default:"unknown" flag:"user" description:"Your name"`
|
||||||
cfg = config{}
|
Details struct {
|
||||||
rconfig.Parse(&cfg)
|
Age int `default:"25" flag:"age" env:"age" description:"Your age"`
|
||||||
}
|
}
|
||||||
```
|
}{}
|
||||||
|
)
|
||||||
|
|
||||||
You're ready to access your configuration:
|
|
||||||
|
|
||||||
```go
|
|
||||||
func main() {
|
func main() {
|
||||||
|
rconfig.Parse(&cfg)
|
||||||
|
|
||||||
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
|
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
|
||||||
cfg.Username,
|
cfg.Username,
|
||||||
cfg.Details.Age)
|
cfg.Details.Age)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -72,18 +69,14 @@ The order of the directives (lower number = higher precedence):
|
||||||
1. `default` tag in the struct
|
1. `default` tag in the struct
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type config struct {
|
var cfg = struct {
|
||||||
Username string `vardefault:"username" flag:"username" description:"Your username"`
|
Username string `vardefault:"username" flag:"username" description:"Your username"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg = config{}
|
func main() {
|
||||||
|
|
||||||
func init() {
|
|
||||||
rconfig.SetVariableDefaults(rconfig.VarDefaultsFromYAMLFile("~/.myapp.yml"))
|
rconfig.SetVariableDefaults(rconfig.VarDefaultsFromYAMLFile("~/.myapp.yml"))
|
||||||
rconfig.Parse(&cfg)
|
rconfig.Parse(&cfg)
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Printf("Username = %s", cfg.Username)
|
fmt.Printf("Username = %s", cfg.Username)
|
||||||
// Output: Username = luzifer
|
// Output: Username = luzifer
|
||||||
}
|
}
|
||||||
|
|
70
vendor/github.com/Luzifer/rconfig/bool_test.go
generated
vendored
Normal file
70
vendor/github.com/Luzifer/rconfig/bool_test.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing bool parsing", func() {
|
||||||
|
type t struct {
|
||||||
|
Test1 bool `default:"true"`
|
||||||
|
Test2 bool `default:"false" flag:"test2"`
|
||||||
|
Test3 bool `default:"true" flag:"test3,t"`
|
||||||
|
Test4 bool `flag:"test4"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--test2",
|
||||||
|
"-t",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.Test1).To(Equal(true))
|
||||||
|
Expect(cfg.Test2).To(Equal(true))
|
||||||
|
Expect(cfg.Test3).To(Equal(true))
|
||||||
|
Expect(cfg.Test4).To(Equal(false))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
var _ = Describe("Testing to set bool from ENV with default", func() {
|
||||||
|
type t struct {
|
||||||
|
Test1 bool `default:"true" env:"TEST1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
os.Unsetenv("TEST1")
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.Test1).To(Equal(true))
|
||||||
|
})
|
||||||
|
})
|
42
vendor/github.com/Luzifer/rconfig/config.go
generated
vendored
42
vendor/github.com/Luzifer/rconfig/config.go
generated
vendored
|
@ -10,8 +10,10 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
validator "gopkg.in/validator.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -44,6 +46,15 @@ func Parse(config interface{}) error {
|
||||||
return parse(config, nil)
|
return parse(config, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseAndValidate works exactly like Parse but implements an additional run of
|
||||||
|
// the go-validator package on the configuration struct. Therefore additonal struct
|
||||||
|
// tags are supported like described in the readme file of the go-validator package:
|
||||||
|
//
|
||||||
|
// https://github.com/go-validator/validator/tree/v2#usage
|
||||||
|
func ParseAndValidate(config interface{}) error {
|
||||||
|
return parseAndValidate(config, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// Args returns the non-flag command-line arguments.
|
// Args returns the non-flag command-line arguments.
|
||||||
func Args() []string {
|
func Args() []string {
|
||||||
return fs.Args()
|
return fs.Args()
|
||||||
|
@ -64,6 +75,14 @@ func SetVariableDefaults(defaults map[string]string) {
|
||||||
variableDefaults = defaults
|
variableDefaults = defaults
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseAndValidate(in interface{}, args []string) error {
|
||||||
|
if err := parse(in, args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return validator.Validate(in)
|
||||||
|
}
|
||||||
|
|
||||||
func parse(in interface{}, args []string) error {
|
func parse(in interface{}, args []string) error {
|
||||||
if args == nil {
|
if args == nil {
|
||||||
args = os.Args
|
args = os.Args
|
||||||
|
@ -100,6 +119,29 @@ func execTags(in interface{}, fs *pflag.FlagSet) error {
|
||||||
value = envDefault(typeField.Tag.Get("env"), value)
|
value = envDefault(typeField.Tag.Get("env"), value)
|
||||||
parts := strings.Split(typeField.Tag.Get("flag"), ",")
|
parts := strings.Split(typeField.Tag.Get("flag"), ",")
|
||||||
|
|
||||||
|
switch typeField.Type {
|
||||||
|
case reflect.TypeOf(time.Duration(0)):
|
||||||
|
v, err := time.ParseDuration(value)
|
||||||
|
if err != nil {
|
||||||
|
if value == "" {
|
||||||
|
v = time.Duration(0)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if typeField.Tag.Get("flag") != "" {
|
||||||
|
if len(parts) == 1 {
|
||||||
|
fs.DurationVar(valField.Addr().Interface().(*time.Duration), parts[0], v, typeField.Tag.Get("description"))
|
||||||
|
} else {
|
||||||
|
fs.DurationVarP(valField.Addr().Interface().(*time.Duration), parts[0], parts[1], v, typeField.Tag.Get("description"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
valField.Set(reflect.ValueOf(v))
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
switch typeField.Type.Kind() {
|
switch typeField.Type.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
if typeField.Tag.Get("flag") != "" {
|
if typeField.Tag.Get("flag") != "" {
|
||||||
|
|
41
vendor/github.com/Luzifer/rconfig/duration_test.go
generated
vendored
Normal file
41
vendor/github.com/Luzifer/rconfig/duration_test.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Duration", func() {
|
||||||
|
type t struct {
|
||||||
|
Test time.Duration `flag:"duration"`
|
||||||
|
TestS time.Duration `flag:"other-duration,o"`
|
||||||
|
TestDef time.Duration `default:"30h"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--duration=23s", "-o", "45m",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.Test).To(Equal(23 * time.Second))
|
||||||
|
Expect(cfg.TestS).To(Equal(45 * time.Minute))
|
||||||
|
|
||||||
|
Expect(cfg.TestDef).To(Equal(30 * time.Hour))
|
||||||
|
})
|
||||||
|
})
|
56
vendor/github.com/Luzifer/rconfig/errors_test.go
generated
vendored
Normal file
56
vendor/github.com/Luzifer/rconfig/errors_test.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing errors", func() {
|
||||||
|
|
||||||
|
It("should not accept string as int", func() {
|
||||||
|
Expect(parse(&struct {
|
||||||
|
A int `default:"a"`
|
||||||
|
}{}, []string{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not accept string as float", func() {
|
||||||
|
Expect(parse(&struct {
|
||||||
|
A float32 `default:"a"`
|
||||||
|
}{}, []string{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not accept string as uint", func() {
|
||||||
|
Expect(parse(&struct {
|
||||||
|
A uint `default:"a"`
|
||||||
|
}{}, []string{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not accept string as uint in sub-struct", func() {
|
||||||
|
Expect(parse(&struct {
|
||||||
|
B struct {
|
||||||
|
A uint `default:"a"`
|
||||||
|
}
|
||||||
|
}{}, []string{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not accept string slice as int slice", func() {
|
||||||
|
Expect(parse(&struct {
|
||||||
|
A []int `default:"a,bn"`
|
||||||
|
}{}, []string{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not accept variables not being pointers", func() {
|
||||||
|
cfg := struct {
|
||||||
|
A string `default:"a"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
Expect(parse(cfg, []string{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not accept variables not being pointers to structs", func() {
|
||||||
|
cfg := "test"
|
||||||
|
|
||||||
|
Expect(parse(cfg, []string{})).To(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
37
vendor/github.com/Luzifer/rconfig/example_test.go
generated
vendored
Normal file
37
vendor/github.com/Luzifer/rconfig/example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleParse() {
|
||||||
|
// We're building an example configuration with a sub-struct to be filled
|
||||||
|
// by the Parse command.
|
||||||
|
config := struct {
|
||||||
|
Username string `default:"unknown" flag:"user,u" description:"Your name"`
|
||||||
|
Details struct {
|
||||||
|
Age int `default:"25" flag:"age" description:"Your age"`
|
||||||
|
}
|
||||||
|
}{}
|
||||||
|
|
||||||
|
// To have more relieable results we're setting os.Args to a known value.
|
||||||
|
// In real-life use cases you wouldn't do this but parse the original
|
||||||
|
// commandline arguments.
|
||||||
|
os.Args = []string{
|
||||||
|
"example",
|
||||||
|
"--user=Luzifer",
|
||||||
|
}
|
||||||
|
|
||||||
|
Parse(&config)
|
||||||
|
|
||||||
|
fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
|
||||||
|
config.Username,
|
||||||
|
config.Details.Age)
|
||||||
|
|
||||||
|
// You can also show an usage message for your user
|
||||||
|
Usage()
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hello Luzifer, happy birthday for your 25th birthday.
|
||||||
|
}
|
44
vendor/github.com/Luzifer/rconfig/float_test.go
generated
vendored
Normal file
44
vendor/github.com/Luzifer/rconfig/float_test.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing float parsing", func() {
|
||||||
|
type t struct {
|
||||||
|
Test32 float32 `flag:"float32"`
|
||||||
|
Test32P float32 `flag:"float32p,3"`
|
||||||
|
Test64 float64 `flag:"float64"`
|
||||||
|
Test64P float64 `flag:"float64p,6"`
|
||||||
|
TestDef float32 `default:"66.256"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--float32=5.5", "-3", "6.6",
|
||||||
|
"--float64=7.7", "-6", "8.8",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.Test32).To(Equal(float32(5.5)))
|
||||||
|
Expect(cfg.Test32P).To(Equal(float32(6.6)))
|
||||||
|
Expect(cfg.Test64).To(Equal(float64(7.7)))
|
||||||
|
Expect(cfg.Test64P).To(Equal(float64(8.8)))
|
||||||
|
|
||||||
|
Expect(cfg.TestDef).To(Equal(float32(66.256)))
|
||||||
|
})
|
||||||
|
})
|
128
vendor/github.com/Luzifer/rconfig/general_test.go
generated
vendored
Normal file
128
vendor/github.com/Luzifer/rconfig/general_test.go
generated
vendored
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing general parsing", func() {
|
||||||
|
type t struct {
|
||||||
|
Test string `default:"foo" env:"shell" flag:"shell" description:"Test"`
|
||||||
|
Test2 string `default:"blub" env:"testvar" flag:"testvar,t" description:"Test"`
|
||||||
|
DefaultFlag string `default:"goo"`
|
||||||
|
SadFlag string
|
||||||
|
}
|
||||||
|
|
||||||
|
type tValidated struct {
|
||||||
|
Test string `flag:"test" default:"" validate:"nonzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
Context("with defined arguments", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--shell=test23",
|
||||||
|
"-t", "bla",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have parsed the expected values", func() {
|
||||||
|
Expect(cfg.Test).To(Equal("test23"))
|
||||||
|
Expect(cfg.Test2).To(Equal("bla"))
|
||||||
|
Expect(cfg.SadFlag).To(Equal(""))
|
||||||
|
Expect(cfg.DefaultFlag).To(Equal("goo"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("with no arguments", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have used the default value", func() {
|
||||||
|
Expect(cfg.Test).To(Equal("foo"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("with no arguments and set env", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{}
|
||||||
|
os.Setenv("shell", "test546")
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
os.Unsetenv("shell")
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have used the value from env", func() {
|
||||||
|
Expect(cfg.Test).To(Equal("test546"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("with additional arguments", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--shell=test23",
|
||||||
|
"-t", "bla",
|
||||||
|
"positional1", "positional2",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have parsed the expected values", func() {
|
||||||
|
Expect(cfg.Test).To(Equal("test23"))
|
||||||
|
Expect(cfg.Test2).To(Equal("bla"))
|
||||||
|
Expect(cfg.SadFlag).To(Equal(""))
|
||||||
|
Expect(cfg.DefaultFlag).To(Equal("goo"))
|
||||||
|
})
|
||||||
|
It("should have detected the positional arguments", func() {
|
||||||
|
Expect(Args()).To(Equal([]string{"positional1", "positional2"}))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("making use of the validator package", func() {
|
||||||
|
var cfgValidated tValidated
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfgValidated = tValidated{}
|
||||||
|
args = []string{}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parseAndValidate(&cfgValidated, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should have errored", func() { Expect(err).To(HaveOccurred()) })
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
54
vendor/github.com/Luzifer/rconfig/int_test.go
generated
vendored
Normal file
54
vendor/github.com/Luzifer/rconfig/int_test.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing int parsing", func() {
|
||||||
|
type t struct {
|
||||||
|
Test int `flag:"int"`
|
||||||
|
TestP int `flag:"intp,i"`
|
||||||
|
Test8 int8 `flag:"int8"`
|
||||||
|
Test8P int8 `flag:"int8p,8"`
|
||||||
|
Test32 int32 `flag:"int32"`
|
||||||
|
Test32P int32 `flag:"int32p,3"`
|
||||||
|
Test64 int64 `flag:"int64"`
|
||||||
|
Test64P int64 `flag:"int64p,6"`
|
||||||
|
TestDef int8 `default:"66"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--int=1", "-i", "2",
|
||||||
|
"--int8=3", "-8", "4",
|
||||||
|
"--int32=5", "-3", "6",
|
||||||
|
"--int64=7", "-6", "8",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.Test).To(Equal(1))
|
||||||
|
Expect(cfg.TestP).To(Equal(2))
|
||||||
|
Expect(cfg.Test8).To(Equal(int8(3)))
|
||||||
|
Expect(cfg.Test8P).To(Equal(int8(4)))
|
||||||
|
Expect(cfg.Test32).To(Equal(int32(5)))
|
||||||
|
Expect(cfg.Test32P).To(Equal(int32(6)))
|
||||||
|
Expect(cfg.Test64).To(Equal(int64(7)))
|
||||||
|
Expect(cfg.Test64P).To(Equal(int64(8)))
|
||||||
|
|
||||||
|
Expect(cfg.TestDef).To(Equal(int8(66)))
|
||||||
|
})
|
||||||
|
})
|
40
vendor/github.com/Luzifer/rconfig/os-args_test.go
generated
vendored
Normal file
40
vendor/github.com/Luzifer/rconfig/os-args_test.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package rconfig_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
. "github.com/Luzifer/rconfig"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing os.Args", func() {
|
||||||
|
type t struct {
|
||||||
|
A string `default:"a" flag:"a"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = Parse(&cfg)
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("With only valid arguments", func() {
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
os.Args = []string{"--a=bar"}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.A).To(Equal("bar"))
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
87
vendor/github.com/Luzifer/rconfig/precedence_test.go
generated
vendored
Normal file
87
vendor/github.com/Luzifer/rconfig/precedence_test.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Precedence", func() {
|
||||||
|
|
||||||
|
type t struct {
|
||||||
|
A int `default:"1" vardefault:"a" env:"a" flag:"avar,a" description:"a"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
cfg t
|
||||||
|
args []string
|
||||||
|
vardefaults map[string]string
|
||||||
|
)
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
SetVariableDefaults(vardefaults)
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Provided: Flag, Env, Default, VarDefault", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
args = []string{"-a", "5"}
|
||||||
|
os.Setenv("a", "8")
|
||||||
|
vardefaults = map[string]string{
|
||||||
|
"a": "3",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have used the flag value", func() {
|
||||||
|
Expect(cfg.A).To(Equal(5))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Provided: Env, Default, VarDefault", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
args = []string{}
|
||||||
|
os.Setenv("a", "8")
|
||||||
|
vardefaults = map[string]string{
|
||||||
|
"a": "3",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have used the env value", func() {
|
||||||
|
Expect(cfg.A).To(Equal(8))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Provided: Default, VarDefault", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
args = []string{}
|
||||||
|
os.Unsetenv("a")
|
||||||
|
vardefaults = map[string]string{
|
||||||
|
"a": "3",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have used the vardefault value", func() {
|
||||||
|
Expect(cfg.A).To(Equal(3))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Provided: Default", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
args = []string{}
|
||||||
|
os.Unsetenv("a")
|
||||||
|
vardefaults = map[string]string{}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have used the default value", func() {
|
||||||
|
Expect(cfg.A).To(Equal(1))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
13
vendor/github.com/Luzifer/rconfig/rconfig_suite_test.go
generated
vendored
Normal file
13
vendor/github.com/Luzifer/rconfig/rconfig_suite_test.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package rconfig_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRconfig(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "Rconfig Suite")
|
||||||
|
}
|
51
vendor/github.com/Luzifer/rconfig/slice_test.go
generated
vendored
Normal file
51
vendor/github.com/Luzifer/rconfig/slice_test.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing slices", func() {
|
||||||
|
type t struct {
|
||||||
|
Int []int `default:"1,2,3" flag:"int"`
|
||||||
|
String []string `default:"a,b,c" flag:"string"`
|
||||||
|
IntP []int `default:"1,2,3" flag:"intp,i"`
|
||||||
|
StringP []string `default:"a,b,c" flag:"stringp,s"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--int=4,5", "-s", "hallo,welt",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values for int-slice", func() {
|
||||||
|
Expect(len(cfg.Int)).To(Equal(2))
|
||||||
|
Expect(cfg.Int).To(Equal([]int{4, 5}))
|
||||||
|
Expect(cfg.Int).NotTo(Equal([]int{5, 4}))
|
||||||
|
})
|
||||||
|
It("should have the expected values for int-shorthand-slice", func() {
|
||||||
|
Expect(len(cfg.IntP)).To(Equal(3))
|
||||||
|
Expect(cfg.IntP).To(Equal([]int{1, 2, 3}))
|
||||||
|
})
|
||||||
|
It("should have the expected values for string-slice", func() {
|
||||||
|
Expect(len(cfg.String)).To(Equal(3))
|
||||||
|
Expect(cfg.String).To(Equal([]string{"a", "b", "c"}))
|
||||||
|
})
|
||||||
|
It("should have the expected values for string-shorthand-slice", func() {
|
||||||
|
Expect(len(cfg.StringP)).To(Equal(2))
|
||||||
|
Expect(cfg.StringP).To(Equal([]string{"hallo", "welt"}))
|
||||||
|
})
|
||||||
|
})
|
36
vendor/github.com/Luzifer/rconfig/sub-struct_test.go
generated
vendored
Normal file
36
vendor/github.com/Luzifer/rconfig/sub-struct_test.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing sub-structs", func() {
|
||||||
|
type t struct {
|
||||||
|
Test string `default:"blubb"`
|
||||||
|
Sub struct {
|
||||||
|
Test string `default:"Hallo"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.Test).To(Equal("blubb"))
|
||||||
|
Expect(cfg.Sub.Test).To(Equal("Hallo"))
|
||||||
|
})
|
||||||
|
})
|
59
vendor/github.com/Luzifer/rconfig/uint_test.go
generated
vendored
Normal file
59
vendor/github.com/Luzifer/rconfig/uint_test.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing uint parsing", func() {
|
||||||
|
type t struct {
|
||||||
|
Test uint `flag:"int"`
|
||||||
|
TestP uint `flag:"intp,i"`
|
||||||
|
Test8 uint8 `flag:"int8"`
|
||||||
|
Test8P uint8 `flag:"int8p,8"`
|
||||||
|
Test16 uint16 `flag:"int16"`
|
||||||
|
Test16P uint16 `flag:"int16p,1"`
|
||||||
|
Test32 uint32 `flag:"int32"`
|
||||||
|
Test32P uint32 `flag:"int32p,3"`
|
||||||
|
Test64 uint64 `flag:"int64"`
|
||||||
|
Test64P uint64 `flag:"int64p,6"`
|
||||||
|
TestDef uint8 `default:"66"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
args []string
|
||||||
|
cfg t
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
args = []string{
|
||||||
|
"--int=1", "-i", "2",
|
||||||
|
"--int8=3", "-8", "4",
|
||||||
|
"--int32=5", "-3", "6",
|
||||||
|
"--int64=7", "-6", "8",
|
||||||
|
"--int16=9", "-1", "10",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.Test).To(Equal(uint(1)))
|
||||||
|
Expect(cfg.TestP).To(Equal(uint(2)))
|
||||||
|
Expect(cfg.Test8).To(Equal(uint8(3)))
|
||||||
|
Expect(cfg.Test8P).To(Equal(uint8(4)))
|
||||||
|
Expect(cfg.Test32).To(Equal(uint32(5)))
|
||||||
|
Expect(cfg.Test32P).To(Equal(uint32(6)))
|
||||||
|
Expect(cfg.Test64).To(Equal(uint64(7)))
|
||||||
|
Expect(cfg.Test64P).To(Equal(uint64(8)))
|
||||||
|
Expect(cfg.Test16).To(Equal(uint16(9)))
|
||||||
|
Expect(cfg.Test16P).To(Equal(uint16(10)))
|
||||||
|
|
||||||
|
Expect(cfg.TestDef).To(Equal(uint8(66)))
|
||||||
|
})
|
||||||
|
})
|
122
vendor/github.com/Luzifer/rconfig/vardefault_test.go
generated
vendored
Normal file
122
vendor/github.com/Luzifer/rconfig/vardefault_test.go
generated
vendored
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package rconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Testing variable defaults", func() {
|
||||||
|
|
||||||
|
type t struct {
|
||||||
|
MySecretValue string `default:"secret" env:"foo" vardefault:"my_secret_value"`
|
||||||
|
MyUsername string `default:"luzifer" vardefault:"username"`
|
||||||
|
SomeVar string `flag:"var" description:"some variable"`
|
||||||
|
IntVar int64 `vardefault:"int_var" default:"23"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
cfg t
|
||||||
|
args = []string{}
|
||||||
|
vardefaults = map[string]string{
|
||||||
|
"my_secret_value": "veryverysecretkey",
|
||||||
|
"unkownkey": "hi there",
|
||||||
|
"int_var": "42",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
cfg = t{}
|
||||||
|
})
|
||||||
|
|
||||||
|
JustBeforeEach(func() {
|
||||||
|
err = parse(&cfg, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("With manually provided variables", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
SetVariableDefaults(vardefaults)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.IntVar).To(Equal(int64(42)))
|
||||||
|
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
||||||
|
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
||||||
|
Expect(cfg.SomeVar).To(Equal(""))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("With defaults from YAML data", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
yamlData := []byte("---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n")
|
||||||
|
SetVariableDefaults(VarDefaultsFromYAML(yamlData))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.IntVar).To(Equal(int64(42)))
|
||||||
|
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
||||||
|
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
||||||
|
Expect(cfg.SomeVar).To(Equal(""))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("With defaults from YAML file", func() {
|
||||||
|
var tmp *os.File
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
tmp, _ = ioutil.TempFile("", "")
|
||||||
|
yamlData := "---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n"
|
||||||
|
tmp.WriteString(yamlData)
|
||||||
|
SetVariableDefaults(VarDefaultsFromYAMLFile(tmp.Name()))
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
tmp.Close()
|
||||||
|
os.Remove(tmp.Name())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.IntVar).To(Equal(int64(42)))
|
||||||
|
Expect(cfg.MySecretValue).To(Equal("veryverysecretkey"))
|
||||||
|
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
||||||
|
Expect(cfg.SomeVar).To(Equal(""))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("With defaults from invalid YAML data", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
yamlData := []byte("---\nmy_secret_value = veryverysecretkey\nunknownkey = hi there\nint_var = 42\n")
|
||||||
|
SetVariableDefaults(VarDefaultsFromYAML(yamlData))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.IntVar).To(Equal(int64(23)))
|
||||||
|
Expect(cfg.MySecretValue).To(Equal("secret"))
|
||||||
|
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
||||||
|
Expect(cfg.SomeVar).To(Equal(""))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("With defaults from non existent YAML file", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
file := "/tmp/this_file_should_not_exist_146e26723r"
|
||||||
|
SetVariableDefaults(VarDefaultsFromYAMLFile(file))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not have errored", func() { Expect(err).NotTo(HaveOccurred()) })
|
||||||
|
It("should have the expected values", func() {
|
||||||
|
Expect(cfg.IntVar).To(Equal(int64(23)))
|
||||||
|
Expect(cfg.MySecretValue).To(Equal("secret"))
|
||||||
|
Expect(cfg.MyUsername).To(Equal("luzifer"))
|
||||||
|
Expect(cfg.SomeVar).To(Equal(""))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
14
vendor/github.com/aws/aws-sdk-go/.github/ISSUE_TEMPLATE.md
generated
vendored
Normal file
14
vendor/github.com/aws/aws-sdk-go/.github/ISSUE_TEMPLATE.md
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Please fill out the sections below to help us address your issue.
|
||||||
|
|
||||||
|
### Version of AWS SDK for Go?
|
||||||
|
|
||||||
|
|
||||||
|
### Version of Go (`go version`)?
|
||||||
|
|
||||||
|
|
||||||
|
### What issue did you see?
|
||||||
|
|
||||||
|
### Steps to reproduce
|
||||||
|
|
||||||
|
If you have have an runnable example, please include it.
|
||||||
|
|
3
vendor/github.com/aws/aws-sdk-go/.github/PULL_REQUEST_TEMPLATE.md
generated
vendored
Normal file
3
vendor/github.com/aws/aws-sdk-go/.github/PULL_REQUEST_TEMPLATE.md
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
For changes to files under the `/model/` folder, and manual edits to autogenerated code (e.g. `/service/s3/api.go`) please create an Issue instead of a PR for those type of changes.
|
||||||
|
|
||||||
|
If there is an existing bug or feature this PR is answers please reference it here.
|
11
vendor/github.com/aws/aws-sdk-go/.gitignore
generated
vendored
Normal file
11
vendor/github.com/aws/aws-sdk-go/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
dist
|
||||||
|
/doc
|
||||||
|
/doc-staging
|
||||||
|
.yardoc
|
||||||
|
Gemfile.lock
|
||||||
|
awstesting/integration/smoke/**/importmarker__.go
|
||||||
|
awstesting/integration/smoke/_test/
|
||||||
|
/vendor/bin/
|
||||||
|
/vendor/pkg/
|
||||||
|
/vendor/src/
|
||||||
|
/private/model/cli/gen-api/gen-api
|
14
vendor/github.com/aws/aws-sdk-go/.godoc_config
generated
vendored
Normal file
14
vendor/github.com/aws/aws-sdk-go/.godoc_config
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"PkgHandler": {
|
||||||
|
"Pattern": "/sdk-for-go/api/",
|
||||||
|
"StripPrefix": "/sdk-for-go/api",
|
||||||
|
"Include": ["/src/github.com/aws/aws-sdk-go/aws", "/src/github.com/aws/aws-sdk-go/service"],
|
||||||
|
"Exclude": ["/src/cmd", "/src/github.com/aws/aws-sdk-go/awstesting", "/src/github.com/aws/aws-sdk-go/awsmigrate"],
|
||||||
|
"IgnoredSuffixes": ["iface"]
|
||||||
|
},
|
||||||
|
"Github": {
|
||||||
|
"Tag": "master",
|
||||||
|
"Repo": "/aws/aws-sdk-go",
|
||||||
|
"UseGithub": true
|
||||||
|
}
|
||||||
|
}
|
29
vendor/github.com/aws/aws-sdk-go/.travis.yml
generated
vendored
Normal file
29
vendor/github.com/aws/aws-sdk-go/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
sudo: required
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.5.x
|
||||||
|
- 1.6.x
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
# Use Go 1.5's vendoring experiment for 1.5 tests.
|
||||||
|
env:
|
||||||
|
- GO15VENDOREXPERIMENT=1
|
||||||
|
|
||||||
|
install:
|
||||||
|
- make get-deps
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make unit-with-race-cover
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
2296
vendor/github.com/aws/aws-sdk-go/CHANGELOG.md
generated
vendored
Normal file
2296
vendor/github.com/aws/aws-sdk-go/CHANGELOG.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
5
vendor/github.com/aws/aws-sdk-go/CHANGELOG_PENDING.md
generated
vendored
Normal file
5
vendor/github.com/aws/aws-sdk-go/CHANGELOG_PENDING.md
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
### SDK Features
|
||||||
|
|
||||||
|
### SDK Enhancements
|
||||||
|
|
||||||
|
### SDK Bugs
|
127
vendor/github.com/aws/aws-sdk-go/CONTRIBUTING.md
generated
vendored
Normal file
127
vendor/github.com/aws/aws-sdk-go/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
Contributing to the AWS SDK for Go
|
||||||
|
|
||||||
|
We work hard to provide a high-quality and useful SDK, and we greatly value
|
||||||
|
feedback and contributions from our community. Whether it's a bug report,
|
||||||
|
new feature, correction, or additional documentation, we welcome your issues
|
||||||
|
and pull requests. Please read through this document before submitting any
|
||||||
|
issues or pull requests to ensure we have all the necessary information to
|
||||||
|
effectively respond to your bug report or contribution.
|
||||||
|
|
||||||
|
|
||||||
|
## Filing Bug Reports
|
||||||
|
|
||||||
|
You can file bug reports against the SDK on the [GitHub issues][issues] page.
|
||||||
|
|
||||||
|
If you are filing a report for a bug or regression in the SDK, it's extremely
|
||||||
|
helpful to provide as much information as possible when opening the original
|
||||||
|
issue. This helps us reproduce and investigate the possible bug without having
|
||||||
|
to wait for this extra information to be provided. Please read the following
|
||||||
|
guidelines prior to filing a bug report.
|
||||||
|
|
||||||
|
1. Search through existing [issues][] to ensure that your specific issue has
|
||||||
|
not yet been reported. If it is a common issue, it is likely there is
|
||||||
|
already a bug report for your problem.
|
||||||
|
|
||||||
|
2. Ensure that you have tested the latest version of the SDK. Although you
|
||||||
|
may have an issue against an older version of the SDK, we cannot provide
|
||||||
|
bug fixes for old versions. It's also possible that the bug may have been
|
||||||
|
fixed in the latest release.
|
||||||
|
|
||||||
|
3. Provide as much information about your environment, SDK version, and
|
||||||
|
relevant dependencies as possible. For example, let us know what version
|
||||||
|
of Go you are using, which and version of the operating system, and the
|
||||||
|
the environment your code is running in. e.g Container.
|
||||||
|
|
||||||
|
4. Provide a minimal test case that reproduces your issue or any error
|
||||||
|
information you related to your problem. We can provide feedback much
|
||||||
|
more quickly if we know what operations you are calling in the SDK. If
|
||||||
|
you cannot provide a full test case, provide as much code as you can
|
||||||
|
to help us diagnose the problem. Any relevant information should be provided
|
||||||
|
as well, like whether this is a persistent issue, or if it only occurs
|
||||||
|
some of the time.
|
||||||
|
|
||||||
|
|
||||||
|
## Submitting Pull Requests
|
||||||
|
|
||||||
|
We are always happy to receive code and documentation contributions to the SDK.
|
||||||
|
Please be aware of the following notes prior to opening a pull request:
|
||||||
|
|
||||||
|
1. The SDK is released under the [Apache license][license]. Any code you submit
|
||||||
|
will be released under that license. For substantial contributions, we may
|
||||||
|
ask you to sign a [Contributor License Agreement (CLA)][cla].
|
||||||
|
|
||||||
|
2. If you would like to implement support for a significant feature that is not
|
||||||
|
yet available in the SDK, please talk to us beforehand to avoid any
|
||||||
|
duplication of effort.
|
||||||
|
|
||||||
|
3. Wherever possible, pull requests should contain tests as appropriate.
|
||||||
|
Bugfixes should contain tests that exercise the corrected behavior (i.e., the
|
||||||
|
test should fail without the bugfix and pass with it), and new features
|
||||||
|
should be accompanied by tests exercising the feature.
|
||||||
|
|
||||||
|
4. Pull requests that contain failing tests will not be merged until the test
|
||||||
|
failures are addressed. Pull requests that cause a significant drop in the
|
||||||
|
SDK's test coverage percentage are unlikely to be merged until tests have
|
||||||
|
been added.
|
||||||
|
|
||||||
|
5. The JSON files under the SDK's `models` folder are sourced from outside the SDK.
|
||||||
|
Such as `models/apis/ec2/2016-11-15/api.json`. We will not accept pull requests
|
||||||
|
directly on these models. If you discover an issue with the models please
|
||||||
|
create a [GitHub issue][issues] describing the issue.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
To run the tests locally, running the `make unit` command will `go get` the
|
||||||
|
SDK's testing dependencies, and run vet, link and unit tests for the SDK.
|
||||||
|
|
||||||
|
```
|
||||||
|
make unit
|
||||||
|
```
|
||||||
|
|
||||||
|
Standard go testing functionality is supported as well. To test SDK code that
|
||||||
|
is tagged with `codegen` you'll need to set the build tag in the go test
|
||||||
|
command. The `make unit` command will do this automatically.
|
||||||
|
|
||||||
|
```
|
||||||
|
go test -tags codegen ./private/...
|
||||||
|
```
|
||||||
|
|
||||||
|
See the `Makefile` for additional testing tags that can be used in testing.
|
||||||
|
|
||||||
|
To test on multiple platform the SDK includes several DockerFiles under the
|
||||||
|
`awstesting/sandbox` folder, and associated make recipes to to execute
|
||||||
|
unit testing within environments configured for specific Go versions.
|
||||||
|
|
||||||
|
```
|
||||||
|
make sandbox-test-go18
|
||||||
|
```
|
||||||
|
|
||||||
|
To run all sandbox environments use the following make recipe
|
||||||
|
|
||||||
|
```
|
||||||
|
# Optionally update the Go tip that will be used during the batch testing
|
||||||
|
make update-aws-golang-tip
|
||||||
|
|
||||||
|
# Run all SDK tests for supported Go versions in sandboxes
|
||||||
|
make sandbox-test
|
||||||
|
```
|
||||||
|
|
||||||
|
In addition the sandbox environment include make recipes for interactive modes
|
||||||
|
so you can run command within the Docker container and context of the SDK.
|
||||||
|
|
||||||
|
```
|
||||||
|
make sandbox-go18
|
||||||
|
```
|
||||||
|
|
||||||
|
### Changelog
|
||||||
|
|
||||||
|
You can see all release changes in the `CHANGELOG.md` file at the root of the
|
||||||
|
repository. The release notes added to this file will contain service client
|
||||||
|
updates, and major SDK changes.
|
||||||
|
|
||||||
|
[issues]: https://github.com/aws/aws-sdk-go/issues
|
||||||
|
[pr]: https://github.com/aws/aws-sdk-go/pulls
|
||||||
|
[license]: http://aws.amazon.com/apache2.0/
|
||||||
|
[cla]: http://en.wikipedia.org/wiki/Contributor_License_Agreement
|
||||||
|
[releasenotes]: https://github.com/aws/aws-sdk-go/releases
|
||||||
|
|
20
vendor/github.com/aws/aws-sdk-go/Gopkg.lock
generated
vendored
Normal file
20
vendor/github.com/aws/aws-sdk-go/Gopkg.lock
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/go-ini/ini"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "300e940a926eb277d3901b20bdfcc54928ad3642"
|
||||||
|
version = "v1.25.4"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/jmespath/go-jmespath"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "0b12d6b5"
|
||||||
|
|
||||||
|
[solve-meta]
|
||||||
|
analyzer-name = "dep"
|
||||||
|
analyzer-version = 1
|
||||||
|
inputs-digest = "51a86a867df617990082dec6b868e4efe2fdb2ed0e02a3daa93cd30f962b5085"
|
||||||
|
solver-name = "gps-cdcl"
|
||||||
|
solver-version = 1
|
48
vendor/github.com/aws/aws-sdk-go/Gopkg.toml
generated
vendored
Normal file
48
vendor/github.com/aws/aws-sdk-go/Gopkg.toml
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
# Gopkg.toml example
|
||||||
|
#
|
||||||
|
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||||
|
# for detailed Gopkg.toml documentation.
|
||||||
|
#
|
||||||
|
# required = ["github.com/user/thing/cmd/thing"]
|
||||||
|
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project"
|
||||||
|
# version = "1.0.0"
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project2"
|
||||||
|
# branch = "dev"
|
||||||
|
# source = "github.com/myfork/project2"
|
||||||
|
#
|
||||||
|
# [[override]]
|
||||||
|
# name = "github.com/x/y"
|
||||||
|
# version = "2.4.0"
|
||||||
|
|
||||||
|
ignored = [
|
||||||
|
# Testing/Example/Codegen dependencies
|
||||||
|
"github.com/stretchr/testify",
|
||||||
|
"github.com/stretchr/testify/assert",
|
||||||
|
"github.com/stretchr/testify/require",
|
||||||
|
"github.com/go-sql-driver/mysql",
|
||||||
|
"github.com/gucumber/gucumber",
|
||||||
|
"github.com/pkg/errors",
|
||||||
|
"golang.org/x/net",
|
||||||
|
"golang.org/x/net/html",
|
||||||
|
"golang.org/x/net/http2",
|
||||||
|
"golang.org/x/text",
|
||||||
|
"golang.org/x/text/html",
|
||||||
|
"golang.org/x/tools",
|
||||||
|
"golang.org/x/tools/go/loader",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/go-ini/ini"
|
||||||
|
version = "1.25.4"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/jmespath/go-jmespath"
|
||||||
|
revision = "0b12d6b5"
|
||||||
|
#version = "0.2.2"
|
187
vendor/github.com/aws/aws-sdk-go/Makefile
generated
vendored
Normal file
187
vendor/github.com/aws/aws-sdk-go/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
LINTIGNOREDOT='awstesting/integration.+should not use dot imports'
|
||||||
|
LINTIGNOREDOC='service/[^/]+/(api|service|waiters)\.go:.+(comment on exported|should have comment or be unexported)'
|
||||||
|
LINTIGNORECONST='service/[^/]+/(api|service|waiters)\.go:.+(type|struct field|const|func) ([^ ]+) should be ([^ ]+)'
|
||||||
|
LINTIGNORESTUTTER='service/[^/]+/(api|service)\.go:.+(and that stutters)'
|
||||||
|
LINTIGNOREINFLECT='service/[^/]+/(api|errors|service)\.go:.+(method|const) .+ should be '
|
||||||
|
LINTIGNOREINFLECTS3UPLOAD='service/s3/s3manager/upload\.go:.+struct field SSEKMSKeyId should be '
|
||||||
|
LINTIGNOREDEPS='vendor/.+\.go'
|
||||||
|
LINTIGNOREPKGCOMMENT='service/[^/]+/doc_custom.go:.+package comment should be of the form'
|
||||||
|
UNIT_TEST_TAGS="example codegen awsinclude"
|
||||||
|
|
||||||
|
SDK_WITH_VENDOR_PKGS=$(shell go list -tags ${UNIT_TEST_TAGS} ./... | grep -v "/vendor/src")
|
||||||
|
SDK_ONLY_PKGS=$(shell go list ./... | grep -v "/vendor/")
|
||||||
|
SDK_UNIT_TEST_ONLY_PKGS=$(shell go list -tags ${UNIT_TEST_TAGS} ./... | grep -v "/vendor/")
|
||||||
|
SDK_GO_1_4=$(shell go version | grep "go1.4")
|
||||||
|
SDK_GO_1_5=$(shell go version | grep "go1.5")
|
||||||
|
SDK_GO_VERSION=$(shell go version | awk '''{print $$3}''' | tr -d '''\n''')
|
||||||
|
|
||||||
|
all: get-deps generate unit
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " api_info to print a list of services and versions"
|
||||||
|
@echo " docs to build SDK documentation"
|
||||||
|
@echo " build to go build the SDK"
|
||||||
|
@echo " unit to run unit tests"
|
||||||
|
@echo " integration to run integration tests"
|
||||||
|
@echo " performance to run performance tests"
|
||||||
|
@echo " verify to verify tests"
|
||||||
|
@echo " lint to lint the SDK"
|
||||||
|
@echo " vet to vet the SDK"
|
||||||
|
@echo " generate to go generate and make services"
|
||||||
|
@echo " gen-test to generate protocol tests"
|
||||||
|
@echo " gen-services to generate services"
|
||||||
|
@echo " get-deps to go get the SDK dependencies"
|
||||||
|
@echo " get-deps-tests to get the SDK's test dependencies"
|
||||||
|
@echo " get-deps-verify to get the SDK's verification dependencies"
|
||||||
|
|
||||||
|
generate: gen-test gen-endpoints gen-services
|
||||||
|
|
||||||
|
gen-test: gen-protocol-test
|
||||||
|
|
||||||
|
gen-services:
|
||||||
|
go generate ./service
|
||||||
|
|
||||||
|
gen-protocol-test:
|
||||||
|
go generate ./private/protocol/...
|
||||||
|
|
||||||
|
gen-endpoints:
|
||||||
|
go generate ./models/endpoints/
|
||||||
|
|
||||||
|
build:
|
||||||
|
@echo "go build SDK and vendor packages"
|
||||||
|
@go build ${SDK_ONLY_PKGS}
|
||||||
|
|
||||||
|
unit: get-deps-tests build verify
|
||||||
|
@echo "go test SDK and vendor packages"
|
||||||
|
@go test -tags ${UNIT_TEST_TAGS} $(SDK_UNIT_TEST_ONLY_PKGS)
|
||||||
|
|
||||||
|
unit-with-race-cover: get-deps-tests build verify
|
||||||
|
@echo "go test SDK and vendor packages"
|
||||||
|
@go test -tags ${UNIT_TEST_TAGS} -race -cpu=1,2,4 $(SDK_UNIT_TEST_ONLY_PKGS)
|
||||||
|
|
||||||
|
integration: get-deps-tests integ-custom smoke-tests performance
|
||||||
|
|
||||||
|
integ-custom:
|
||||||
|
go test -tags "integration" ./awstesting/integration/customizations/...
|
||||||
|
|
||||||
|
cleanup-integ:
|
||||||
|
go run -tags "integration" ./awstesting/cmd/bucket_cleanup/main.go "aws-sdk-go-integration"
|
||||||
|
|
||||||
|
smoke-tests: get-deps-tests
|
||||||
|
gucumber -go-tags "integration" ./awstesting/integration/smoke
|
||||||
|
|
||||||
|
performance: get-deps-tests
|
||||||
|
AWS_TESTING_LOG_RESULTS=${log-detailed} AWS_TESTING_REGION=$(region) AWS_TESTING_DB_TABLE=$(table) gucumber -go-tags "integration" ./awstesting/performance
|
||||||
|
|
||||||
|
sandbox-tests: sandbox-test-go15 sandbox-test-go15-novendorexp sandbox-test-go16 sandbox-test-go17 sandbox-test-go18 sandbox-test-go19 sandbox-test-gotip
|
||||||
|
|
||||||
|
sandbox-build-go15:
|
||||||
|
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.5 -t "aws-sdk-go-1.5" .
|
||||||
|
sandbox-go15: sandbox-build-go15
|
||||||
|
docker run -i -t aws-sdk-go-1.5 bash
|
||||||
|
sandbox-test-go15: sandbox-build-go15
|
||||||
|
docker run -t aws-sdk-go-1.5
|
||||||
|
|
||||||
|
sandbox-build-go15-novendorexp:
|
||||||
|
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.5-novendorexp -t "aws-sdk-go-1.5-novendorexp" .
|
||||||
|
sandbox-go15-novendorexp: sandbox-build-go15-novendorexp
|
||||||
|
docker run -i -t aws-sdk-go-1.5-novendorexp bash
|
||||||
|
sandbox-test-go15-novendorexp: sandbox-build-go15-novendorexp
|
||||||
|
docker run -t aws-sdk-go-1.5-novendorexp
|
||||||
|
|
||||||
|
sandbox-build-go16:
|
||||||
|
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.6 -t "aws-sdk-go-1.6" .
|
||||||
|
sandbox-go16: sandbox-build-go16
|
||||||
|
docker run -i -t aws-sdk-go-1.6 bash
|
||||||
|
sandbox-test-go16: sandbox-build-go16
|
||||||
|
docker run -t aws-sdk-go-1.6
|
||||||
|
|
||||||
|
sandbox-build-go17:
|
||||||
|
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.7 -t "aws-sdk-go-1.7" .
|
||||||
|
sandbox-go17: sandbox-build-go17
|
||||||
|
docker run -i -t aws-sdk-go-1.7 bash
|
||||||
|
sandbox-test-go17: sandbox-build-go17
|
||||||
|
docker run -t aws-sdk-go-1.7
|
||||||
|
|
||||||
|
sandbox-build-go18:
|
||||||
|
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.8 -t "aws-sdk-go-1.8" .
|
||||||
|
sandbox-go18: sandbox-build-go18
|
||||||
|
docker run -i -t aws-sdk-go-1.8 bash
|
||||||
|
sandbox-test-go18: sandbox-build-go18
|
||||||
|
docker run -t aws-sdk-go-1.8
|
||||||
|
|
||||||
|
sandbox-build-go19:
|
||||||
|
docker build -f ./awstesting/sandbox/Dockerfile.test.go1.8 -t "aws-sdk-go-1.9" .
|
||||||
|
sandbox-go19: sandbox-build-go19
|
||||||
|
docker run -i -t aws-sdk-go-1.9 bash
|
||||||
|
sandbox-test-go19: sandbox-build-go19
|
||||||
|
docker run -t aws-sdk-go-1.9
|
||||||
|
|
||||||
|
sandbox-build-gotip:
|
||||||
|
@echo "Run make update-aws-golang-tip, if this test fails because missing aws-golang:tip container"
|
||||||
|
docker build -f ./awstesting/sandbox/Dockerfile.test.gotip -t "aws-sdk-go-tip" .
|
||||||
|
sandbox-gotip: sandbox-build-gotip
|
||||||
|
docker run -i -t aws-sdk-go-tip bash
|
||||||
|
sandbox-test-gotip: sandbox-build-gotip
|
||||||
|
docker run -t aws-sdk-go-tip
|
||||||
|
|
||||||
|
update-aws-golang-tip:
|
||||||
|
docker build --no-cache=true -f ./awstesting/sandbox/Dockerfile.golang-tip -t "aws-golang:tip" .
|
||||||
|
|
||||||
|
verify: get-deps-verify lint vet
|
||||||
|
|
||||||
|
lint:
|
||||||
|
@echo "go lint SDK and vendor packages"
|
||||||
|
@lint=`if [ \( -z "${SDK_GO_1_4}" \) -a \( -z "${SDK_GO_1_5}" \) ]; then golint ./...; else echo "skipping golint"; fi`; \
|
||||||
|
lint=`echo "$$lint" | grep -E -v -e ${LINTIGNOREDOT} -e ${LINTIGNOREDOC} -e ${LINTIGNORECONST} -e ${LINTIGNORESTUTTER} -e ${LINTIGNOREINFLECT} -e ${LINTIGNOREDEPS} -e ${LINTIGNOREINFLECTS3UPLOAD} -e ${LINTIGNOREPKGCOMMENT}`; \
|
||||||
|
echo "$$lint"; \
|
||||||
|
if [ "$$lint" != "" ] && [ "$$lint" != "skipping golint" ]; then exit 1; fi
|
||||||
|
|
||||||
|
SDK_BASE_FOLDERS=$(shell ls -d */ | grep -v vendor | grep -v awsmigrate)
|
||||||
|
ifneq (,$(findstring go1.4, ${SDK_GO_VERSION}))
|
||||||
|
GO_VET_CMD=echo skipping go vet, ${SDK_GO_VERSION}
|
||||||
|
else ifneq (,$(findstring go1.6, ${SDK_GO_VERSION}))
|
||||||
|
GO_VET_CMD=go tool vet --all -shadow -example=false
|
||||||
|
else
|
||||||
|
GO_VET_CMD=go tool vet --all -shadow
|
||||||
|
endif
|
||||||
|
|
||||||
|
vet:
|
||||||
|
${GO_VET_CMD} ${SDK_BASE_FOLDERS}
|
||||||
|
|
||||||
|
get-deps: get-deps-tests get-deps-verify
|
||||||
|
@echo "go get SDK dependencies"
|
||||||
|
@go get -v $(SDK_ONLY_PKGS)
|
||||||
|
|
||||||
|
get-deps-tests:
|
||||||
|
@echo "go get SDK testing dependencies"
|
||||||
|
go get github.com/gucumber/gucumber/cmd/gucumber
|
||||||
|
go get github.com/stretchr/testify
|
||||||
|
go get github.com/smartystreets/goconvey
|
||||||
|
go get golang.org/x/net/html
|
||||||
|
go get golang.org/x/net/http2
|
||||||
|
|
||||||
|
get-deps-verify:
|
||||||
|
@echo "go get SDK verification utilities"
|
||||||
|
@if [ \( -z "${SDK_GO_1_4}" \) -a \( -z "${SDK_GO_1_5}" \) ]; then go get github.com/golang/lint/golint; else echo "skipped getting golint"; fi
|
||||||
|
|
||||||
|
bench:
|
||||||
|
@echo "go bench SDK packages"
|
||||||
|
@go test -run NONE -bench . -benchmem -tags 'bench' $(SDK_ONLY_PKGS)
|
||||||
|
|
||||||
|
bench-protocol:
|
||||||
|
@echo "go bench SDK protocol marshallers"
|
||||||
|
@go test -run NONE -bench . -benchmem -tags 'bench' ./private/protocol/...
|
||||||
|
|
||||||
|
docs:
|
||||||
|
@echo "generate SDK docs"
|
||||||
|
@# This env variable, DOCS, is for internal use
|
||||||
|
@if [ -z ${AWS_DOC_GEN_TOOL} ]; then\
|
||||||
|
rm -rf doc && bundle install && bundle exec yard;\
|
||||||
|
else\
|
||||||
|
$(AWS_DOC_GEN_TOOL) `pwd`;\
|
||||||
|
fi
|
||||||
|
|
||||||
|
api_info:
|
||||||
|
@go run private/model/cli/api-info/api-info.go
|
449
vendor/github.com/aws/aws-sdk-go/README.md
generated
vendored
Normal file
449
vendor/github.com/aws/aws-sdk-go/README.md
generated
vendored
Normal file
|
@ -0,0 +1,449 @@
|
||||||
|
[![API Reference](http://img.shields.io/badge/api-reference-blue.svg)](http://docs.aws.amazon.com/sdk-for-go/api) [![Join the chat at https://gitter.im/aws/aws-sdk-go](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/aws/aws-sdk-go?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://img.shields.io/travis/aws/aws-sdk-go.svg)](https://travis-ci.org/aws/aws-sdk-go) [![Apache V2 License](http://img.shields.io/badge/license-Apache%20V2-blue.svg)](https://github.com/aws/aws-sdk-go/blob/master/LICENSE.txt)
|
||||||
|
|
||||||
|
# AWS SDK for Go
|
||||||
|
|
||||||
|
aws-sdk-go is the official AWS SDK for the Go programming language.
|
||||||
|
|
||||||
|
Checkout our [release notes](https://github.com/aws/aws-sdk-go/releases) for information about the latest bug fixes, updates, and features added to the SDK.
|
||||||
|
|
||||||
|
## Installing
|
||||||
|
|
||||||
|
If you are using Go 1.5 with the `GO15VENDOREXPERIMENT=1` vendoring flag, or 1.6 and higher you can use the following command to retrieve the SDK. The SDK's non-testing dependencies will be included and are vendored in the `vendor` folder.
|
||||||
|
|
||||||
|
go get -u github.com/aws/aws-sdk-go
|
||||||
|
|
||||||
|
Otherwise if your Go environment does not have vendoring support enabled, or you do not want to include the vendored SDK's dependencies you can use the following command to retrieve the SDK and its non-testing dependencies using `go get`.
|
||||||
|
|
||||||
|
go get -u github.com/aws/aws-sdk-go/aws/...
|
||||||
|
go get -u github.com/aws/aws-sdk-go/service/...
|
||||||
|
|
||||||
|
If you're looking to retrieve just the SDK without any dependencies use the following command.
|
||||||
|
|
||||||
|
go get -d github.com/aws/aws-sdk-go/
|
||||||
|
|
||||||
|
These two processes will still include the `vendor` folder and it should be deleted if its not going to be used by your environment.
|
||||||
|
|
||||||
|
rm -rf $GOPATH/src/github.com/aws/aws-sdk-go/vendor
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
Please use these community resources for getting help. We use the GitHub issues for tracking bugs and feature requests.
|
||||||
|
|
||||||
|
* Ask a question on [StackOverflow](http://stackoverflow.com/) and tag it with the [`aws-sdk-go`](http://stackoverflow.com/questions/tagged/aws-sdk-go) tag.
|
||||||
|
* Come join the AWS SDK for Go community chat on [gitter](https://gitter.im/aws/aws-sdk-go).
|
||||||
|
* Open a support ticket with [AWS Support](http://docs.aws.amazon.com/awssupport/latest/user/getting-started.html).
|
||||||
|
* If you think you may have found a bug, please open an [issue](https://github.com/aws/aws-sdk-go/issues/new).
|
||||||
|
|
||||||
|
## Opening Issues
|
||||||
|
|
||||||
|
If you encounter a bug with the AWS SDK for Go we would like to hear about it. Search the [existing issues](https://github.com/aws/aws-sdk-go/issues) and see if others are also experiencing the issue before opening a new issue. Please include the version of AWS SDK for Go, Go language, and OS you’re using. Please also include repro case when appropriate.
|
||||||
|
|
||||||
|
The GitHub issues are intended for bug reports and feature requests. For help and questions with using AWS SDK for GO please make use of the resources listed in the [Getting Help](https://github.com/aws/aws-sdk-go#getting-help) section. Keeping the list of open issues lean will help us respond in a timely manner.
|
||||||
|
|
||||||
|
## Reference Documentation
|
||||||
|
|
||||||
|
[`Getting Started Guide`](https://aws.amazon.com/sdk-for-go/) - This document is a general introduction how to configure and make requests with the SDK. If this is your first time using the SDK, this documentation and the API documentation will help you get started. This document focuses on the syntax and behavior of the SDK. The [Service Developer Guide](https://aws.amazon.com/documentation/) will help you get started using specific AWS services.
|
||||||
|
|
||||||
|
[`SDK API Reference Documentation`](https://docs.aws.amazon.com/sdk-for-go/api/) - Use this document to look up all API operation input and output parameters for AWS services supported by the SDK. The API reference also includes documentation of the SDK, and examples how to using the SDK, service client API operations, and API operation require parameters.
|
||||||
|
|
||||||
|
[`Service Developer Guide`](https://aws.amazon.com/documentation/) - Use this documentation to learn how to interface with an AWS service. These are great guides both, if you're getting started with a service, or looking for more information on a service. You should not need this document for coding, though in some cases, services may supply helpful samples that you might want to look out for.
|
||||||
|
|
||||||
|
[`SDK Examples`](https://github.com/aws/aws-sdk-go/tree/master/example) - Included in the SDK's repo are a several hand crafted examples using the SDK features and AWS services.
|
||||||
|
|
||||||
|
## Overview of SDK's Packages
|
||||||
|
|
||||||
|
The SDK is composed of two main components, SDK core, and service clients.
|
||||||
|
The SDK core packages are all available under the aws package at the root of
|
||||||
|
the SDK. Each client for a supported AWS service is available within its own
|
||||||
|
package under the service folder at the root of the SDK.
|
||||||
|
|
||||||
|
* aws - SDK core, provides common shared types such as Config, Logger,
|
||||||
|
and utilities to make working with API parameters easier.
|
||||||
|
|
||||||
|
* awserr - Provides the error interface that the SDK will use for all
|
||||||
|
errors that occur in the SDK's processing. This includes service API
|
||||||
|
response errors as well. The Error type is made up of a code and message.
|
||||||
|
Cast the SDK's returned error type to awserr.Error and call the Code
|
||||||
|
method to compare returned error to specific error codes. See the package's
|
||||||
|
documentation for additional values that can be extracted such as RequestID.
|
||||||
|
|
||||||
|
* credentials - Provides the types and built in credentials providers
|
||||||
|
the SDK will use to retrieve AWS credentials to make API requests with.
|
||||||
|
Nested under this folder are also additional credentials providers such as
|
||||||
|
stscreds for assuming IAM roles, and ec2rolecreds for EC2 Instance roles.
|
||||||
|
|
||||||
|
* endpoints - Provides the AWS Regions and Endpoints metadata for the SDK.
|
||||||
|
Use this to lookup AWS service endpoint information such as which services
|
||||||
|
are in a region, and what regions a service is in. Constants are also provided
|
||||||
|
for all region identifiers, e.g UsWest2RegionID for "us-west-2".
|
||||||
|
|
||||||
|
* session - Provides initial default configuration, and load
|
||||||
|
configuration from external sources such as environment and shared
|
||||||
|
credentials file.
|
||||||
|
|
||||||
|
* request - Provides the API request sending, and retry logic for the SDK.
|
||||||
|
This package also includes utilities for defining your own request
|
||||||
|
retryer, and configuring how the SDK processes the request.
|
||||||
|
|
||||||
|
* service - Clients for AWS services. All services supported by the SDK are
|
||||||
|
available under this folder.
|
||||||
|
|
||||||
|
## How to Use the SDK's AWS Service Clients
|
||||||
|
|
||||||
|
The SDK includes the Go types and utilities you can use to make requests to
|
||||||
|
AWS service APIs. Within the service folder at the root of the SDK you'll find
|
||||||
|
a package for each AWS service the SDK supports. All service clients follows
|
||||||
|
a common pattern of creation and usage.
|
||||||
|
|
||||||
|
When creating a client for an AWS service you'll first need to have a Session
|
||||||
|
value constructed. The Session provides shared configuration that can be shared
|
||||||
|
between your service clients. When service clients are created you can pass
|
||||||
|
in additional configuration via the aws.Config type to override configuration
|
||||||
|
provided by in the Session to create service client instances with custom
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
Once the service's client is created you can use it to make API requests the
|
||||||
|
AWS service. These clients are safe to use concurrently.
|
||||||
|
|
||||||
|
## Configuring the SDK
|
||||||
|
|
||||||
|
In the AWS SDK for Go, you can configure settings for service clients, such
|
||||||
|
as the log level and maximum number of retries. Most settings are optional;
|
||||||
|
however, for each service client, you must specify a region and your credentials.
|
||||||
|
The SDK uses these values to send requests to the correct AWS region and sign
|
||||||
|
requests with the correct credentials. You can specify these values as part
|
||||||
|
of a session or as environment variables.
|
||||||
|
|
||||||
|
See the SDK's [configuration guide][config_guide] for more information.
|
||||||
|
|
||||||
|
See the [session][session_pkg] package documentation for more information on how to use Session
|
||||||
|
with the SDK.
|
||||||
|
|
||||||
|
See the [Config][config_typ] type in the [aws][aws_pkg] package for more information on configuration
|
||||||
|
options.
|
||||||
|
|
||||||
|
[config_guide]: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html
|
||||||
|
[session_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/session/
|
||||||
|
[config_typ]: https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
|
||||||
|
[aws_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/
|
||||||
|
|
||||||
|
### Configuring Credentials
|
||||||
|
|
||||||
|
When using the SDK you'll generally need your AWS credentials to authenticate
|
||||||
|
with AWS services. The SDK supports multiple methods of supporting these
|
||||||
|
credentials. By default the SDK will source credentials automatically from
|
||||||
|
its default credential chain. See the session package for more information
|
||||||
|
on this chain, and how to configure it. The common items in the credential
|
||||||
|
chain are the following:
|
||||||
|
|
||||||
|
* Environment Credentials - Set of environment variables that are useful
|
||||||
|
when sub processes are created for specific roles.
|
||||||
|
|
||||||
|
* Shared Credentials file (~/.aws/credentials) - This file stores your
|
||||||
|
credentials based on a profile name and is useful for local development.
|
||||||
|
|
||||||
|
* EC2 Instance Role Credentials - Use EC2 Instance Role to assign credentials
|
||||||
|
to application running on an EC2 instance. This removes the need to manage
|
||||||
|
credential files in production.
|
||||||
|
|
||||||
|
Credentials can be configured in code as well by setting the Config's Credentials
|
||||||
|
value to a custom provider or using one of the providers included with the
|
||||||
|
SDK to bypass the default credential chain and use a custom one. This is
|
||||||
|
helpful when you want to instruct the SDK to only use a specific set of
|
||||||
|
credentials or providers.
|
||||||
|
|
||||||
|
This example creates a credential provider for assuming an IAM role, "myRoleARN"
|
||||||
|
and configures the S3 service client to use that role for API requests.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Initial credentials loaded from SDK's default credential chain. Such as
|
||||||
|
// the environment, shared credentials (~/.aws/credentials), or EC2 Instance
|
||||||
|
// Role. These credentials will be used to to make the STS Assume Role API.
|
||||||
|
sess := session.Must(session.NewSession())
|
||||||
|
|
||||||
|
// Create the credentials from AssumeRoleProvider to assume the role
|
||||||
|
// referenced by the "myRoleARN" ARN.
|
||||||
|
creds := stscreds.NewCredentials(sess, "myRoleArn")
|
||||||
|
|
||||||
|
// Create service client value configured for credentials
|
||||||
|
// from assumed role.
|
||||||
|
svc := s3.New(sess, &aws.Config{Credentials: creds})
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [credentials][credentials_pkg] package documentation for more information on credential
|
||||||
|
providers included with the SDK, and how to customize the SDK's usage of
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
The SDK has support for the shared configuration file (~/.aws/config). This
|
||||||
|
support can be enabled by setting the environment variable, "AWS_SDK_LOAD_CONFIG=1",
|
||||||
|
or enabling the feature in code when creating a Session via the
|
||||||
|
Option's SharedConfigState parameter.
|
||||||
|
|
||||||
|
```go
|
||||||
|
sess := session.Must(session.NewSessionWithOptions(session.Options{
|
||||||
|
SharedConfigState: session.SharedConfigEnable,
|
||||||
|
}))
|
||||||
|
```
|
||||||
|
|
||||||
|
[credentials_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials
|
||||||
|
|
||||||
|
### Configuring AWS Region
|
||||||
|
|
||||||
|
In addition to the credentials you'll need to specify the region the SDK
|
||||||
|
will use to make AWS API requests to. In the SDK you can specify the region
|
||||||
|
either with an environment variable, or directly in code when a Session or
|
||||||
|
service client is created. The last value specified in code wins if the region
|
||||||
|
is specified multiple ways.
|
||||||
|
|
||||||
|
To set the region via the environment variable set the "AWS_REGION" to the
|
||||||
|
region you want to the SDK to use. Using this method to set the region will
|
||||||
|
allow you to run your application in multiple regions without needing additional
|
||||||
|
code in the application to select the region.
|
||||||
|
|
||||||
|
AWS_REGION=us-west-2
|
||||||
|
|
||||||
|
The endpoints package includes constants for all regions the SDK knows. The
|
||||||
|
values are all suffixed with RegionID. These values are helpful, because they
|
||||||
|
reduce the need to type the region string manually.
|
||||||
|
|
||||||
|
To set the region on a Session use the aws package's Config struct parameter
|
||||||
|
Region to the AWS region you want the service clients created from the session to
|
||||||
|
use. This is helpful when you want to create multiple service clients, and
|
||||||
|
all of the clients make API requests to the same region.
|
||||||
|
|
||||||
|
```go
|
||||||
|
sess := session.Must(session.NewSession(&aws.Config{
|
||||||
|
Region: aws.String(endpoints.UsWest2RegionID),
|
||||||
|
}))
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [endpoints][endpoints_pkg] package for the AWS Regions and Endpoints metadata.
|
||||||
|
|
||||||
|
In addition to setting the region when creating a Session you can also set
|
||||||
|
the region on a per service client bases. This overrides the region of a
|
||||||
|
Session. This is helpful when you want to create service clients in specific
|
||||||
|
regions different from the Session's region.
|
||||||
|
|
||||||
|
```go
|
||||||
|
svc := s3.New(sess, &aws.Config{
|
||||||
|
Region: aws.String(endpoints.UsWest2RegionID),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Config][config_typ] type in the [aws][aws_pkg] package for more information and additional
|
||||||
|
options such as setting the Endpoint, and other service client configuration options.
|
||||||
|
|
||||||
|
[endpoints_pkg]: https://docs.aws.amazon.com/sdk-for-go/api/aws/endpoints/
|
||||||
|
|
||||||
|
## Making API Requests
|
||||||
|
|
||||||
|
Once the client is created you can make an API request to the service.
|
||||||
|
Each API method takes a input parameter, and returns the service response
|
||||||
|
and an error. The SDK provides methods for making the API call in multiple ways.
|
||||||
|
|
||||||
|
In this list we'll use the S3 ListObjects API as an example for the different
|
||||||
|
ways of making API requests.
|
||||||
|
|
||||||
|
* ListObjects - Base API operation that will make the API request to the service.
|
||||||
|
|
||||||
|
* ListObjectsRequest - API methods suffixed with Request will construct the
|
||||||
|
API request, but not send it. This is also helpful when you want to get a
|
||||||
|
presigned URL for a request, and share the presigned URL instead of your
|
||||||
|
application making the request directly.
|
||||||
|
|
||||||
|
* ListObjectsPages - Same as the base API operation, but uses a callback to
|
||||||
|
automatically handle pagination of the API's response.
|
||||||
|
|
||||||
|
* ListObjectsWithContext - Same as base API operation, but adds support for
|
||||||
|
the Context pattern. This is helpful for controlling the canceling of in
|
||||||
|
flight requests. See the Go standard library context package for more
|
||||||
|
information. This method also takes request package's Option functional
|
||||||
|
options as the variadic argument for modifying how the request will be
|
||||||
|
made, or extracting information from the raw HTTP response.
|
||||||
|
|
||||||
|
* ListObjectsPagesWithContext - same as ListObjectsPages, but adds support for
|
||||||
|
the Context pattern. Similar to ListObjectsWithContext this method also
|
||||||
|
takes the request package's Option function option types as the variadic
|
||||||
|
argument.
|
||||||
|
|
||||||
|
In addition to the API operations the SDK also includes several higher level
|
||||||
|
methods that abstract checking for and waiting for an AWS resource to be in
|
||||||
|
a desired state. In this list we'll use WaitUntilBucketExists to demonstrate
|
||||||
|
the different forms of waiters.
|
||||||
|
|
||||||
|
* WaitUntilBucketExists. - Method to make API request to query an AWS service for
|
||||||
|
a resource's state. Will return successfully when that state is accomplished.
|
||||||
|
|
||||||
|
* WaitUntilBucketExistsWithContext - Same as WaitUntilBucketExists, but adds
|
||||||
|
support for the Context pattern. In addition these methods take request
|
||||||
|
package's WaiterOptions to configure the waiter, and how underlying request
|
||||||
|
will be made by the SDK.
|
||||||
|
|
||||||
|
The API method will document which error codes the service might return for
|
||||||
|
the operation. These errors will also be available as const strings prefixed
|
||||||
|
with "ErrCode" in the service client's package. If there are no errors listed
|
||||||
|
in the API's SDK documentation you'll need to consult the AWS service's API
|
||||||
|
documentation for the errors that could be returned.
|
||||||
|
|
||||||
|
```go
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
result, err := svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
|
||||||
|
Bucket: aws.String("my-bucket"),
|
||||||
|
Key: aws.String("my-key"),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
// Cast err to awserr.Error to handle specific error codes.
|
||||||
|
aerr, ok := err.(awserr.Error)
|
||||||
|
if ok && aerr.Code() == s3.ErrCodeNoSuchKey {
|
||||||
|
// Specific error code handling
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure to close the body when done with it for S3 GetObject APIs or
|
||||||
|
// will leak connections.
|
||||||
|
defer result.Body.Close()
|
||||||
|
|
||||||
|
fmt.Println("Object Size:", aws.StringValue(result.ContentLength))
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Request Pagination and Resource Waiters
|
||||||
|
|
||||||
|
Pagination helper methods are suffixed with "Pages", and provide the
|
||||||
|
functionality needed to round trip API page requests. Pagination methods
|
||||||
|
take a callback function that will be called for each page of the API's response.
|
||||||
|
|
||||||
|
```go
|
||||||
|
objects := []string{}
|
||||||
|
err := svc.ListObjectsPagesWithContext(ctx, &s3.ListObjectsInput{
|
||||||
|
Bucket: aws.String(myBucket),
|
||||||
|
}, func(p *s3.ListObjectsOutput, lastPage bool) bool {
|
||||||
|
for _, o := range p.Contents {
|
||||||
|
objects = append(objects, aws.StringValue(o.Key))
|
||||||
|
}
|
||||||
|
return true // continue paging
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to list objects for bucket, %s, %v", myBucket, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Objects in bucket:", objects)
|
||||||
|
```
|
||||||
|
|
||||||
|
Waiter helper methods provide the functionality to wait for an AWS resource
|
||||||
|
state. These methods abstract the logic needed to to check the state of an
|
||||||
|
AWS resource, and wait until that resource is in a desired state. The waiter
|
||||||
|
will block until the resource is in the state that is desired, an error occurs,
|
||||||
|
or the waiter times out. If a resource times out the error code returned will
|
||||||
|
be request.WaiterResourceNotReadyErrorCode.
|
||||||
|
|
||||||
|
```go
|
||||||
|
err := svc.WaitUntilBucketExistsWithContext(ctx, &s3.HeadBucketInput{
|
||||||
|
Bucket: aws.String(myBucket),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
aerr, ok := err.(awserr.Error)
|
||||||
|
if ok && aerr.Code() == request.WaiterResourceNotReadyErrorCode {
|
||||||
|
fmt.Fprintf(os.Stderr, "timed out while waiting for bucket to exist")
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("failed to wait for bucket to exist, %v", err))
|
||||||
|
}
|
||||||
|
fmt.Println("Bucket", myBucket, "exists")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Complete SDK Example
|
||||||
|
|
||||||
|
This example shows a complete working Go file which will upload a file to S3
|
||||||
|
and use the Context pattern to implement timeout logic that will cancel the
|
||||||
|
request if it takes too long. This example highlights how to use sessions,
|
||||||
|
create a service client, make a request, handle the error, and process the
|
||||||
|
response.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Uploads a file to S3 given a bucket and object key. Also takes a duration
|
||||||
|
// value to terminate the update if it doesn't complete within that time.
|
||||||
|
//
|
||||||
|
// The AWS Region needs to be provided in the AWS shared config or on the
|
||||||
|
// environment variable as `AWS_REGION`. Credentials also must be provided
|
||||||
|
// Will default to shared config file, but can load from environment if provided.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// # Upload myfile.txt to myBucket/myKey. Must complete within 10 minutes or will fail
|
||||||
|
// go run withContext.go -b mybucket -k myKey -d 10m < myfile.txt
|
||||||
|
func main() {
|
||||||
|
var bucket, key string
|
||||||
|
var timeout time.Duration
|
||||||
|
|
||||||
|
flag.StringVar(&bucket, "b", "", "Bucket name.")
|
||||||
|
flag.StringVar(&key, "k", "", "Object key name.")
|
||||||
|
flag.DurationVar(&timeout, "d", 0, "Upload timeout.")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// All clients require a Session. The Session provides the client with
|
||||||
|
// shared configuration such as region, endpoint, and credentials. A
|
||||||
|
// Session should be shared where possible to take advantage of
|
||||||
|
// configuration and credential caching. See the session package for
|
||||||
|
// more information.
|
||||||
|
sess := session.Must(session.NewSession())
|
||||||
|
|
||||||
|
// Create a new instance of the service's client with a Session.
|
||||||
|
// Optional aws.Config values can also be provided as variadic arguments
|
||||||
|
// to the New function. This option allows you to provide service
|
||||||
|
// specific configuration.
|
||||||
|
svc := s3.New(sess)
|
||||||
|
|
||||||
|
// Create a context with a timeout that will abort the upload if it takes
|
||||||
|
// more than the passed in timeout.
|
||||||
|
ctx := context.Background()
|
||||||
|
var cancelFn func()
|
||||||
|
if timeout > 0 {
|
||||||
|
ctx, cancelFn = context.WithTimeout(ctx, timeout)
|
||||||
|
}
|
||||||
|
// Ensure the context is canceled to prevent leaking.
|
||||||
|
// See context package for more information, https://golang.org/pkg/context/
|
||||||
|
defer cancelFn()
|
||||||
|
|
||||||
|
// Uploads the object to S3. The Context will interrupt the request if the
|
||||||
|
// timeout expires.
|
||||||
|
_, err := svc.PutObjectWithContext(ctx, &s3.PutObjectInput{
|
||||||
|
Bucket: aws.String(bucket),
|
||||||
|
Key: aws.String(key),
|
||||||
|
Body: os.Stdin,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if aerr, ok := err.(awserr.Error); ok && aerr.Code() == request.CanceledErrorCode {
|
||||||
|
// If the SDK can determine the request or retry delay was canceled
|
||||||
|
// by a context the CanceledErrorCode error code will be returned.
|
||||||
|
fmt.Fprintf(os.Stderr, "upload canceled due to timeout, %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to upload object, %v\n", err)
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("successfully uploaded file to %s/%s\n", bucket, key)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This SDK is distributed under the
|
||||||
|
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0),
|
||||||
|
see LICENSE.txt and NOTICE.txt for more information.
|
86
vendor/github.com/aws/aws-sdk-go/aws/arn/arn.go
generated
vendored
Normal file
86
vendor/github.com/aws/aws-sdk-go/aws/arn/arn.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// Package arn provides a parser for interacting with Amazon Resource Names.
|
||||||
|
package arn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
arnDelimiter = ":"
|
||||||
|
arnSections = 6
|
||||||
|
arnPrefix = "arn:"
|
||||||
|
|
||||||
|
// zero-indexed
|
||||||
|
sectionPartition = 1
|
||||||
|
sectionService = 2
|
||||||
|
sectionRegion = 3
|
||||||
|
sectionAccountID = 4
|
||||||
|
sectionResource = 5
|
||||||
|
|
||||||
|
// errors
|
||||||
|
invalidPrefix = "arn: invalid prefix"
|
||||||
|
invalidSections = "arn: not enough sections"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ARN captures the individual fields of an Amazon Resource Name.
|
||||||
|
// See http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html for more information.
|
||||||
|
type ARN struct {
|
||||||
|
// The partition that the resource is in. For standard AWS regions, the partition is "aws". If you have resources in
|
||||||
|
// other partitions, the partition is "aws-partitionname". For example, the partition for resources in the China
|
||||||
|
// (Beijing) region is "aws-cn".
|
||||||
|
Partition string
|
||||||
|
|
||||||
|
// The service namespace that identifies the AWS product (for example, Amazon S3, IAM, or Amazon RDS). For a list of
|
||||||
|
// namespaces, see
|
||||||
|
// http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-aws-service-namespaces.
|
||||||
|
Service string
|
||||||
|
|
||||||
|
// The region the resource resides in. Note that the ARNs for some resources do not require a region, so this
|
||||||
|
// component might be omitted.
|
||||||
|
Region string
|
||||||
|
|
||||||
|
// The ID of the AWS account that owns the resource, without the hyphens. For example, 123456789012. Note that the
|
||||||
|
// ARNs for some resources don't require an account number, so this component might be omitted.
|
||||||
|
AccountID string
|
||||||
|
|
||||||
|
// The content of this part of the ARN varies by service. It often includes an indicator of the type of resource —
|
||||||
|
// for example, an IAM user or Amazon RDS database - followed by a slash (/) or a colon (:), followed by the
|
||||||
|
// resource name itself. Some services allows paths for resource names, as described in
|
||||||
|
// http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-paths.
|
||||||
|
Resource string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses an ARN into its constituent parts.
|
||||||
|
//
|
||||||
|
// Some example ARNs:
|
||||||
|
// arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment
|
||||||
|
// arn:aws:iam::123456789012:user/David
|
||||||
|
// arn:aws:rds:eu-west-1:123456789012:db:mysql-db
|
||||||
|
// arn:aws:s3:::my_corporate_bucket/exampleobject.png
|
||||||
|
func Parse(arn string) (ARN, error) {
|
||||||
|
if !strings.HasPrefix(arn, arnPrefix) {
|
||||||
|
return ARN{}, errors.New(invalidPrefix)
|
||||||
|
}
|
||||||
|
sections := strings.SplitN(arn, arnDelimiter, arnSections)
|
||||||
|
if len(sections) != arnSections {
|
||||||
|
return ARN{}, errors.New(invalidSections)
|
||||||
|
}
|
||||||
|
return ARN{
|
||||||
|
Partition: sections[sectionPartition],
|
||||||
|
Service: sections[sectionService],
|
||||||
|
Region: sections[sectionRegion],
|
||||||
|
AccountID: sections[sectionAccountID],
|
||||||
|
Resource: sections[sectionResource],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the canonical representation of the ARN
|
||||||
|
func (arn ARN) String() string {
|
||||||
|
return arnPrefix +
|
||||||
|
arn.Partition + arnDelimiter +
|
||||||
|
arn.Service + arnDelimiter +
|
||||||
|
arn.Region + arnDelimiter +
|
||||||
|
arn.AccountID + arnDelimiter +
|
||||||
|
arn.Resource
|
||||||
|
}
|
90
vendor/github.com/aws/aws-sdk-go/aws/arn/arn_test.go
generated
vendored
Normal file
90
vendor/github.com/aws/aws-sdk-go/aws/arn/arn_test.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package arn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseARN(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
input string
|
||||||
|
arn ARN
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "invalid",
|
||||||
|
err: errors.New(invalidPrefix),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "arn:nope",
|
||||||
|
err: errors.New(invalidSections),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "arn:aws:ecr:us-west-2:123456789012:repository/foo/bar",
|
||||||
|
arn: ARN{
|
||||||
|
Partition: "aws",
|
||||||
|
Service: "ecr",
|
||||||
|
Region: "us-west-2",
|
||||||
|
AccountID: "123456789012",
|
||||||
|
Resource: "repository/foo/bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment",
|
||||||
|
arn: ARN{
|
||||||
|
Partition: "aws",
|
||||||
|
Service: "elasticbeanstalk",
|
||||||
|
Region: "us-east-1",
|
||||||
|
AccountID: "123456789012",
|
||||||
|
Resource: "environment/My App/MyEnvironment",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "arn:aws:iam::123456789012:user/David",
|
||||||
|
arn: ARN{
|
||||||
|
Partition: "aws",
|
||||||
|
Service: "iam",
|
||||||
|
Region: "",
|
||||||
|
AccountID: "123456789012",
|
||||||
|
Resource: "user/David",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "arn:aws:rds:eu-west-1:123456789012:db:mysql-db",
|
||||||
|
arn: ARN{
|
||||||
|
Partition: "aws",
|
||||||
|
Service: "rds",
|
||||||
|
Region: "eu-west-1",
|
||||||
|
AccountID: "123456789012",
|
||||||
|
Resource: "db:mysql-db",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "arn:aws:s3:::my_corporate_bucket/exampleobject.png",
|
||||||
|
arn: ARN{
|
||||||
|
Partition: "aws",
|
||||||
|
Service: "s3",
|
||||||
|
Region: "",
|
||||||
|
AccountID: "",
|
||||||
|
Resource: "my_corporate_bucket/exampleobject.png",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.input, func(t *testing.T) {
|
||||||
|
spec, err := Parse(tc.input)
|
||||||
|
if tc.arn != spec {
|
||||||
|
t.Errorf("Expected %q to parse as %v, but got %v", tc.input, tc.arn, spec)
|
||||||
|
}
|
||||||
|
if err == nil && tc.err != nil {
|
||||||
|
t.Errorf("Expected err to be %v, but got nil", tc.err)
|
||||||
|
} else if err != nil && tc.err == nil {
|
||||||
|
t.Errorf("Expected err to be nil, but got %v", err)
|
||||||
|
} else if err != nil && tc.err != nil && err.Error() != tc.err.Error() {
|
||||||
|
t.Errorf("Expected err to be %v, but got %v", tc.err, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
56
vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go
generated
vendored
56
vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go
generated
vendored
|
@ -14,13 +14,13 @@ package awserr
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// if awsErr, ok := err.(awserr.Error); ok {
|
// if awsErr, ok := err.(awserr.Error); ok {
|
||||||
// // Get error details
|
// // Get error details
|
||||||
// log.Println("Error:", err.Code(), err.Message())
|
// log.Println("Error:", awsErr.Code(), awsErr.Message())
|
||||||
//
|
//
|
||||||
// // Prints out full error message, including original error if there was one.
|
// // Prints out full error message, including original error if there was one.
|
||||||
// log.Println("Error:", err.Error())
|
// log.Println("Error:", awsErr.Error())
|
||||||
//
|
//
|
||||||
// // Get original error
|
// // Get original error
|
||||||
// if origErr := err.Err(); origErr != nil {
|
// if origErr := awsErr.OrigErr(); origErr != nil {
|
||||||
// // operate on original error.
|
// // operate on original error.
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
|
@ -42,15 +42,55 @@ type Error interface {
|
||||||
OrigErr() error
|
OrigErr() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BatchError is a batch of errors which also wraps lower level errors with
|
||||||
|
// code, message, and original errors. Calling Error() will include all errors
|
||||||
|
// that occurred in the batch.
|
||||||
|
//
|
||||||
|
// Deprecated: Replaced with BatchedErrors. Only defined for backwards
|
||||||
|
// compatibility.
|
||||||
|
type BatchError 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.
|
||||||
|
OrigErrs() []error
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchedErrors is a batch of errors which also wraps lower level errors with
|
||||||
|
// code, message, and original errors. Calling Error() will include all errors
|
||||||
|
// that occurred in the batch.
|
||||||
|
//
|
||||||
|
// Replaces BatchError
|
||||||
|
type BatchedErrors interface {
|
||||||
|
// Satisfy the base Error interface.
|
||||||
|
Error
|
||||||
|
|
||||||
|
// Returns the original error if one was set. Nil is returned if not set.
|
||||||
|
OrigErrs() []error
|
||||||
|
}
|
||||||
|
|
||||||
// New returns an Error object described by the code, message, and origErr.
|
// 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
|
// If origErr satisfies the Error interface it will not be wrapped within a new
|
||||||
// Error object and will instead be returned.
|
// Error object and will instead be returned.
|
||||||
func New(code, message string, origErr error) Error {
|
func New(code, message string, origErr error) Error {
|
||||||
if e, ok := origErr.(Error); ok && e != nil {
|
var errs []error
|
||||||
return e
|
if origErr != nil {
|
||||||
|
errs = append(errs, origErr)
|
||||||
}
|
}
|
||||||
return newBaseError(code, message, origErr)
|
return newBaseError(code, message, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBatchError returns an BatchedErrors with a collection of errors as an
|
||||||
|
// array of errors.
|
||||||
|
func NewBatchError(code, message string, errs []error) BatchedErrors {
|
||||||
|
return newBaseError(code, message, errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A RequestFailure is an interface to extract request failure information from
|
// A RequestFailure is an interface to extract request failure information from
|
||||||
|
@ -63,9 +103,9 @@ func New(code, message string, origErr error) Error {
|
||||||
// output, err := s3manage.Upload(svc, input, opts)
|
// output, err := s3manage.Upload(svc, input, opts)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// if reqerr, ok := err.(RequestFailure); ok {
|
// if reqerr, ok := err.(RequestFailure); ok {
|
||||||
// log.Printf("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID())
|
// log.Println("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID())
|
||||||
// } else {
|
// } else {
|
||||||
// log.Printf("Error:", err.Error()
|
// log.Println("Error:", err.Error())
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
|
85
vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go
generated
vendored
85
vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go
generated
vendored
|
@ -31,23 +31,27 @@ type baseError struct {
|
||||||
|
|
||||||
// Optional original error this error is based off of. Allows building
|
// Optional original error this error is based off of. Allows building
|
||||||
// chained errors.
|
// chained errors.
|
||||||
origErr error
|
errs []error
|
||||||
}
|
}
|
||||||
|
|
||||||
// newBaseError returns an error object for the code, message, and err.
|
// newBaseError returns an error object for the code, message, and errors.
|
||||||
//
|
//
|
||||||
// code is a short no whitespace phrase depicting the classification of
|
// code is a short no whitespace phrase depicting the classification of
|
||||||
// the error that is being created.
|
// the error that is being created.
|
||||||
//
|
//
|
||||||
// message is the free flow string containing detailed information about the error.
|
// 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.
|
// origErrs is the error objects which will be nested under the new errors to
|
||||||
func newBaseError(code, message string, origErr error) *baseError {
|
// be returned.
|
||||||
return &baseError{
|
func newBaseError(code, message string, origErrs []error) *baseError {
|
||||||
|
b := &baseError{
|
||||||
code: code,
|
code: code,
|
||||||
message: message,
|
message: message,
|
||||||
origErr: origErr,
|
errs: origErrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returns the string representation of the error.
|
// Error returns the string representation of the error.
|
||||||
|
@ -56,7 +60,12 @@ func newBaseError(code, message string, origErr error) *baseError {
|
||||||
//
|
//
|
||||||
// Satisfies the error interface.
|
// Satisfies the error interface.
|
||||||
func (b baseError) Error() string {
|
func (b baseError) Error() string {
|
||||||
return SprintError(b.code, b.message, "", b.origErr)
|
size := len(b.errs)
|
||||||
|
if size > 0 {
|
||||||
|
return SprintError(b.code, b.message, "", errorList(b.errs))
|
||||||
|
}
|
||||||
|
|
||||||
|
return SprintError(b.code, b.message, "", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string representation of the error.
|
// String returns the string representation of the error.
|
||||||
|
@ -75,10 +84,28 @@ func (b baseError) Message() string {
|
||||||
return b.message
|
return b.message
|
||||||
}
|
}
|
||||||
|
|
||||||
// OrigErr returns the original error if one was set. Nil is returned if no error
|
// OrigErr returns the original error if one was set. Nil is returned if no
|
||||||
// was set.
|
// error was set. This only returns the first element in the list. If the full
|
||||||
|
// list is needed, use BatchedErrors.
|
||||||
func (b baseError) OrigErr() error {
|
func (b baseError) OrigErr() error {
|
||||||
return b.origErr
|
switch len(b.errs) {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case 1:
|
||||||
|
return b.errs[0]
|
||||||
|
default:
|
||||||
|
if err, ok := b.errs[0].(Error); ok {
|
||||||
|
return NewBatchError(err.Code(), err.Message(), b.errs[1:])
|
||||||
|
}
|
||||||
|
return NewBatchError("BatchedErrors",
|
||||||
|
"multiple errors occurred", b.errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrigErrs returns the original errors if one was set. An empty slice is
|
||||||
|
// returned if no error was set.
|
||||||
|
func (b baseError) OrigErrs() []error {
|
||||||
|
return b.errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// So that the Error interface type can be included as an anonymous field
|
// So that the Error interface type can be included as an anonymous field
|
||||||
|
@ -94,8 +121,8 @@ type requestError struct {
|
||||||
requestID string
|
requestID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRequestError returns a wrapped error with additional information for request
|
// newRequestError returns a wrapped error with additional information for
|
||||||
// status code, and service requestID.
|
// request status code, and service requestID.
|
||||||
//
|
//
|
||||||
// Should be used to wrap all request which involve service requests. Even if
|
// 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
|
// the request failed without a service response, but had an HTTP status code
|
||||||
|
@ -133,3 +160,35 @@ func (r requestError) StatusCode() int {
|
||||||
func (r requestError) RequestID() string {
|
func (r requestError) RequestID() string {
|
||||||
return r.requestID
|
return r.requestID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrigErrs returns the original errors if one was set. An empty slice is
|
||||||
|
// returned if no error was set.
|
||||||
|
func (r requestError) OrigErrs() []error {
|
||||||
|
if b, ok := r.awsError.(BatchedErrors); ok {
|
||||||
|
return b.OrigErrs()
|
||||||
|
}
|
||||||
|
return []error{r.OrigErr()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An error list that satisfies the golang interface
|
||||||
|
type errorList []error
|
||||||
|
|
||||||
|
// Error returns the string representation of the error.
|
||||||
|
//
|
||||||
|
// Satisfies the error interface.
|
||||||
|
func (e errorList) Error() string {
|
||||||
|
msg := ""
|
||||||
|
// How do we want to handle the array size being zero
|
||||||
|
if size := len(e); size > 0 {
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
msg += fmt.Sprintf("%s", e[i].Error())
|
||||||
|
// We check the next index to see if it is within the slice.
|
||||||
|
// If it is, then we append a newline. We do this, because unit tests
|
||||||
|
// could be broken with the additional '\n'
|
||||||
|
if i+1 < size {
|
||||||
|
msg += "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
21
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
21
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
|
@ -3,6 +3,7 @@ package awsutil
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Copy deeply copies a src structure to dst. Useful for copying request and
|
// Copy deeply copies a src structure to dst. Useful for copying request and
|
||||||
|
@ -49,7 +50,14 @@ func rcopy(dst, src reflect.Value, root bool) {
|
||||||
} else {
|
} else {
|
||||||
e := src.Type().Elem()
|
e := src.Type().Elem()
|
||||||
if dst.CanSet() && !src.IsNil() {
|
if dst.CanSet() && !src.IsNil() {
|
||||||
dst.Set(reflect.New(e))
|
if _, ok := src.Interface().(*time.Time); !ok {
|
||||||
|
dst.Set(reflect.New(e))
|
||||||
|
} else {
|
||||||
|
tempValue := reflect.New(e)
|
||||||
|
tempValue.Elem().Set(src.Elem())
|
||||||
|
// Sets time.Time's unexported values
|
||||||
|
dst.Set(tempValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if src.Elem().IsValid() {
|
if src.Elem().IsValid() {
|
||||||
// Keep the current root state since the depth hasn't changed
|
// Keep the current root state since the depth hasn't changed
|
||||||
|
@ -57,16 +65,13 @@ func rcopy(dst, src reflect.Value, root bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if !root {
|
|
||||||
dst.Set(reflect.New(src.Type()).Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
t := dst.Type()
|
t := dst.Type()
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
name := t.Field(i).Name
|
name := t.Field(i).Name
|
||||||
srcval := src.FieldByName(name)
|
srcVal := src.FieldByName(name)
|
||||||
if srcval.IsValid() {
|
dstVal := dst.FieldByName(name)
|
||||||
rcopy(dst.FieldByName(name), srcval, false)
|
if srcVal.IsValid() && dstVal.CanSet() {
|
||||||
|
rcopy(dstVal, srcVal, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
|
|
353
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go
generated
vendored
Normal file
353
vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go
generated
vendored
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
package awsutil_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleCopy() {
|
||||||
|
type Foo struct {
|
||||||
|
A int
|
||||||
|
B []*string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the initial value
|
||||||
|
str1 := "hello"
|
||||||
|
str2 := "bye bye"
|
||||||
|
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
|
||||||
|
|
||||||
|
// Do the copy
|
||||||
|
var f2 Foo
|
||||||
|
awsutil.Copy(&f2, f1)
|
||||||
|
|
||||||
|
// Print the result
|
||||||
|
fmt.Println(awsutil.Prettify(f2))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// A: 1,
|
||||||
|
// B: ["hello","bye bye"]
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopy1(t *testing.T) {
|
||||||
|
type Bar struct {
|
||||||
|
a *int
|
||||||
|
B *int
|
||||||
|
c int
|
||||||
|
D int
|
||||||
|
}
|
||||||
|
type Foo struct {
|
||||||
|
A int
|
||||||
|
B []*string
|
||||||
|
C map[string]*int
|
||||||
|
D *time.Time
|
||||||
|
E *Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the initial value
|
||||||
|
str1 := "hello"
|
||||||
|
str2 := "bye bye"
|
||||||
|
int1 := 1
|
||||||
|
int2 := 2
|
||||||
|
intPtr1 := 1
|
||||||
|
intPtr2 := 2
|
||||||
|
now := time.Now()
|
||||||
|
f1 := &Foo{
|
||||||
|
A: 1,
|
||||||
|
B: []*string{&str1, &str2},
|
||||||
|
C: map[string]*int{
|
||||||
|
"A": &int1,
|
||||||
|
"B": &int2,
|
||||||
|
},
|
||||||
|
D: &now,
|
||||||
|
E: &Bar{
|
||||||
|
&intPtr1,
|
||||||
|
&intPtr2,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the copy
|
||||||
|
var f2 Foo
|
||||||
|
awsutil.Copy(&f2, f1)
|
||||||
|
|
||||||
|
// Values are equal
|
||||||
|
if v1, v2 := f2.A, f1.A; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.B, f1.B; !reflect.DeepEqual(v1, v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.C, f1.C; !reflect.DeepEqual(v1, v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.D, f1.D; !v1.Equal(*v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.E.B, f1.E.B; !reflect.DeepEqual(v1, v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.E.D, f1.E.D; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// But pointers are not!
|
||||||
|
str3 := "nothello"
|
||||||
|
int3 := 57
|
||||||
|
f2.A = 100
|
||||||
|
*f2.B[0] = str3
|
||||||
|
*f2.C["B"] = int3
|
||||||
|
*f2.D = time.Now()
|
||||||
|
f2.E.a = &int3
|
||||||
|
*f2.E.B = int3
|
||||||
|
f2.E.c = 5
|
||||||
|
f2.E.D = 5
|
||||||
|
if v1, v2 := f2.A, f1.A; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.B, f1.B; reflect.DeepEqual(v1, v2) {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.C, f1.C; reflect.DeepEqual(v1, v2) {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.D, f1.D; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.E.a, f1.E.a; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.E.B, f1.E.B; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.E.c, f1.E.c; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.E.D, f1.E.D; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyNestedWithUnexported(t *testing.T) {
|
||||||
|
type Bar struct {
|
||||||
|
a int
|
||||||
|
B int
|
||||||
|
}
|
||||||
|
type Foo struct {
|
||||||
|
A string
|
||||||
|
B Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
f1 := &Foo{A: "string", B: Bar{a: 1, B: 2}}
|
||||||
|
|
||||||
|
var f2 Foo
|
||||||
|
awsutil.Copy(&f2, f1)
|
||||||
|
|
||||||
|
// Values match
|
||||||
|
if v1, v2 := f2.A, f1.A; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.B, f1.B; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.B.a, f1.B.a; v1 == v2 {
|
||||||
|
t.Errorf("expected values to be not equivalent, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.B.B, f2.B.B; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyIgnoreNilMembers(t *testing.T) {
|
||||||
|
type Foo struct {
|
||||||
|
A *string
|
||||||
|
B []string
|
||||||
|
C map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
f := &Foo{}
|
||||||
|
if v1 := f.A; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1 := f.B; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1 := f.C; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var f2 Foo
|
||||||
|
awsutil.Copy(&f2, f)
|
||||||
|
if v1 := f2.A; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1 := f2.B; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1 := f2.C; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fcopy := awsutil.CopyOf(f)
|
||||||
|
f3 := fcopy.(*Foo)
|
||||||
|
if v1 := f3.A; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1 := f3.B; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1 := f3.C; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyPrimitive(t *testing.T) {
|
||||||
|
str := "hello"
|
||||||
|
var s string
|
||||||
|
awsutil.Copy(&s, &str)
|
||||||
|
if v1, v2 := "hello", s; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyNil(t *testing.T) {
|
||||||
|
var s string
|
||||||
|
awsutil.Copy(&s, nil)
|
||||||
|
if v1, v2 := "", s; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyReader(t *testing.T) {
|
||||||
|
var buf io.Reader = bytes.NewReader([]byte("hello world"))
|
||||||
|
var r io.Reader
|
||||||
|
awsutil.Copy(&r, buf)
|
||||||
|
b, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expected no error, but received %v", err)
|
||||||
|
}
|
||||||
|
if v1, v2 := []byte("hello world"), b; !bytes.Equal(v1, v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty bytes because this is not a deep copy
|
||||||
|
b, err = ioutil.ReadAll(buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expected no error, but received %v", err)
|
||||||
|
}
|
||||||
|
if v1, v2 := []byte(""), b; !bytes.Equal(v1, v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyDifferentStructs(t *testing.T) {
|
||||||
|
type SrcFoo struct {
|
||||||
|
A int
|
||||||
|
B []*string
|
||||||
|
C map[string]*int
|
||||||
|
SrcUnique string
|
||||||
|
SameNameDiffType int
|
||||||
|
unexportedPtr *int
|
||||||
|
ExportedPtr *int
|
||||||
|
}
|
||||||
|
type DstFoo struct {
|
||||||
|
A int
|
||||||
|
B []*string
|
||||||
|
C map[string]*int
|
||||||
|
DstUnique int
|
||||||
|
SameNameDiffType string
|
||||||
|
unexportedPtr *int
|
||||||
|
ExportedPtr *int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the initial value
|
||||||
|
str1 := "hello"
|
||||||
|
str2 := "bye bye"
|
||||||
|
int1 := 1
|
||||||
|
int2 := 2
|
||||||
|
f1 := &SrcFoo{
|
||||||
|
A: 1,
|
||||||
|
B: []*string{&str1, &str2},
|
||||||
|
C: map[string]*int{
|
||||||
|
"A": &int1,
|
||||||
|
"B": &int2,
|
||||||
|
},
|
||||||
|
SrcUnique: "unique",
|
||||||
|
SameNameDiffType: 1,
|
||||||
|
unexportedPtr: &int1,
|
||||||
|
ExportedPtr: &int2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the copy
|
||||||
|
var f2 DstFoo
|
||||||
|
awsutil.Copy(&f2, f1)
|
||||||
|
|
||||||
|
// Values are equal
|
||||||
|
if v1, v2 := f2.A, f1.A; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.B, f1.B; !reflect.DeepEqual(v1, v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := f2.C, f1.C; !reflect.DeepEqual(v1, v2) {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := "unique", f1.SrcUnique; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := 1, f1.SameNameDiffType; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := 0, f2.DstUnique; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := "", f2.SameNameDiffType; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := int1, *f1.unexportedPtr; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1 := f2.unexportedPtr; v1 != nil {
|
||||||
|
t.Errorf("expected nil, but received %v", v1)
|
||||||
|
}
|
||||||
|
if v1, v2 := int2, *f1.ExportedPtr; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
if v1, v2 := int2, *f2.ExportedPtr; v1 != v2 {
|
||||||
|
t.Errorf("expected values to be equivalent but received %v and %v", v1, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleCopyOf() {
|
||||||
|
type Foo struct {
|
||||||
|
A int
|
||||||
|
B []*string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the initial value
|
||||||
|
str1 := "hello"
|
||||||
|
str2 := "bye bye"
|
||||||
|
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
|
||||||
|
|
||||||
|
// Do the copy
|
||||||
|
v := awsutil.CopyOf(f1)
|
||||||
|
var f2 *Foo = v.(*Foo)
|
||||||
|
|
||||||
|
// Print the result
|
||||||
|
fmt.Println(awsutil.Prettify(f2))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// A: 1,
|
||||||
|
// B: ["hello","bye bye"]
|
||||||
|
// }
|
||||||
|
}
|
27
vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go
generated
vendored
Normal file
27
vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package awsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeepEqual returns if the two values are deeply equal like reflect.DeepEqual.
|
||||||
|
// In addition to this, this method will also dereference the input values if
|
||||||
|
// possible so the DeepEqual performed will not fail if one parameter is a
|
||||||
|
// pointer and the other is not.
|
||||||
|
//
|
||||||
|
// DeepEqual will not perform indirection of nested values of the input parameters.
|
||||||
|
func DeepEqual(a, b interface{}) bool {
|
||||||
|
ra := reflect.Indirect(reflect.ValueOf(a))
|
||||||
|
rb := reflect.Indirect(reflect.ValueOf(b))
|
||||||
|
|
||||||
|
if raValid, rbValid := ra.IsValid(), rb.IsValid(); !raValid && !rbValid {
|
||||||
|
// If the elements are both nil, and of the same type the are equal
|
||||||
|
// If they are of different types they are not equal
|
||||||
|
return reflect.TypeOf(a) == reflect.TypeOf(b)
|
||||||
|
} else if raValid != rbValid {
|
||||||
|
// Both values must be valid to be equal
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.DeepEqual(ra.Interface(), rb.Interface())
|
||||||
|
}
|
30
vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go
generated
vendored
Normal file
30
vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package awsutil_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDeepEqual(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
a, b interface{}
|
||||||
|
equal bool
|
||||||
|
}{
|
||||||
|
{"a", "a", true},
|
||||||
|
{"a", "b", false},
|
||||||
|
{"a", aws.String(""), false},
|
||||||
|
{"a", nil, false},
|
||||||
|
{"a", aws.String("a"), true},
|
||||||
|
{(*bool)(nil), (*bool)(nil), true},
|
||||||
|
{(*bool)(nil), (*string)(nil), false},
|
||||||
|
{nil, nil, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
if awsutil.DeepEqual(c.a, c.b) != c.equal {
|
||||||
|
t.Errorf("%d, a:%v b:%v, %t", i, c.a, c.b, c.equal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
117
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
|
@ -5,18 +5,20 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jmespath/go-jmespath"
|
||||||
)
|
)
|
||||||
|
|
||||||
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
|
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
|
||||||
|
|
||||||
// rValuesAtPath returns a slice of values found in value v. The values
|
// rValuesAtPath returns a slice of values found in value v. The values
|
||||||
// in v are explored recursively so all nested values are collected.
|
// in v are explored recursively so all nested values are collected.
|
||||||
func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool) []reflect.Value {
|
func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value {
|
||||||
pathparts := strings.Split(path, "||")
|
pathparts := strings.Split(path, "||")
|
||||||
if len(pathparts) > 1 {
|
if len(pathparts) > 1 {
|
||||||
for _, pathpart := range pathparts {
|
for _, pathpart := range pathparts {
|
||||||
vals := rValuesAtPath(v, pathpart, create, caseSensitive)
|
vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm)
|
||||||
if vals != nil && len(vals) > 0 {
|
if len(vals) > 0 {
|
||||||
return vals
|
return vals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +76,16 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
if create && value.Kind() == reflect.Ptr && value.IsNil() {
|
if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 {
|
||||||
|
if !value.IsNil() {
|
||||||
|
value.Set(reflect.Zero(value.Type()))
|
||||||
|
}
|
||||||
|
return []reflect.Value{value}
|
||||||
|
}
|
||||||
|
|
||||||
|
if createPath && value.Kind() == reflect.Ptr && value.IsNil() {
|
||||||
|
// TODO if the value is the terminus it should not be created
|
||||||
|
// if the value to be set to its position is nil.
|
||||||
value.Set(reflect.New(value.Type().Elem()))
|
value.Set(reflect.New(value.Type().Elem()))
|
||||||
value = value.Elem()
|
value = value.Elem()
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,7 +93,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||||
if !create && value.IsNil() {
|
if !createPath && value.IsNil() {
|
||||||
value = reflect.ValueOf(nil)
|
value = reflect.ValueOf(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,8 +106,8 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
|
|
||||||
if indexStar || index != nil {
|
if indexStar || index != nil {
|
||||||
nextvals = []reflect.Value{}
|
nextvals = []reflect.Value{}
|
||||||
for _, value := range values {
|
for _, valItem := range values {
|
||||||
value := reflect.Indirect(value)
|
value := reflect.Indirect(valItem)
|
||||||
if value.Kind() != reflect.Slice {
|
if value.Kind() != reflect.Slice {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -114,7 +125,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
// pull out index
|
// pull out index
|
||||||
i := int(*index)
|
i := int(*index)
|
||||||
if i >= value.Len() { // check out of bounds
|
if i >= value.Len() { // check out of bounds
|
||||||
if create {
|
if createPath {
|
||||||
// TODO resize slice
|
// TODO resize slice
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
|
@ -125,7 +136,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
value = reflect.Indirect(value.Index(i))
|
value = reflect.Indirect(value.Index(i))
|
||||||
|
|
||||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||||
if !create && value.IsNil() {
|
if !createPath && value.IsNil() {
|
||||||
value = reflect.ValueOf(nil)
|
value = reflect.ValueOf(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,46 +153,70 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValuesAtPath returns a list of objects at the lexical path inside of a structure
|
// ValuesAtPath returns a list of values at the case insensitive lexical
|
||||||
func ValuesAtPath(i interface{}, path string) []interface{} {
|
// path inside of a structure.
|
||||||
if rvals := rValuesAtPath(i, path, false, true); rvals != nil {
|
func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
|
||||||
vals := make([]interface{}, len(rvals))
|
result, err := jmespath.Search(path, i)
|
||||||
for i, rval := range rvals {
|
if err != nil {
|
||||||
vals[i] = rval.Interface()
|
return nil, err
|
||||||
}
|
|
||||||
return vals
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
v := reflect.ValueOf(result)
|
||||||
|
if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if s, ok := result.([]interface{}); ok {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
if v.Kind() == reflect.Map && v.Len() == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if v.Kind() == reflect.Slice {
|
||||||
|
out := make([]interface{}, v.Len())
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
out[i] = v.Index(i).Interface()
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return []interface{}{result}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValuesAtAnyPath returns a list of objects at the case-insensitive lexical
|
// SetValueAtPath sets a value at the case insensitive lexical path inside
|
||||||
// path inside of a structure
|
// 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{}) {
|
func SetValueAtPath(i interface{}, path string, v interface{}) {
|
||||||
if rvals := rValuesAtPath(i, path, true, true); rvals != nil {
|
if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil {
|
||||||
for _, rval := range rvals {
|
for _, rval := range rvals {
|
||||||
rval.Set(reflect.ValueOf(v))
|
if rval.Kind() == reflect.Ptr && rval.IsNil() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
setValue(rval, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetValueAtAnyPath sets an object at the case insensitive lexical path inside
|
func setValue(dstVal reflect.Value, src interface{}) {
|
||||||
// of a structure
|
if dstVal.Kind() == reflect.Ptr {
|
||||||
func SetValueAtAnyPath(i interface{}, path string, v interface{}) {
|
dstVal = reflect.Indirect(dstVal)
|
||||||
if rvals := rValuesAtPath(i, path, true, false); rvals != nil {
|
|
||||||
for _, rval := range rvals {
|
|
||||||
rval.Set(reflect.ValueOf(v))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
srcVal := reflect.ValueOf(src)
|
||||||
|
|
||||||
|
if !srcVal.IsValid() { // src is literal nil
|
||||||
|
if dstVal.CanAddr() {
|
||||||
|
// Convert to pointer so that pointer's value can be nil'ed
|
||||||
|
// dstVal = dstVal.Addr()
|
||||||
|
}
|
||||||
|
dstVal.Set(reflect.Zero(dstVal.Type()))
|
||||||
|
|
||||||
|
} else if srcVal.Kind() == reflect.Ptr {
|
||||||
|
if srcVal.IsNil() {
|
||||||
|
srcVal = reflect.Zero(dstVal.Type())
|
||||||
|
} else {
|
||||||
|
srcVal = reflect.ValueOf(src).Elem()
|
||||||
|
}
|
||||||
|
dstVal.Set(srcVal)
|
||||||
|
} else {
|
||||||
|
dstVal.Set(srcVal)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
182
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go
generated
vendored
Normal file
182
vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go
generated
vendored
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
package awsutil_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Struct struct {
|
||||||
|
A []Struct
|
||||||
|
z []Struct
|
||||||
|
B *Struct
|
||||||
|
D *Struct
|
||||||
|
C string
|
||||||
|
E map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = Struct{
|
||||||
|
A: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
|
||||||
|
z: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
|
||||||
|
B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}},
|
||||||
|
C: "initial",
|
||||||
|
}
|
||||||
|
var data2 = Struct{A: []Struct{
|
||||||
|
{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
|
||||||
|
{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
|
||||||
|
}}
|
||||||
|
|
||||||
|
func TestValueAtPathSuccess(t *testing.T) {
|
||||||
|
var testCases = []struct {
|
||||||
|
expect []interface{}
|
||||||
|
data interface{}
|
||||||
|
path string
|
||||||
|
}{
|
||||||
|
{[]interface{}{"initial"}, data, "C"},
|
||||||
|
{[]interface{}{"value1"}, data, "A[0].C"},
|
||||||
|
{[]interface{}{"value2"}, data, "A[1].C"},
|
||||||
|
{[]interface{}{"value3"}, data, "A[2].C"},
|
||||||
|
{[]interface{}{"value3"}, data, "a[2].c"},
|
||||||
|
{[]interface{}{"value3"}, data, "A[-1].C"},
|
||||||
|
{[]interface{}{"value1", "value2", "value3"}, data, "A[].C"},
|
||||||
|
{[]interface{}{"terminal"}, data, "B . B . C"},
|
||||||
|
{[]interface{}{"initial"}, data, "A.D.X || C"},
|
||||||
|
{[]interface{}{"initial"}, data, "A[0].B || C"},
|
||||||
|
{[]interface{}{
|
||||||
|
Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
|
||||||
|
Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
|
||||||
|
}, data2, "A"},
|
||||||
|
}
|
||||||
|
for i, c := range testCases {
|
||||||
|
v, err := awsutil.ValuesAtPath(c.data, c.path)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %v, expected no error, %v", i, c.path)
|
||||||
|
}
|
||||||
|
if e, a := c.expect, v; !awsutil.DeepEqual(e, a) {
|
||||||
|
t.Errorf("case %v, %v", i, c.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValueAtPathFailure(t *testing.T) {
|
||||||
|
var testCases = []struct {
|
||||||
|
expect []interface{}
|
||||||
|
errContains string
|
||||||
|
data interface{}
|
||||||
|
path string
|
||||||
|
}{
|
||||||
|
{nil, "", data, "C.x"},
|
||||||
|
{nil, "SyntaxError: Invalid token: tDot", data, ".x"},
|
||||||
|
{nil, "", data, "X.Y.Z"},
|
||||||
|
{nil, "", data, "A[100].C"},
|
||||||
|
{nil, "", data, "A[3].C"},
|
||||||
|
{nil, "", data, "B.B.C.Z"},
|
||||||
|
{nil, "", data, "z[-1].C"},
|
||||||
|
{nil, "", nil, "A.B.C"},
|
||||||
|
{[]interface{}{}, "", Struct{}, "A"},
|
||||||
|
{nil, "", data, "A[0].B.C"},
|
||||||
|
{nil, "", data, "D"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range testCases {
|
||||||
|
v, err := awsutil.ValuesAtPath(c.data, c.path)
|
||||||
|
if c.errContains != "" {
|
||||||
|
if !strings.Contains(err.Error(), c.errContains) {
|
||||||
|
t.Errorf("case %v, expected error, %v", i, c.path)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %v, expected no error, %v", i, c.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e, a := c.expect, v; !awsutil.DeepEqual(e, a) {
|
||||||
|
t.Errorf("case %v, %v", i, c.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetValueAtPathSuccess(t *testing.T) {
|
||||||
|
var s Struct
|
||||||
|
awsutil.SetValueAtPath(&s, "C", "test1")
|
||||||
|
awsutil.SetValueAtPath(&s, "B.B.C", "test2")
|
||||||
|
awsutil.SetValueAtPath(&s, "B.D.C", "test3")
|
||||||
|
if e, a := "test1", s.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "test2", s.B.B.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "test3", s.B.D.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
awsutil.SetValueAtPath(&s, "B.*.C", "test0")
|
||||||
|
if e, a := "test0", s.B.B.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "test0", s.B.D.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
var s2 Struct
|
||||||
|
awsutil.SetValueAtPath(&s2, "b.b.c", "test0")
|
||||||
|
if e, a := "test0", s2.B.B.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
awsutil.SetValueAtPath(&s2, "A", []Struct{{}})
|
||||||
|
if e, a := []Struct{{}}, s2.A; !awsutil.DeepEqual(e, a) {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
str := "foo"
|
||||||
|
|
||||||
|
s3 := Struct{}
|
||||||
|
awsutil.SetValueAtPath(&s3, "b.b.c", str)
|
||||||
|
if e, a := "foo", s3.B.B.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
s3 = Struct{B: &Struct{B: &Struct{C: str}}}
|
||||||
|
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
|
||||||
|
if e, a := "", s3.B.B.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
s3 = Struct{}
|
||||||
|
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
|
||||||
|
if e, a := "", s3.B.B.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
s3 = Struct{}
|
||||||
|
awsutil.SetValueAtPath(&s3, "b.b.c", &str)
|
||||||
|
if e, a := "foo", s3.B.B.C; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
var s4 struct{ Name *string }
|
||||||
|
awsutil.SetValueAtPath(&s4, "Name", str)
|
||||||
|
if e, a := str, *s4.Name; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
s4 = struct{ Name *string }{}
|
||||||
|
awsutil.SetValueAtPath(&s4, "Name", nil)
|
||||||
|
if e, a := (*string)(nil), s4.Name; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
s4 = struct{ Name *string }{Name: &str}
|
||||||
|
awsutil.SetValueAtPath(&s4, "Name", nil)
|
||||||
|
if e, a := (*string)(nil), s4.Name; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
s4 = struct{ Name *string }{}
|
||||||
|
awsutil.SetValueAtPath(&s4, "Name", &str)
|
||||||
|
if e, a := str, *s4.Name; e != a {
|
||||||
|
t.Errorf("expected %v, but received %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
10
vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
10
vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
|
@ -61,6 +61,12 @@ func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
|
||||||
|
|
||||||
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
|
strtype := v.Type().String()
|
||||||
|
if strtype == "[]uint8" {
|
||||||
|
fmt.Fprintf(buf, "<binary> len %d", v.Len())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
nl, id, id2 := "", "", ""
|
nl, id, id2 := "", "", ""
|
||||||
if v.Len() > 3 {
|
if v.Len() > 3 {
|
||||||
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
|
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
|
||||||
|
@ -91,6 +97,10 @@ func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
|
||||||
|
|
||||||
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||||
default:
|
default:
|
||||||
|
if !v.IsValid() {
|
||||||
|
fmt.Fprint(buf, "<invalid value>")
|
||||||
|
return
|
||||||
|
}
|
||||||
format := "%v"
|
format := "%v"
|
||||||
switch v.Interface().(type) {
|
switch v.Interface().(type) {
|
||||||
case string:
|
case string:
|
||||||
|
|
89
vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go
generated
vendored
Normal file
89
vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
package awsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StringValue returns the string representation of a value.
|
||||||
|
func StringValue(i interface{}) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
stringValue(reflect.ValueOf(i), 0, &buf)
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) {
|
||||||
|
for v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
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.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 + ": ")
|
||||||
|
stringValue(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)
|
||||||
|
stringValue(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() + ": ")
|
||||||
|
stringValue(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"
|
||||||
|
}
|
||||||
|
fmt.Fprintf(buf, format, v.Interface())
|
||||||
|
}
|
||||||
|
}
|
90
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
Normal file
90
vendor/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Config provides configuration to a service client instance.
|
||||||
|
type Config struct {
|
||||||
|
Config *aws.Config
|
||||||
|
Handlers request.Handlers
|
||||||
|
Endpoint string
|
||||||
|
SigningRegion string
|
||||||
|
SigningName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigProvider provides a generic way for a service client to receive
|
||||||
|
// the ClientConfig without circular dependencies.
|
||||||
|
type ConfigProvider interface {
|
||||||
|
ClientConfig(serviceName string, cfgs ...*aws.Config) Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigNoResolveEndpointProvider same as ConfigProvider except it will not
|
||||||
|
// resolve the endpoint automatically. The service client's endpoint must be
|
||||||
|
// provided via the aws.Config.Endpoint field.
|
||||||
|
type ConfigNoResolveEndpointProvider interface {
|
||||||
|
ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Client implements the base client request and response handling
|
||||||
|
// used by all service clients.
|
||||||
|
type Client struct {
|
||||||
|
request.Retryer
|
||||||
|
metadata.ClientInfo
|
||||||
|
|
||||||
|
Config aws.Config
|
||||||
|
Handlers request.Handlers
|
||||||
|
}
|
||||||
|
|
||||||
|
// New will return a pointer to a new initialized service client.
|
||||||
|
func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client {
|
||||||
|
svc := &Client{
|
||||||
|
Config: cfg,
|
||||||
|
ClientInfo: info,
|
||||||
|
Handlers: handlers.Copy(),
|
||||||
|
}
|
||||||
|
|
||||||
|
switch retryer, ok := cfg.Retryer.(request.Retryer); {
|
||||||
|
case ok:
|
||||||
|
svc.Retryer = retryer
|
||||||
|
case cfg.Retryer != nil && cfg.Logger != nil:
|
||||||
|
s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
|
||||||
|
cfg.Logger.Log(s)
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
maxRetries := aws.IntValue(cfg.MaxRetries)
|
||||||
|
if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
|
||||||
|
maxRetries = 3
|
||||||
|
}
|
||||||
|
svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
|
||||||
|
}
|
||||||
|
|
||||||
|
svc.AddDebugHandlers()
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
option(svc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest returns a new Request pointer for the service API
|
||||||
|
// operation and parameters.
|
||||||
|
func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
|
||||||
|
return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDebugHandlers injects debug logging handlers into the service to log request
|
||||||
|
// debug information.
|
||||||
|
func (c *Client) AddDebugHandlers() {
|
||||||
|
if !c.Config.LogLevel.AtLeast(aws.LogDebug) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Handlers.Send.PushFrontNamed(request.NamedHandler{Name: "awssdk.client.LogRequest", Fn: logRequest})
|
||||||
|
c.Handlers.Send.PushBackNamed(request.NamedHandler{Name: "awssdk.client.LogResponse", Fn: logResponse})
|
||||||
|
}
|
78
vendor/github.com/aws/aws-sdk-go/aws/client/client_test.go
generated
vendored
Normal file
78
vendor/github.com/aws/aws-sdk-go/aws/client/client_test.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
func pushBackTestHandler(name string, list *request.HandlerList) *bool {
|
||||||
|
called := false
|
||||||
|
(*list).PushBackNamed(request.NamedHandler{
|
||||||
|
Name: name,
|
||||||
|
Fn: func(r *request.Request) {
|
||||||
|
called = true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return &called
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushFrontTestHandler(name string, list *request.HandlerList) *bool {
|
||||||
|
called := false
|
||||||
|
(*list).PushFrontNamed(request.NamedHandler{
|
||||||
|
Name: name,
|
||||||
|
Fn: func(r *request.Request) {
|
||||||
|
called = true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return &called
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewClient_CopyHandlers(t *testing.T) {
|
||||||
|
handlers := request.Handlers{}
|
||||||
|
firstCalled := pushBackTestHandler("first", &handlers.Send)
|
||||||
|
secondCalled := pushBackTestHandler("second", &handlers.Send)
|
||||||
|
|
||||||
|
var clientHandlerCalled *bool
|
||||||
|
c := New(aws.Config{}, metadata.ClientInfo{}, handlers,
|
||||||
|
func(c *Client) {
|
||||||
|
clientHandlerCalled = pushFrontTestHandler("client handler", &c.Handlers.Send)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if e, a := 2, handlers.Send.Len(); e != a {
|
||||||
|
t.Errorf("expect %d original handlers, got %d", e, a)
|
||||||
|
}
|
||||||
|
if e, a := 3, c.Handlers.Send.Len(); e != a {
|
||||||
|
t.Errorf("expect %d client handlers, got %d", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers.Send.Run(nil)
|
||||||
|
if !*firstCalled {
|
||||||
|
t.Errorf("expect first handler to of been called")
|
||||||
|
}
|
||||||
|
*firstCalled = false
|
||||||
|
if !*secondCalled {
|
||||||
|
t.Errorf("expect second handler to of been called")
|
||||||
|
}
|
||||||
|
*secondCalled = false
|
||||||
|
if *clientHandlerCalled {
|
||||||
|
t.Errorf("expect client handler to not of been called, but was")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Handlers.Send.Run(nil)
|
||||||
|
if !*firstCalled {
|
||||||
|
t.Errorf("expect client's first handler to of been called")
|
||||||
|
}
|
||||||
|
if !*secondCalled {
|
||||||
|
t.Errorf("expect client's second handler to of been called")
|
||||||
|
}
|
||||||
|
if !*clientHandlerCalled {
|
||||||
|
t.Errorf("expect client's client handler to of been called")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
138
vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
generated
vendored
Normal file
138
vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
generated
vendored
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"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 {
|
||||||
|
// client.DefaultRetryer
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // This implementation always has 100 max retries
|
||||||
|
// func (d retryer) MaxRetries() int { return 100 }
|
||||||
|
type DefaultRetryer struct {
|
||||||
|
NumMaxRetries int
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxRetries returns the number of maximum returns the service will use to make
|
||||||
|
// an individual API request.
|
||||||
|
func (d DefaultRetryer) MaxRetries() int {
|
||||||
|
return d.NumMaxRetries
|
||||||
|
}
|
||||||
|
|
||||||
|
var seededRand = rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())})
|
||||||
|
|
||||||
|
// RetryRules returns the delay duration before retrying this request again
|
||||||
|
func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
|
||||||
|
// Set the upper limit of delay in retrying at ~five minutes
|
||||||
|
minTime := 30
|
||||||
|
throttle := d.shouldThrottle(r)
|
||||||
|
if throttle {
|
||||||
|
if delay, ok := getRetryDelay(r); ok {
|
||||||
|
return delay
|
||||||
|
}
|
||||||
|
|
||||||
|
minTime = 500
|
||||||
|
}
|
||||||
|
|
||||||
|
retryCount := r.RetryCount
|
||||||
|
if throttle && retryCount > 8 {
|
||||||
|
retryCount = 8
|
||||||
|
} else if retryCount > 13 {
|
||||||
|
retryCount = 13
|
||||||
|
}
|
||||||
|
|
||||||
|
delay := (1 << uint(retryCount)) * (seededRand.Intn(minTime) + minTime)
|
||||||
|
return time.Duration(delay) * time.Millisecond
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShouldRetry returns true if the request should be retried.
|
||||||
|
func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
|
||||||
|
// 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 {
|
||||||
|
return *r.Retryable
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.HTTPResponse.StatusCode >= 500 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return r.IsErrorRetryable() || d.shouldThrottle(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShouldThrottle returns true if the request should be throttled.
|
||||||
|
func (d DefaultRetryer) shouldThrottle(r *request.Request) bool {
|
||||||
|
switch r.HTTPResponse.StatusCode {
|
||||||
|
case 429:
|
||||||
|
case 502:
|
||||||
|
case 503:
|
||||||
|
case 504:
|
||||||
|
default:
|
||||||
|
return r.IsErrorThrottle()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will look in the Retry-After header, RFC 7231, for how long
|
||||||
|
// it will wait before attempting another request
|
||||||
|
func getRetryDelay(r *request.Request) (time.Duration, bool) {
|
||||||
|
if !canUseRetryAfterHeader(r) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
delayStr := r.HTTPResponse.Header.Get("Retry-After")
|
||||||
|
if len(delayStr) == 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
delay, err := strconv.Atoi(delayStr)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Duration(delay) * time.Second, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will look at the status code to see if the retry header pertains to
|
||||||
|
// the status code.
|
||||||
|
func canUseRetryAfterHeader(r *request.Request) bool {
|
||||||
|
switch r.HTTPResponse.StatusCode {
|
||||||
|
case 429:
|
||||||
|
case 503:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// lockedSource is a thread-safe implementation of rand.Source
|
||||||
|
type lockedSource struct {
|
||||||
|
lk sync.Mutex
|
||||||
|
src rand.Source
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *lockedSource) Int63() (n int64) {
|
||||||
|
r.lk.Lock()
|
||||||
|
n = r.src.Int63()
|
||||||
|
r.lk.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *lockedSource) Seed(seed int64) {
|
||||||
|
r.lk.Lock()
|
||||||
|
r.src.Seed(seed)
|
||||||
|
r.lk.Unlock()
|
||||||
|
}
|
189
vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer_test.go
generated
vendored
Normal file
189
vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer_test.go
generated
vendored
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRetryThrottleStatusCodes(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
expectThrottle bool
|
||||||
|
expectRetry bool
|
||||||
|
r request.Request
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 200},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 429},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 502},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 503},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 504},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 500},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
d := DefaultRetryer{NumMaxRetries: 10}
|
||||||
|
for i, c := range cases {
|
||||||
|
throttle := d.shouldThrottle(&c.r)
|
||||||
|
retry := d.ShouldRetry(&c.r)
|
||||||
|
|
||||||
|
if e, a := c.expectThrottle, throttle; e != a {
|
||||||
|
t.Errorf("%d: expected %v, but received %v", i, e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, a := c.expectRetry, retry; e != a {
|
||||||
|
t.Errorf("%d: expected %v, but received %v", i, e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCanUseRetryAfter(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
r request.Request
|
||||||
|
e bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 200},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 500},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 429},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 503},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
a := canUseRetryAfterHeader(&c.r)
|
||||||
|
if c.e != a {
|
||||||
|
t.Errorf("%d: expected %v, but received %v", i, c.e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetRetryDelay(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
r request.Request
|
||||||
|
e time.Duration
|
||||||
|
equal bool
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 429, Header: http.Header{"Retry-After": []string{"3600"}}},
|
||||||
|
},
|
||||||
|
3600 * time.Second,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 503, Header: http.Header{"Retry-After": []string{"120"}}},
|
||||||
|
},
|
||||||
|
120 * time.Second,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 503, Header: http.Header{"Retry-After": []string{"120"}}},
|
||||||
|
},
|
||||||
|
1 * time.Second,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
request.Request{
|
||||||
|
HTTPResponse: &http.Response{StatusCode: 503, Header: http.Header{"Retry-After": []string{""}}},
|
||||||
|
},
|
||||||
|
0 * time.Second,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
a, ok := getRetryDelay(&c.r)
|
||||||
|
if c.ok != ok {
|
||||||
|
t.Errorf("%d: expected %v, but received %v", i, c.ok, ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.e != a) == c.equal {
|
||||||
|
t.Errorf("%d: expected %v, but received %v", i, c.e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRetryDelay(t *testing.T) {
|
||||||
|
r := request.Request{}
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
rTemp := r
|
||||||
|
rTemp.HTTPResponse = &http.Response{StatusCode: 500, Header: http.Header{"Retry-After": []string{""}}}
|
||||||
|
rTemp.RetryCount = i
|
||||||
|
a, _ := getRetryDelay(&rTemp)
|
||||||
|
if a > 5*time.Minute {
|
||||||
|
t.Errorf("retry delay should never be greater than five minutes, received %d", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
rTemp := r
|
||||||
|
rTemp.RetryCount = i
|
||||||
|
rTemp.HTTPResponse = &http.Response{StatusCode: 503, Header: http.Header{"Retry-After": []string{""}}}
|
||||||
|
a, _ := getRetryDelay(&rTemp)
|
||||||
|
if a > 5*time.Minute {
|
||||||
|
t.Errorf("retry delay should never be greater than five minutes, received %d", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
vendor/github.com/aws/aws-sdk-go/aws/client/logger.go
generated
vendored
Normal file
108
vendor/github.com/aws/aws-sdk-go/aws/client/logger.go
generated
vendored
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http/httputil"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
const logReqMsg = `DEBUG: Request %s/%s Details:
|
||||||
|
---[ REQUEST POST-SIGN ]-----------------------------
|
||||||
|
%s
|
||||||
|
-----------------------------------------------------`
|
||||||
|
|
||||||
|
const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
|
||||||
|
---[ REQUEST DUMP ERROR ]-----------------------------
|
||||||
|
%s
|
||||||
|
------------------------------------------------------`
|
||||||
|
|
||||||
|
type logWriter struct {
|
||||||
|
// Logger is what we will use to log the payload of a response.
|
||||||
|
Logger aws.Logger
|
||||||
|
// buf stores the contents of what has been read
|
||||||
|
buf *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *logWriter) Write(b []byte) (int, error) {
|
||||||
|
return logger.buf.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type teeReaderCloser struct {
|
||||||
|
// io.Reader will be a tee reader that is used during logging.
|
||||||
|
// This structure will read from a body and write the contents to a logger.
|
||||||
|
io.Reader
|
||||||
|
// Source is used just to close when we are done reading.
|
||||||
|
Source io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (reader *teeReaderCloser) Close() error {
|
||||||
|
return reader.Source.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func logRequest(r *request.Request) {
|
||||||
|
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||||
|
dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
|
||||||
|
if err != nil {
|
||||||
|
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if logBody {
|
||||||
|
// 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.ResetBody()
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const logRespMsg = `DEBUG: Response %s/%s Details:
|
||||||
|
---[ RESPONSE ]--------------------------------------
|
||||||
|
%s
|
||||||
|
-----------------------------------------------------`
|
||||||
|
|
||||||
|
const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
|
||||||
|
---[ RESPONSE DUMP ERROR ]-----------------------------
|
||||||
|
%s
|
||||||
|
-----------------------------------------------------`
|
||||||
|
|
||||||
|
func logResponse(r *request.Request) {
|
||||||
|
lw := &logWriter{r.Config.Logger, bytes.NewBuffer(nil)}
|
||||||
|
r.HTTPResponse.Body = &teeReaderCloser{
|
||||||
|
Reader: io.TeeReader(r.HTTPResponse.Body, lw),
|
||||||
|
Source: r.HTTPResponse.Body,
|
||||||
|
}
|
||||||
|
|
||||||
|
handlerFn := func(req *request.Request) {
|
||||||
|
body, err := httputil.DumpResponse(req.HTTPResponse, false)
|
||||||
|
if err != nil {
|
||||||
|
lw.Logger.Log(fmt.Sprintf(logRespErrMsg, req.ClientInfo.ServiceName, req.Operation.Name, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(lw.buf)
|
||||||
|
if err != nil {
|
||||||
|
lw.Logger.Log(fmt.Sprintf(logRespErrMsg, req.ClientInfo.ServiceName, req.Operation.Name, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lw.Logger.Log(fmt.Sprintf(logRespMsg, req.ClientInfo.ServiceName, req.Operation.Name, string(body)))
|
||||||
|
if req.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) {
|
||||||
|
lw.Logger.Log(string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlerName = "awsdk.client.LogResponse.ResponseBody"
|
||||||
|
|
||||||
|
r.Handlers.Unmarshal.SetBackNamed(request.NamedHandler{
|
||||||
|
Name: handlerName, Fn: handlerFn,
|
||||||
|
})
|
||||||
|
r.Handlers.UnmarshalError.SetBackNamed(request.NamedHandler{
|
||||||
|
Name: handlerName, Fn: handlerFn,
|
||||||
|
})
|
||||||
|
}
|
57
vendor/github.com/aws/aws-sdk-go/aws/client/logger_test.go
generated
vendored
Normal file
57
vendor/github.com/aws/aws-sdk-go/aws/client/logger_test.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockCloser struct {
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (closer *mockCloser) Read(b []byte) (int, error) {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
func (closer *mockCloser) Close() error {
|
||||||
|
closer.closed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTeeReaderCloser(t *testing.T) {
|
||||||
|
expected := "FOO"
|
||||||
|
buf := bytes.NewBuffer([]byte(expected))
|
||||||
|
lw := bytes.NewBuffer(nil)
|
||||||
|
c := &mockCloser{}
|
||||||
|
closer := teeReaderCloser{
|
||||||
|
io.TeeReader(buf, lw),
|
||||||
|
c,
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make([]byte, len(expected))
|
||||||
|
_, err := closer.Read(b)
|
||||||
|
closer.Close()
|
||||||
|
|
||||||
|
if expected != lw.String() {
|
||||||
|
t.Errorf("Expected %q, but received %q", expected, lw.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected 'nil', but received %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.closed {
|
||||||
|
t.Error("Expected 'true', but received 'false'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogWriter(t *testing.T) {
|
||||||
|
expected := "FOO"
|
||||||
|
lw := &logWriter{nil, bytes.NewBuffer(nil)}
|
||||||
|
lw.Write([]byte(expected))
|
||||||
|
|
||||||
|
if expected != lw.buf.String() {
|
||||||
|
t.Errorf("Expected %q, but received %q", expected, lw.buf.String())
|
||||||
|
}
|
||||||
|
}
|
12
vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go
generated
vendored
Normal file
12
vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
// ClientInfo wraps immutable data from the client.Client structure.
|
||||||
|
type ClientInfo struct {
|
||||||
|
ServiceName string
|
||||||
|
APIVersion string
|
||||||
|
Endpoint string
|
||||||
|
SigningName string
|
||||||
|
SigningRegion string
|
||||||
|
JSONVersion string
|
||||||
|
TargetPrefix string
|
||||||
|
}
|
283
vendor/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
283
vendor/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
|
@ -5,17 +5,40 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/endpoints"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The default number of retries for a service. The value of -1 indicates that
|
// UseServiceDefaultRetries instructs the config to use the service's own
|
||||||
// the service specific retry default will be used.
|
// default number of retries. This will be the default action if
|
||||||
const DefaultRetries = -1
|
// Config.MaxRetries is nil also.
|
||||||
|
const UseServiceDefaultRetries = -1
|
||||||
|
|
||||||
|
// RequestRetryer is an alias for a type that implements the request.Retryer
|
||||||
|
// interface.
|
||||||
|
type RequestRetryer interface{}
|
||||||
|
|
||||||
// A Config provides service configuration for service clients. By default,
|
// A Config provides service configuration for service clients. By default,
|
||||||
// all clients will use the {defaults.DefaultConfig} structure.
|
// all clients will use the defaults.DefaultConfig tructure.
|
||||||
|
//
|
||||||
|
// // Create Session with MaxRetry configuration to be shared by multiple
|
||||||
|
// // service clients.
|
||||||
|
// sess := session.Must(session.NewSession(&aws.Config{
|
||||||
|
// MaxRetries: aws.Int(3),
|
||||||
|
// }))
|
||||||
|
//
|
||||||
|
// // Create S3 service client with a specific Region.
|
||||||
|
// svc := s3.New(sess, &aws.Config{
|
||||||
|
// Region: aws.String("us-west-2"),
|
||||||
|
// })
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// The credentials object to use when signing requests. Defaults to
|
// Enables verbose error printing of all credential chain errors.
|
||||||
// {defaults.DefaultChainCredentials}.
|
// Should be used when wanting to see all errors while attempting to
|
||||||
|
// retrieve credentials.
|
||||||
|
CredentialsChainVerboseErrors *bool
|
||||||
|
|
||||||
|
// The credentials object to use when signing requests. Defaults to a
|
||||||
|
// chain of credential providers to search for credentials in environment
|
||||||
|
// variables, shared credential file, and EC2 Instance Roles.
|
||||||
Credentials *credentials.Credentials
|
Credentials *credentials.Credentials
|
||||||
|
|
||||||
// An optional endpoint URL (hostname only or fully qualified URI)
|
// An optional endpoint URL (hostname only or fully qualified URI)
|
||||||
|
@ -26,6 +49,17 @@ type Config struct {
|
||||||
// endpoint for a client.
|
// endpoint for a client.
|
||||||
Endpoint *string
|
Endpoint *string
|
||||||
|
|
||||||
|
// The resolver to use for looking up endpoints for AWS service clients
|
||||||
|
// to use based on region.
|
||||||
|
EndpointResolver endpoints.Resolver
|
||||||
|
|
||||||
|
// EnforceShouldRetryCheck is used in the AfterRetryHandler to always call
|
||||||
|
// ShouldRetry regardless of whether or not if request.Retryable is set.
|
||||||
|
// This will utilize ShouldRetry method of custom retryers. If EnforceShouldRetryCheck
|
||||||
|
// is not set, then ShouldRetry will only be called if request.Retryable is nil.
|
||||||
|
// Proper handling of the request.Retryable field is important when setting this field.
|
||||||
|
EnforceShouldRetryCheck *bool
|
||||||
|
|
||||||
// The region to send requests to. This parameter is required and must
|
// The region to send requests to. This parameter is required and must
|
||||||
// be configured globally or on a per-client basis unless otherwise
|
// be configured globally or on a per-client basis unless otherwise
|
||||||
// noted. A full list of regions is found in the "Regions and Endpoints"
|
// noted. A full list of regions is found in the "Regions and Endpoints"
|
||||||
|
@ -53,12 +87,28 @@ type Config struct {
|
||||||
Logger Logger
|
Logger Logger
|
||||||
|
|
||||||
// The maximum number of times that a request will be retried for failures.
|
// The maximum number of times that a request will be retried for failures.
|
||||||
// Defaults to -1, which defers the max retry setting to the service specific
|
// Defaults to -1, which defers the max retry setting to the service
|
||||||
// configuration.
|
// specific configuration.
|
||||||
MaxRetries *int
|
MaxRetries *int
|
||||||
|
|
||||||
// Disables semantic parameter validation, which validates input for missing
|
// Retryer guides how HTTP requests should be retried in case of
|
||||||
// required fields and/or other semantic request input errors.
|
// recoverable failures.
|
||||||
|
//
|
||||||
|
// When nil or the value does not implement the request.Retryer interface,
|
||||||
|
// the client.DefaultRetryer will be used.
|
||||||
|
//
|
||||||
|
// When both Retryer and MaxRetries are non-nil, the former is used and
|
||||||
|
// the latter ignored.
|
||||||
|
//
|
||||||
|
// To set the Retryer field in a type-safe manner and with chaining, use
|
||||||
|
// the request.WithRetryer helper function:
|
||||||
|
//
|
||||||
|
// cfg := request.WithRetryer(aws.NewConfig(), myRetryer)
|
||||||
|
//
|
||||||
|
Retryer RequestRetryer
|
||||||
|
|
||||||
|
// Disables semantic parameter validation, which validates input for
|
||||||
|
// missing required fields and/or other semantic request input errors.
|
||||||
DisableParamValidation *bool
|
DisableParamValidation *bool
|
||||||
|
|
||||||
// Disables the computation of request and response checksums, e.g.,
|
// Disables the computation of request and response checksums, e.g.,
|
||||||
|
@ -66,8 +116,8 @@ type Config struct {
|
||||||
DisableComputeChecksums *bool
|
DisableComputeChecksums *bool
|
||||||
|
|
||||||
// Set this to `true` to force the request to use path-style addressing,
|
// Set this to `true` to force the request to use path-style addressing,
|
||||||
// i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client will
|
// i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client
|
||||||
// use virtual hosted bucket addressing when possible
|
// will use virtual hosted bucket addressing when possible
|
||||||
// (`http://BUCKET.s3.amazonaws.com/KEY`).
|
// (`http://BUCKET.s3.amazonaws.com/KEY`).
|
||||||
//
|
//
|
||||||
// @note This configuration option is specific to the Amazon S3 service.
|
// @note This configuration option is specific to the Amazon S3 service.
|
||||||
|
@ -75,18 +125,121 @@ type Config struct {
|
||||||
// Amazon S3: Virtual Hosting of Buckets
|
// Amazon S3: Virtual Hosting of Buckets
|
||||||
S3ForcePathStyle *bool
|
S3ForcePathStyle *bool
|
||||||
|
|
||||||
|
// Set this to `true` to disable the SDK adding the `Expect: 100-Continue`
|
||||||
|
// header to PUT requests over 2MB of content. 100-Continue instructs the
|
||||||
|
// HTTP client not to send the body until the service responds with a
|
||||||
|
// `continue` status. This is useful to prevent sending the request body
|
||||||
|
// until after the request is authenticated, and validated.
|
||||||
|
//
|
||||||
|
// http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
|
||||||
|
//
|
||||||
|
// 100-Continue is only enabled for Go 1.6 and above. See `http.Transport`'s
|
||||||
|
// `ExpectContinueTimeout` for information on adjusting the continue wait
|
||||||
|
// timeout. https://golang.org/pkg/net/http/#Transport
|
||||||
|
//
|
||||||
|
// You should use this flag to disble 100-Continue if you experience issues
|
||||||
|
// with proxies or third party S3 compatible services.
|
||||||
|
S3Disable100Continue *bool
|
||||||
|
|
||||||
|
// Set this to `true` to enable S3 Accelerate feature. For all operations
|
||||||
|
// compatible with S3 Accelerate will use the accelerate endpoint for
|
||||||
|
// requests. Requests not compatible will fall back to normal S3 requests.
|
||||||
|
//
|
||||||
|
// The bucket must be enable for accelerate to be used with S3 client with
|
||||||
|
// accelerate enabled. If the bucket is not enabled for accelerate an error
|
||||||
|
// will be returned. The bucket name must be DNS compatible to also work
|
||||||
|
// with accelerate.
|
||||||
|
S3UseAccelerate *bool
|
||||||
|
|
||||||
|
// Set this to `true` to disable the EC2Metadata client from overriding the
|
||||||
|
// default http.Client's Timeout. This is helpful if you do not want the
|
||||||
|
// EC2Metadata client to create a new http.Client. This options is only
|
||||||
|
// meaningful if you're not already using a custom HTTP client with the
|
||||||
|
// SDK. Enabled by default.
|
||||||
|
//
|
||||||
|
// Must be set and provided to the session.NewSession() in order to disable
|
||||||
|
// the EC2Metadata overriding the timeout for default credentials chain.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// sess := session.Must(session.NewSession(aws.NewConfig()
|
||||||
|
// .WithEC2MetadataDiableTimeoutOverride(true)))
|
||||||
|
//
|
||||||
|
// svc := s3.New(sess)
|
||||||
|
//
|
||||||
|
EC2MetadataDisableTimeoutOverride *bool
|
||||||
|
|
||||||
|
// Instructs the endpiont to be generated for a service client to
|
||||||
|
// be the dual stack endpoint. The dual stack endpoint will support
|
||||||
|
// both IPv4 and IPv6 addressing.
|
||||||
|
//
|
||||||
|
// Setting this for a service which does not support dual stack will fail
|
||||||
|
// to make requets. It is not recommended to set this value on the session
|
||||||
|
// as it will apply to all service clients created with the session. Even
|
||||||
|
// services which don't support dual stack endpoints.
|
||||||
|
//
|
||||||
|
// If the Endpoint config value is also provided the UseDualStack flag
|
||||||
|
// will be ignored.
|
||||||
|
//
|
||||||
|
// Only supported with.
|
||||||
|
//
|
||||||
|
// sess := session.Must(session.NewSession())
|
||||||
|
//
|
||||||
|
// svc := s3.New(sess, &aws.Config{
|
||||||
|
// UseDualStack: aws.Bool(true),
|
||||||
|
// })
|
||||||
|
UseDualStack *bool
|
||||||
|
|
||||||
|
// SleepDelay is an override for the func the SDK will call when sleeping
|
||||||
|
// during the lifecycle of a request. Specifically this will be used for
|
||||||
|
// request delays. This value should only be used for testing. To adjust
|
||||||
|
// the delay of a request see the aws/client.DefaultRetryer and
|
||||||
|
// aws/request.Retryer.
|
||||||
|
//
|
||||||
|
// SleepDelay will prevent any Context from being used for canceling retry
|
||||||
|
// delay of an API operation. It is recommended to not use SleepDelay at all
|
||||||
|
// and specify a Retryer instead.
|
||||||
SleepDelay func(time.Duration)
|
SleepDelay func(time.Duration)
|
||||||
|
|
||||||
|
// DisableRestProtocolURICleaning will not clean the URL path when making rest protocol requests.
|
||||||
|
// Will default to false. This would only be used for empty directory names in s3 requests.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// sess := session.Must(session.NewSession(&aws.Config{
|
||||||
|
// DisableRestProtocolURICleaning: aws.Bool(true),
|
||||||
|
// }))
|
||||||
|
//
|
||||||
|
// svc := s3.New(sess)
|
||||||
|
// out, err := svc.GetObject(&s3.GetObjectInput {
|
||||||
|
// Bucket: aws.String("bucketname"),
|
||||||
|
// Key: aws.String("//foo//bar//moo"),
|
||||||
|
// })
|
||||||
|
DisableRestProtocolURICleaning *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig returns a new Config pointer that can be chained with builder methods to
|
// NewConfig returns a new Config pointer that can be chained with builder
|
||||||
// set multiple configuration values inline without using pointers.
|
// methods to set multiple configuration values inline without using pointers.
|
||||||
//
|
//
|
||||||
// svc := s3.New(aws.NewConfig().WithRegion("us-west-2").WithMaxRetries(10))
|
// // Create Session with MaxRetry configuration to be shared by multiple
|
||||||
|
// // service clients.
|
||||||
|
// sess := session.Must(session.NewSession(aws.NewConfig().
|
||||||
|
// WithMaxRetries(3),
|
||||||
|
// ))
|
||||||
//
|
//
|
||||||
|
// // Create S3 service client with a specific Region.
|
||||||
|
// svc := s3.New(sess, aws.NewConfig().
|
||||||
|
// WithRegion("us-west-2"),
|
||||||
|
// )
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
return &Config{}
|
return &Config{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithCredentialsChainVerboseErrors sets a config verbose errors boolean and returning
|
||||||
|
// a Config pointer.
|
||||||
|
func (c *Config) WithCredentialsChainVerboseErrors(verboseErrs bool) *Config {
|
||||||
|
c.CredentialsChainVerboseErrors = &verboseErrs
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// WithCredentials sets a config Credentials value returning a Config pointer
|
// WithCredentials sets a config Credentials value returning a Config pointer
|
||||||
// for chaining.
|
// for chaining.
|
||||||
func (c *Config) WithCredentials(creds *credentials.Credentials) *Config {
|
func (c *Config) WithCredentials(creds *credentials.Credentials) *Config {
|
||||||
|
@ -101,6 +254,13 @@ func (c *Config) WithEndpoint(endpoint string) *Config {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithEndpointResolver sets a config EndpointResolver value returning a
|
||||||
|
// Config pointer for chaining.
|
||||||
|
func (c *Config) WithEndpointResolver(resolver endpoints.Resolver) *Config {
|
||||||
|
c.EndpointResolver = resolver
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// WithRegion sets a config Region value returning a Config pointer for
|
// WithRegion sets a config Region value returning a Config pointer for
|
||||||
// chaining.
|
// chaining.
|
||||||
func (c *Config) WithRegion(region string) *Config {
|
func (c *Config) WithRegion(region string) *Config {
|
||||||
|
@ -164,6 +324,34 @@ func (c *Config) WithS3ForcePathStyle(force bool) *Config {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithS3Disable100Continue sets a config S3Disable100Continue value returning
|
||||||
|
// a Config pointer for chaining.
|
||||||
|
func (c *Config) WithS3Disable100Continue(disable bool) *Config {
|
||||||
|
c.S3Disable100Continue = &disable
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithS3UseAccelerate sets a config S3UseAccelerate value returning a Config
|
||||||
|
// pointer for chaining.
|
||||||
|
func (c *Config) WithS3UseAccelerate(enable bool) *Config {
|
||||||
|
c.S3UseAccelerate = &enable
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithUseDualStack sets a config UseDualStack value returning a Config
|
||||||
|
// pointer for chaining.
|
||||||
|
func (c *Config) WithUseDualStack(enable bool) *Config {
|
||||||
|
c.UseDualStack = &enable
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithEC2MetadataDisableTimeoutOverride sets a config EC2MetadataDisableTimeoutOverride value
|
||||||
|
// returning a Config pointer for chaining.
|
||||||
|
func (c *Config) WithEC2MetadataDisableTimeoutOverride(enable bool) *Config {
|
||||||
|
c.EC2MetadataDisableTimeoutOverride = &enable
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// WithSleepDelay overrides the function used to sleep while waiting for the
|
// WithSleepDelay overrides the function used to sleep while waiting for the
|
||||||
// next retry. Defaults to time.Sleep.
|
// next retry. Defaults to time.Sleep.
|
||||||
func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
|
func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
|
||||||
|
@ -171,15 +359,21 @@ func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge returns a new Config with the other Config's attribute values merged into
|
// MergeIn merges the passed in configs into the existing config object.
|
||||||
// this Config. If the other Config's attribute is nil it will not be merged into
|
func (c *Config) MergeIn(cfgs ...*Config) {
|
||||||
// the new Config to be returned.
|
for _, other := range cfgs {
|
||||||
func (c Config) Merge(other *Config) *Config {
|
mergeInConfig(c, other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeInConfig(dst *Config, other *Config) {
|
||||||
if other == nil {
|
if other == nil {
|
||||||
return &c
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := c
|
if other.CredentialsChainVerboseErrors != nil {
|
||||||
|
dst.CredentialsChainVerboseErrors = other.CredentialsChainVerboseErrors
|
||||||
|
}
|
||||||
|
|
||||||
if other.Credentials != nil {
|
if other.Credentials != nil {
|
||||||
dst.Credentials = other.Credentials
|
dst.Credentials = other.Credentials
|
||||||
|
@ -189,6 +383,10 @@ func (c Config) Merge(other *Config) *Config {
|
||||||
dst.Endpoint = other.Endpoint
|
dst.Endpoint = other.Endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if other.EndpointResolver != nil {
|
||||||
|
dst.EndpointResolver = other.EndpointResolver
|
||||||
|
}
|
||||||
|
|
||||||
if other.Region != nil {
|
if other.Region != nil {
|
||||||
dst.Region = other.Region
|
dst.Region = other.Region
|
||||||
}
|
}
|
||||||
|
@ -213,6 +411,10 @@ func (c Config) Merge(other *Config) *Config {
|
||||||
dst.MaxRetries = other.MaxRetries
|
dst.MaxRetries = other.MaxRetries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if other.Retryer != nil {
|
||||||
|
dst.Retryer = other.Retryer
|
||||||
|
}
|
||||||
|
|
||||||
if other.DisableParamValidation != nil {
|
if other.DisableParamValidation != nil {
|
||||||
dst.DisableParamValidation = other.DisableParamValidation
|
dst.DisableParamValidation = other.DisableParamValidation
|
||||||
}
|
}
|
||||||
|
@ -225,15 +427,44 @@ func (c Config) Merge(other *Config) *Config {
|
||||||
dst.S3ForcePathStyle = other.S3ForcePathStyle
|
dst.S3ForcePathStyle = other.S3ForcePathStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if other.S3Disable100Continue != nil {
|
||||||
|
dst.S3Disable100Continue = other.S3Disable100Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.S3UseAccelerate != nil {
|
||||||
|
dst.S3UseAccelerate = other.S3UseAccelerate
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.UseDualStack != nil {
|
||||||
|
dst.UseDualStack = other.UseDualStack
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.EC2MetadataDisableTimeoutOverride != nil {
|
||||||
|
dst.EC2MetadataDisableTimeoutOverride = other.EC2MetadataDisableTimeoutOverride
|
||||||
|
}
|
||||||
|
|
||||||
if other.SleepDelay != nil {
|
if other.SleepDelay != nil {
|
||||||
dst.SleepDelay = other.SleepDelay
|
dst.SleepDelay = other.SleepDelay
|
||||||
}
|
}
|
||||||
|
|
||||||
return &dst
|
if other.DisableRestProtocolURICleaning != nil {
|
||||||
|
dst.DisableRestProtocolURICleaning = other.DisableRestProtocolURICleaning
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.EnforceShouldRetryCheck != nil {
|
||||||
|
dst.EnforceShouldRetryCheck = other.EnforceShouldRetryCheck
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy will return a shallow copy of the Config object.
|
// Copy will return a shallow copy of the Config object. If any additional
|
||||||
func (c Config) Copy() *Config {
|
// configurations are provided they will be merged into the new config returned.
|
||||||
dst := c
|
func (c *Config) Copy(cfgs ...*Config) *Config {
|
||||||
return &dst
|
dst := &Config{}
|
||||||
|
dst.MergeIn(c)
|
||||||
|
|
||||||
|
for _, cfg := range cfgs {
|
||||||
|
dst.MergeIn(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst
|
||||||
}
|
}
|
||||||
|
|
86
vendor/github.com/aws/aws-sdk-go/aws/config_test.go
generated
vendored
Normal file
86
vendor/github.com/aws/aws-sdk-go/aws/config_test.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testCredentials = credentials.NewStaticCredentials("AKID", "SECRET", "SESSION")
|
||||||
|
|
||||||
|
var copyTestConfig = Config{
|
||||||
|
Credentials: testCredentials,
|
||||||
|
Endpoint: String("CopyTestEndpoint"),
|
||||||
|
Region: String("COPY_TEST_AWS_REGION"),
|
||||||
|
DisableSSL: Bool(true),
|
||||||
|
HTTPClient: http.DefaultClient,
|
||||||
|
LogLevel: LogLevel(LogDebug),
|
||||||
|
Logger: NewDefaultLogger(),
|
||||||
|
MaxRetries: Int(3),
|
||||||
|
DisableParamValidation: Bool(true),
|
||||||
|
DisableComputeChecksums: Bool(true),
|
||||||
|
S3ForcePathStyle: Bool(true),
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopy(t *testing.T) {
|
||||||
|
want := copyTestConfig
|
||||||
|
got := copyTestConfig.Copy()
|
||||||
|
if !reflect.DeepEqual(*got, want) {
|
||||||
|
t.Errorf("Copy() = %+v", got)
|
||||||
|
t.Errorf(" want %+v", want)
|
||||||
|
}
|
||||||
|
|
||||||
|
got.Region = String("other")
|
||||||
|
if got.Region == want.Region {
|
||||||
|
t.Errorf("Expect setting copy values not not reflect in source")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyReturnsNewInstance(t *testing.T) {
|
||||||
|
want := copyTestConfig
|
||||||
|
got := copyTestConfig.Copy()
|
||||||
|
if got == &want {
|
||||||
|
t.Errorf("Copy() = %p; want different instance as source %p", got, &want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var mergeTestZeroValueConfig = Config{}
|
||||||
|
|
||||||
|
var mergeTestConfig = Config{
|
||||||
|
Credentials: testCredentials,
|
||||||
|
Endpoint: String("MergeTestEndpoint"),
|
||||||
|
Region: String("MERGE_TEST_AWS_REGION"),
|
||||||
|
DisableSSL: Bool(true),
|
||||||
|
HTTPClient: http.DefaultClient,
|
||||||
|
LogLevel: LogLevel(LogDebug),
|
||||||
|
Logger: NewDefaultLogger(),
|
||||||
|
MaxRetries: Int(10),
|
||||||
|
DisableParamValidation: Bool(true),
|
||||||
|
DisableComputeChecksums: Bool(true),
|
||||||
|
S3ForcePathStyle: Bool(true),
|
||||||
|
}
|
||||||
|
|
||||||
|
var mergeTests = []struct {
|
||||||
|
cfg *Config
|
||||||
|
in *Config
|
||||||
|
want *Config
|
||||||
|
}{
|
||||||
|
{&Config{}, nil, &Config{}},
|
||||||
|
{&Config{}, &mergeTestZeroValueConfig, &Config{}},
|
||||||
|
{&Config{}, &mergeTestConfig, &mergeTestConfig},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMerge(t *testing.T) {
|
||||||
|
for i, tt := range mergeTests {
|
||||||
|
got := tt.cfg.Copy()
|
||||||
|
got.MergeIn(tt.in)
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Config %d %+v", i, tt.cfg)
|
||||||
|
t.Errorf(" Merge(%+v)", tt.in)
|
||||||
|
t.Errorf(" got %+v", got)
|
||||||
|
t.Errorf(" want %+v", tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
vendor/github.com/aws/aws-sdk-go/aws/context.go
generated
vendored
Normal file
71
vendor/github.com/aws/aws-sdk-go/aws/context.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Context is an copy of the Go v1.7 stdlib's context.Context interface.
|
||||||
|
// It is represented as a SDK interface to enable you to use the "WithContext"
|
||||||
|
// API methods with Go v1.6 and a Context type such as golang.org/x/net/context.
|
||||||
|
//
|
||||||
|
// See https://golang.org/pkg/context on how to use contexts.
|
||||||
|
type Context interface {
|
||||||
|
// Deadline returns the time when work done on behalf of this context
|
||||||
|
// should be canceled. Deadline returns ok==false when no deadline is
|
||||||
|
// set. Successive calls to Deadline return the same results.
|
||||||
|
Deadline() (deadline time.Time, ok bool)
|
||||||
|
|
||||||
|
// Done returns a channel that's closed when work done on behalf of this
|
||||||
|
// context should be canceled. Done may return nil if this context can
|
||||||
|
// never be canceled. Successive calls to Done return the same value.
|
||||||
|
Done() <-chan struct{}
|
||||||
|
|
||||||
|
// Err returns a non-nil error value after Done is closed. Err returns
|
||||||
|
// Canceled if the context was canceled or DeadlineExceeded if the
|
||||||
|
// context's deadline passed. No other values for Err are defined.
|
||||||
|
// After Done is closed, successive calls to Err return the same value.
|
||||||
|
Err() error
|
||||||
|
|
||||||
|
// Value returns the value associated with this context for key, or nil
|
||||||
|
// if no value is associated with key. Successive calls to Value with
|
||||||
|
// the same key returns the same result.
|
||||||
|
//
|
||||||
|
// Use context values only for request-scoped data that transits
|
||||||
|
// processes and API boundaries, not for passing optional parameters to
|
||||||
|
// functions.
|
||||||
|
Value(key interface{}) interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BackgroundContext returns a context that will never be canceled, has no
|
||||||
|
// values, and no deadline. This context is used by the SDK to provide
|
||||||
|
// backwards compatibility with non-context API operations and functionality.
|
||||||
|
//
|
||||||
|
// Go 1.6 and before:
|
||||||
|
// This context function is equivalent to context.Background in the Go stdlib.
|
||||||
|
//
|
||||||
|
// Go 1.7 and later:
|
||||||
|
// The context returned will be the value returned by context.Background()
|
||||||
|
//
|
||||||
|
// See https://golang.org/pkg/context for more information on Contexts.
|
||||||
|
func BackgroundContext() Context {
|
||||||
|
return backgroundCtx
|
||||||
|
}
|
||||||
|
|
||||||
|
// SleepWithContext will wait for the timer duration to expire, or the context
|
||||||
|
// is canceled. Which ever happens first. If the context is canceled the Context's
|
||||||
|
// error will be returned.
|
||||||
|
//
|
||||||
|
// Expects Context to always return a non-nil error if the Done channel is closed.
|
||||||
|
func SleepWithContext(ctx Context, dur time.Duration) error {
|
||||||
|
t := time.NewTimer(dur)
|
||||||
|
defer t.Stop()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
break
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
41
vendor/github.com/aws/aws-sdk-go/aws/context_1_6.go
generated
vendored
Normal file
41
vendor/github.com/aws/aws-sdk-go/aws/context_1_6.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// An emptyCtx is a copy of the Go 1.7 context.emptyCtx type. This is copied to
|
||||||
|
// provide a 1.6 and 1.5 safe version of context that is compatible with Go
|
||||||
|
// 1.7's Context.
|
||||||
|
//
|
||||||
|
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
||||||
|
// struct{}, since vars of this type must have distinct addresses.
|
||||||
|
type emptyCtx int
|
||||||
|
|
||||||
|
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*emptyCtx) Done() <-chan struct{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*emptyCtx) Err() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*emptyCtx) Value(key interface{}) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *emptyCtx) String() string {
|
||||||
|
switch e {
|
||||||
|
case backgroundCtx:
|
||||||
|
return "aws.BackgroundContext"
|
||||||
|
}
|
||||||
|
return "unknown empty Context"
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
backgroundCtx = new(emptyCtx)
|
||||||
|
)
|
9
vendor/github.com/aws/aws-sdk-go/aws/context_1_7.go
generated
vendored
Normal file
9
vendor/github.com/aws/aws-sdk-go/aws/context_1_7.go
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
var (
|
||||||
|
backgroundCtx = context.Background()
|
||||||
|
)
|
37
vendor/github.com/aws/aws-sdk-go/aws/context_test.go
generated
vendored
Normal file
37
vendor/github.com/aws/aws-sdk-go/aws/context_test.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package aws_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSleepWithContext(t *testing.T) {
|
||||||
|
ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})}
|
||||||
|
|
||||||
|
err := aws.SleepWithContext(ctx, 1*time.Millisecond)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect context to not be canceled, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSleepWithContext_Canceled(t *testing.T) {
|
||||||
|
ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})}
|
||||||
|
|
||||||
|
expectErr := fmt.Errorf("context canceled")
|
||||||
|
|
||||||
|
ctx.Error = expectErr
|
||||||
|
close(ctx.DoneCh)
|
||||||
|
|
||||||
|
err := aws.SleepWithContext(ctx, 1*time.Millisecond)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expect error, did not get one")
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, a := expectErr, err; e != a {
|
||||||
|
t.Errorf("expect %v error, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
42
vendor/github.com/aws/aws-sdk-go/aws/convert_types.go
generated
vendored
42
vendor/github.com/aws/aws-sdk-go/aws/convert_types.go
generated
vendored
|
@ -2,7 +2,7 @@ package aws
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
// String returns a pointer to of the string value passed in.
|
// String returns a pointer to the string value passed in.
|
||||||
func String(v string) *string {
|
func String(v string) *string {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func StringValueMap(src map[string]*string) map[string]string {
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool returns a pointer to of the bool value passed in.
|
// Bool returns a pointer to the bool value passed in.
|
||||||
func Bool(v bool) *bool {
|
func Bool(v bool) *bool {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ func BoolValueMap(src map[string]*bool) map[string]bool {
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int returns a pointer to of the int value passed in.
|
// Int returns a pointer to the int value passed in.
|
||||||
func Int(v int) *int {
|
func Int(v int) *int {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ func IntValueMap(src map[string]*int) map[string]int {
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64 returns a pointer to of the int64 value passed in.
|
// Int64 returns a pointer to the int64 value passed in.
|
||||||
func Int64(v int64) *int64 {
|
func Int64(v int64) *int64 {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ func Int64ValueMap(src map[string]*int64) map[string]int64 {
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float64 returns a pointer to of the float64 value passed in.
|
// Float64 returns a pointer to the float64 value passed in.
|
||||||
func Float64(v float64) *float64 {
|
func Float64(v float64) *float64 {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
@ -297,7 +297,7 @@ func Float64ValueMap(src map[string]*float64) map[string]float64 {
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time returns a pointer to of the time.Time value passed in.
|
// Time returns a pointer to the time.Time value passed in.
|
||||||
func Time(v time.Time) *time.Time {
|
func Time(v time.Time) *time.Time {
|
||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
@ -311,6 +311,36 @@ func TimeValue(v *time.Time) time.Time {
|
||||||
return time.Time{}
|
return time.Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SecondsTimeValue converts an int64 pointer to a time.Time value
|
||||||
|
// representing seconds since Epoch or time.Time{} if the pointer is nil.
|
||||||
|
func SecondsTimeValue(v *int64) time.Time {
|
||||||
|
if v != nil {
|
||||||
|
return time.Unix((*v / 1000), 0)
|
||||||
|
}
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MillisecondsTimeValue converts an int64 pointer to a time.Time value
|
||||||
|
// representing milliseconds sinch Epoch or time.Time{} if the pointer is nil.
|
||||||
|
func MillisecondsTimeValue(v *int64) time.Time {
|
||||||
|
if v != nil {
|
||||||
|
return time.Unix(0, (*v * 1000000))
|
||||||
|
}
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeUnixMilli returns a Unix timestamp in milliseconds from "January 1, 1970 UTC".
|
||||||
|
// The result is undefined if the Unix time cannot be represented by an int64.
|
||||||
|
// Which includes calling TimeUnixMilli on a zero Time is undefined.
|
||||||
|
//
|
||||||
|
// This utility is useful for service API's such as CloudWatch Logs which require
|
||||||
|
// their unix time values to be in milliseconds.
|
||||||
|
//
|
||||||
|
// See Go stdlib https://golang.org/pkg/time/#Time.UnixNano for more information.
|
||||||
|
func TimeUnixMilli(t time.Time) int64 {
|
||||||
|
return t.UnixNano() / int64(time.Millisecond/time.Nanosecond)
|
||||||
|
}
|
||||||
|
|
||||||
// TimeSlice converts a slice of time.Time values into a slice of
|
// TimeSlice converts a slice of time.Time values into a slice of
|
||||||
// time.Time pointers
|
// time.Time pointers
|
||||||
func TimeSlice(src []time.Time) []*time.Time {
|
func TimeSlice(src []time.Time) []*time.Time {
|
||||||
|
|
641
vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go
generated
vendored
Normal file
641
vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go
generated
vendored
Normal file
|
@ -0,0 +1,641 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testCasesStringSlice = [][]string{
|
||||||
|
{"a", "b", "c", "d", "e"},
|
||||||
|
{"a", "b", "", "", "e"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesStringSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := StringSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := StringValueSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesStringValueSlice = [][]*string{
|
||||||
|
{String("a"), String("b"), nil, String("c")},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringValueSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesStringValueSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := StringValueSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if in[i] == nil {
|
||||||
|
if out[i] != "" {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := *(in[i]), out[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := StringSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out2 {
|
||||||
|
if in[i] == nil {
|
||||||
|
if *(out2[i]) != "" {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := *in[i], *out2[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesStringMap = []map[string]string{
|
||||||
|
{"a": "1", "b": "2", "c": "3"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringMap(t *testing.T) {
|
||||||
|
for idx, in := range testCasesStringMap {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := StringMap(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := StringValueMap(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesBoolSlice = [][]bool{
|
||||||
|
{true, true, false, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesBoolSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := BoolSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := BoolValueSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesBoolValueSlice = [][]*bool{}
|
||||||
|
|
||||||
|
func TestBoolValueSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesBoolValueSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := BoolValueSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if in[i] == nil {
|
||||||
|
if out[i] {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := *(in[i]), out[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := BoolSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out2 {
|
||||||
|
if in[i] == nil {
|
||||||
|
if *(out2[i]) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := in[i], out2[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesBoolMap = []map[string]bool{
|
||||||
|
{"a": true, "b": false, "c": true},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolMap(t *testing.T) {
|
||||||
|
for idx, in := range testCasesBoolMap {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := BoolMap(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := BoolValueMap(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesIntSlice = [][]int{
|
||||||
|
{1, 2, 3, 4},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesIntSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := IntSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := IntValueSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesIntValueSlice = [][]*int{}
|
||||||
|
|
||||||
|
func TestIntValueSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesIntValueSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := IntValueSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if in[i] == nil {
|
||||||
|
if out[i] != 0 {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := *(in[i]), out[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := IntSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out2 {
|
||||||
|
if in[i] == nil {
|
||||||
|
if *(out2[i]) != 0 {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := in[i], out2[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesIntMap = []map[string]int{
|
||||||
|
{"a": 3, "b": 2, "c": 1},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntMap(t *testing.T) {
|
||||||
|
for idx, in := range testCasesIntMap {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := IntMap(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := IntValueMap(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesInt64Slice = [][]int64{
|
||||||
|
{1, 2, 3, 4},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInt64Slice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesInt64Slice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := Int64Slice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := Int64ValueSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesInt64ValueSlice = [][]*int64{}
|
||||||
|
|
||||||
|
func TestInt64ValueSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesInt64ValueSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := Int64ValueSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if in[i] == nil {
|
||||||
|
if out[i] != 0 {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := *(in[i]), out[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := Int64Slice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out2 {
|
||||||
|
if in[i] == nil {
|
||||||
|
if *(out2[i]) != 0 {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := in[i], out2[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesInt64Map = []map[string]int64{
|
||||||
|
{"a": 3, "b": 2, "c": 1},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInt64Map(t *testing.T) {
|
||||||
|
for idx, in := range testCasesInt64Map {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := Int64Map(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := Int64ValueMap(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesFloat64Slice = [][]float64{
|
||||||
|
{1, 2, 3, 4},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFloat64Slice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesFloat64Slice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := Float64Slice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := Float64ValueSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesFloat64ValueSlice = [][]*float64{}
|
||||||
|
|
||||||
|
func TestFloat64ValueSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesFloat64ValueSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := Float64ValueSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if in[i] == nil {
|
||||||
|
if out[i] != 0 {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := *(in[i]), out[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := Float64Slice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out2 {
|
||||||
|
if in[i] == nil {
|
||||||
|
if *(out2[i]) != 0 {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := in[i], out2[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesFloat64Map = []map[string]float64{
|
||||||
|
{"a": 3, "b": 2, "c": 1},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFloat64Map(t *testing.T) {
|
||||||
|
for idx, in := range testCasesFloat64Map {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := Float64Map(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := Float64ValueMap(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesTimeSlice = [][]time.Time{
|
||||||
|
{time.Now(), time.Now().AddDate(100, 0, 0)},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesTimeSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := TimeSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := TimeValueSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesTimeValueSlice = [][]*time.Time{}
|
||||||
|
|
||||||
|
func TestTimeValueSlice(t *testing.T) {
|
||||||
|
for idx, in := range testCasesTimeValueSlice {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := TimeValueSlice(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if in[i] == nil {
|
||||||
|
if !out[i].IsZero() {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := *(in[i]), out[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := TimeSlice(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out2 {
|
||||||
|
if in[i] == nil {
|
||||||
|
if !(*(out2[i])).IsZero() {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := in[i], out2[i]; e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesTimeMap = []map[string]time.Time{
|
||||||
|
{"a": time.Now().AddDate(-100, 0, 0), "b": time.Now()},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeMap(t *testing.T) {
|
||||||
|
for idx, in := range testCasesTimeMap {
|
||||||
|
if in == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out := TimeMap(in)
|
||||||
|
if e, a := len(out), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
for i := range out {
|
||||||
|
if e, a := in[i], *(out[i]); e != a {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out2 := TimeValueMap(out)
|
||||||
|
if e, a := len(out2), len(in); e != a {
|
||||||
|
t.Errorf("Unexpected len at idx %d", idx)
|
||||||
|
}
|
||||||
|
if e, a := in, out2; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("Unexpected value at idx %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TimeValueTestCase struct {
|
||||||
|
in int64
|
||||||
|
outSecs time.Time
|
||||||
|
outMillis time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCasesTimeValue = []TimeValueTestCase{
|
||||||
|
{
|
||||||
|
in: int64(1501558289000),
|
||||||
|
outSecs: time.Unix(1501558289, 0),
|
||||||
|
outMillis: time.Unix(1501558289, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: int64(1501558289001),
|
||||||
|
outSecs: time.Unix(1501558289, 0),
|
||||||
|
outMillis: time.Unix(1501558289, 1*1000000),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSecondsTimeValue(t *testing.T) {
|
||||||
|
for idx, testCase := range testCasesTimeValue {
|
||||||
|
out := SecondsTimeValue(&testCase.in)
|
||||||
|
if e, a := testCase.outSecs, out; e != a {
|
||||||
|
t.Errorf("Unexpected value for time value at %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMillisecondsTimeValue(t *testing.T) {
|
||||||
|
for idx, testCase := range testCasesTimeValue {
|
||||||
|
out := MillisecondsTimeValue(&testCase.in)
|
||||||
|
if e, a := testCase.outMillis, out; e != a {
|
||||||
|
t.Errorf("Unexpected value for time value at %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
230
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
generated
vendored
230
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
generated
vendored
|
@ -8,10 +8,13 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,79 +23,173 @@ type lener interface {
|
||||||
Len() int
|
Len() int
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildContentLength builds the content length of a request based on the body,
|
// BuildContentLengthHandler builds the content length of a request based on the body,
|
||||||
// or will use the HTTPRequest.Header's "Content-Length" if defined. If unable
|
// 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.
|
// 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 != "" {
|
// The Content-Length will only be added to the request if the length of the body
|
||||||
length, _ := strconv.ParseInt(slength, 10, 64)
|
// is greater than 0. If the body is empty or the current `Content-Length`
|
||||||
r.HTTPRequest.ContentLength = length
|
// header is <= 0, the header will also be stripped.
|
||||||
return
|
var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLengthHandler", Fn: func(r *request.Request) {
|
||||||
}
|
|
||||||
|
|
||||||
var length int64
|
var length int64
|
||||||
switch body := r.Body.(type) {
|
|
||||||
case nil:
|
if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
|
||||||
length = 0
|
length, _ = strconv.ParseInt(slength, 10, 64)
|
||||||
case lener:
|
} else {
|
||||||
length = int64(body.Len())
|
switch body := r.Body.(type) {
|
||||||
case io.Seeker:
|
case nil:
|
||||||
r.BodyStart, _ = body.Seek(0, 1)
|
length = 0
|
||||||
end, _ := body.Seek(0, 2)
|
case lener:
|
||||||
body.Seek(r.BodyStart, 0) // make sure to seek back to original location
|
length = int64(body.Len())
|
||||||
length = end - r.BodyStart
|
case io.Seeker:
|
||||||
default:
|
r.BodyStart, _ = body.Seek(0, 1)
|
||||||
panic("Cannot get length of body, must provide `ContentLength`")
|
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
|
if length > 0 {
|
||||||
r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
|
r.HTTPRequest.ContentLength = length
|
||||||
|
r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
|
||||||
|
} else {
|
||||||
|
r.HTTPRequest.ContentLength = 0
|
||||||
|
r.HTTPRequest.Header.Del("Content-Length")
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// UserAgentHandler is a request handler for injecting User agent into requests.
|
// SDKVersionUserAgentHandler is a request handler for adding the SDK Version to the user agent.
|
||||||
var UserAgentHandler = request.NamedHandler{"core.UserAgentHandler", func(r *request.Request) {
|
var SDKVersionUserAgentHandler = request.NamedHandler{
|
||||||
r.HTTPRequest.Header.Set("User-Agent", aws.SDKName+"/"+aws.SDKVersion)
|
Name: "core.SDKVersionUserAgentHandler",
|
||||||
}}
|
Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion,
|
||||||
|
runtime.Version(), runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
|
||||||
var reStatusCode = regexp.MustCompile(`^(\d{3})`)
|
var reStatusCode = regexp.MustCompile(`^(\d{3})`)
|
||||||
|
|
||||||
// SendHandler is a request handler to send service request using HTTP client.
|
// ValidateReqSigHandler is a request handler to ensure that the request's
|
||||||
var SendHandler = request.NamedHandler{"core.SendHandler", func(r *request.Request) {
|
// signature doesn't expire before it is sent. This can happen when a request
|
||||||
var err error
|
// is built and signed significantly before it is sent. Or significant delays
|
||||||
r.HTTPResponse, err = r.Service.Config.HTTPClient.Do(r.HTTPRequest)
|
// occur when retrying requests that would cause the signature to expire.
|
||||||
if err != nil {
|
var ValidateReqSigHandler = request.NamedHandler{
|
||||||
// Capture the case where url.Error is returned for error processing
|
Name: "core.ValidateReqSigHandler",
|
||||||
// response. e.g. 301 without location header comes back as string
|
Fn: func(r *request.Request) {
|
||||||
// error and r.HTTPResponse is nil. Other url redirect errors will
|
// Unsigned requests are not signed
|
||||||
// comeback in a similar method.
|
if r.Config.Credentials == credentials.AnonymousCredentials {
|
||||||
if e, ok := err.(*url.Error); ok && e.Err != nil {
|
return
|
||||||
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
|
signedTime := r.Time
|
||||||
// value is consistent.
|
if !r.LastSignedAt.IsZero() {
|
||||||
|
signedTime = r.LastSignedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10 minutes to allow for some clock skew/delays in transmission.
|
||||||
|
// Would be improved with aws/aws-sdk-go#423
|
||||||
|
if signedTime.Add(10 * time.Minute).After(time.Now()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("request expired, resigning")
|
||||||
|
r.Sign()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendHandler is a request handler to send service request using HTTP client.
|
||||||
|
var SendHandler = request.NamedHandler{
|
||||||
|
Name: "core.SendHandler",
|
||||||
|
Fn: func(r *request.Request) {
|
||||||
|
sender := sendFollowRedirects
|
||||||
|
if r.DisableFollowRedirects {
|
||||||
|
sender = sendWithoutFollowRedirects
|
||||||
|
}
|
||||||
|
|
||||||
|
if request.NoBody == r.HTTPRequest.Body {
|
||||||
|
// Strip off the request body if the NoBody reader was used as a
|
||||||
|
// place holder for a request body. This prevents the SDK from
|
||||||
|
// making requests with a request body when it would be invalid
|
||||||
|
// to do so.
|
||||||
|
//
|
||||||
|
// Use a shallow copy of the http.Request to ensure the race condition
|
||||||
|
// of transport on Body will not trigger
|
||||||
|
reqOrig, reqCopy := r.HTTPRequest, *r.HTTPRequest
|
||||||
|
reqCopy.Body = nil
|
||||||
|
r.HTTPRequest = &reqCopy
|
||||||
|
defer func() {
|
||||||
|
r.HTTPRequest = reqOrig
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
r.HTTPResponse, err = sender(r)
|
||||||
|
if err != nil {
|
||||||
|
handleSendError(r, err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendFollowRedirects(r *request.Request) (*http.Response, error) {
|
||||||
|
return r.Config.HTTPClient.Do(r.HTTPRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendWithoutFollowRedirects(r *request.Request) (*http.Response, error) {
|
||||||
|
transport := r.Config.HTTPClient.Transport
|
||||||
|
if transport == nil {
|
||||||
|
transport = http.DefaultTransport
|
||||||
|
}
|
||||||
|
|
||||||
|
return transport.RoundTrip(r.HTTPRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSendError(r *request.Request, err error) {
|
||||||
|
// Prevent leaking if an HTTPResponse was returned. Clean up
|
||||||
|
// the body.
|
||||||
|
if r.HTTPResponse != nil {
|
||||||
|
r.HTTPResponse.Body.Close()
|
||||||
|
}
|
||||||
|
// 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{
|
r.HTTPResponse = &http.Response{
|
||||||
StatusCode: int(0),
|
StatusCode: int(code),
|
||||||
Status: http.StatusText(int(0)),
|
Status: http.StatusText(int(code)),
|
||||||
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// Catch all other request errors.
|
|
||||||
r.Error = awserr.New("RequestError", "send request failed", err)
|
|
||||||
r.Retryable = aws.Bool(true) // network errors are retryable
|
|
||||||
}
|
}
|
||||||
}}
|
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
|
||||||
|
|
||||||
|
// Override the error with a context canceled error, if that was canceled.
|
||||||
|
ctx := r.Context()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
r.Error = awserr.New(request.CanceledErrorCode,
|
||||||
|
"request context canceled", ctx.Err())
|
||||||
|
r.Retryable = aws.Bool(false)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateResponseHandler is a request handler to validate service response.
|
// ValidateResponseHandler is a request handler to validate service response.
|
||||||
var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler", func(r *request.Request) {
|
var ValidateResponseHandler = request.NamedHandler{Name: "core.ValidateResponseHandler", Fn: func(r *request.Request) {
|
||||||
if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 {
|
if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 {
|
||||||
// this may be replaced by an UnmarshalError handler
|
// this may be replaced by an UnmarshalError handler
|
||||||
r.Error = awserr.New("UnknownError", "unknown error", nil)
|
r.Error = awserr.New("UnknownError", "unknown error", nil)
|
||||||
|
@ -101,22 +198,31 @@ var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler
|
||||||
|
|
||||||
// AfterRetryHandler performs final checks to determine if the request should
|
// AfterRetryHandler performs final checks to determine if the request should
|
||||||
// be retried and how long to delay.
|
// be retried and how long to delay.
|
||||||
var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *request.Request) {
|
var AfterRetryHandler = request.NamedHandler{Name: "core.AfterRetryHandler", Fn: func(r *request.Request) {
|
||||||
// If one of the other handlers already set the retry state
|
// If one of the other handlers already set the retry state
|
||||||
// we don't want to override it based on the service's state
|
// we don't want to override it based on the service's state
|
||||||
if r.Retryable == nil {
|
if r.Retryable == nil || aws.BoolValue(r.Config.EnforceShouldRetryCheck) {
|
||||||
r.Retryable = aws.Bool(r.ShouldRetry(r))
|
r.Retryable = aws.Bool(r.ShouldRetry(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.WillRetry() {
|
if r.WillRetry() {
|
||||||
r.RetryDelay = r.RetryRules(r)
|
r.RetryDelay = r.RetryRules(r)
|
||||||
r.Service.Config.SleepDelay(r.RetryDelay)
|
|
||||||
|
if sleepFn := r.Config.SleepDelay; sleepFn != nil {
|
||||||
|
// Support SleepDelay for backwards compatibility and testing
|
||||||
|
sleepFn(r.RetryDelay)
|
||||||
|
} else if err := aws.SleepWithContext(r.Context(), r.RetryDelay); err != nil {
|
||||||
|
r.Error = awserr.New(request.CanceledErrorCode,
|
||||||
|
"request context canceled", err)
|
||||||
|
r.Retryable = aws.Bool(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// when the expired token exception occurs the credentials
|
// when the expired token exception occurs the credentials
|
||||||
// need to be expired locally so that the next request to
|
// need to be expired locally so that the next request to
|
||||||
// get credentials will trigger a credentials refresh.
|
// get credentials will trigger a credentials refresh.
|
||||||
if r.IsErrorExpired() {
|
if r.IsErrorExpired() {
|
||||||
r.Service.Config.Credentials.Expire()
|
r.Config.Credentials.Expire()
|
||||||
}
|
}
|
||||||
|
|
||||||
r.RetryCount++
|
r.RetryCount++
|
||||||
|
@ -127,10 +233,10 @@ var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *r
|
||||||
// ValidateEndpointHandler is a request handler to validate a request had the
|
// ValidateEndpointHandler is a request handler to validate a request had the
|
||||||
// appropriate Region and Endpoint set. Will set r.Error if the endpoint or
|
// appropriate Region and Endpoint set. Will set r.Error if the endpoint or
|
||||||
// region is not valid.
|
// region is not valid.
|
||||||
var ValidateEndpointHandler = request.NamedHandler{"core.ValidateEndpointHandler", func(r *request.Request) {
|
var ValidateEndpointHandler = request.NamedHandler{Name: "core.ValidateEndpointHandler", Fn: func(r *request.Request) {
|
||||||
if r.Service.SigningRegion == "" && aws.StringValue(r.Service.Config.Region) == "" {
|
if r.ClientInfo.SigningRegion == "" && aws.StringValue(r.Config.Region) == "" {
|
||||||
r.Error = aws.ErrMissingRegion
|
r.Error = aws.ErrMissingRegion
|
||||||
} else if r.Service.Endpoint == "" {
|
} else if r.ClientInfo.Endpoint == "" {
|
||||||
r.Error = aws.ErrMissingEndpoint
|
r.Error = aws.ErrMissingEndpoint
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
64
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_1_8_test.go
generated
vendored
Normal file
64
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_1_8_test.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
package corehandlers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"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/aws/session"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSendHandler_HEADNoBody(t *testing.T) {
|
||||||
|
TLSBundleCertFile, TLSBundleKeyFile, TLSBundleCAFile, err := awstesting.CreateTLSBundleFiles()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer awstesting.CleanupTLSBundleFiles(TLSBundleCertFile, TLSBundleKeyFile, TLSBundleCAFile)
|
||||||
|
|
||||||
|
endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
transport := http.DefaultTransport.(*http.Transport)
|
||||||
|
// test server's certificate is self-signed certificate
|
||||||
|
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
|
http2.ConfigureTransport(transport)
|
||||||
|
|
||||||
|
sess, err := session.NewSessionWithOptions(session.Options{
|
||||||
|
Config: aws.Config{
|
||||||
|
HTTPClient: &http.Client{},
|
||||||
|
Endpoint: aws.String(endpoint),
|
||||||
|
Region: aws.String("mock-region"),
|
||||||
|
Credentials: credentials.AnonymousCredentials,
|
||||||
|
S3ForcePathStyle: aws.Bool(true),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
svc := s3.New(sess)
|
||||||
|
|
||||||
|
req, _ := svc.HeadObjectRequest(&s3.HeadObjectInput{
|
||||||
|
Bucket: aws.String("bucketname"),
|
||||||
|
Key: aws.String("keyname"),
|
||||||
|
})
|
||||||
|
|
||||||
|
if e, a := request.NoBody, req.HTTPRequest.Body; e != a {
|
||||||
|
t.Fatalf("expect %T request body, got %T", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = req.Send()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if e, a := http.StatusOK, req.HTTPResponse.StatusCode; e != a {
|
||||||
|
t.Errorf("expect %d status code, got %d", e, a)
|
||||||
|
}
|
||||||
|
}
|
398
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go
generated
vendored
Normal file
398
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go
generated
vendored
Normal file
|
@ -0,0 +1,398 @@
|
||||||
|
package corehandlers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateEndpointHandler(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
|
||||||
|
svc := awstesting.NewClient(aws.NewConfig().WithRegion("us-west-2"))
|
||||||
|
svc.Handlers.Clear()
|
||||||
|
svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
|
||||||
|
|
||||||
|
req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||||
|
err := req.Build()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateEndpointHandlerErrorRegion(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
|
||||||
|
svc := awstesting.NewClient()
|
||||||
|
svc.Handlers.Clear()
|
||||||
|
svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
|
||||||
|
|
||||||
|
req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||||
|
err := req.Build()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expect error, got none")
|
||||||
|
}
|
||||||
|
if e, a := aws.ErrMissingRegion, err; e != a {
|
||||||
|
t.Errorf("expect %v to be %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockCredsProvider struct {
|
||||||
|
expired bool
|
||||||
|
retrieveCalled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockCredsProvider) Retrieve() (credentials.Value, error) {
|
||||||
|
m.retrieveCalled = true
|
||||||
|
return credentials.Value{ProviderName: "mockCredsProvider"}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockCredsProvider) IsExpired() bool {
|
||||||
|
return m.expired
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterRetryRefreshCreds(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
credProvider := &mockCredsProvider{}
|
||||||
|
|
||||||
|
svc := awstesting.NewClient(&aws.Config{
|
||||||
|
Credentials: credentials.NewCredentials(credProvider),
|
||||||
|
MaxRetries: aws.Int(1),
|
||||||
|
})
|
||||||
|
|
||||||
|
svc.Handlers.Clear()
|
||||||
|
svc.Handlers.ValidateResponse.PushBack(func(r *request.Request) {
|
||||||
|
r.Error = awserr.New("UnknownError", "", nil)
|
||||||
|
r.HTTPResponse = &http.Response{StatusCode: 400, Body: ioutil.NopCloser(bytes.NewBuffer([]byte{}))}
|
||||||
|
})
|
||||||
|
svc.Handlers.UnmarshalError.PushBack(func(r *request.Request) {
|
||||||
|
r.Error = awserr.New("ExpiredTokenException", "", nil)
|
||||||
|
})
|
||||||
|
svc.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
|
||||||
|
|
||||||
|
if !svc.Config.Credentials.IsExpired() {
|
||||||
|
t.Errorf("Expect to start out expired")
|
||||||
|
}
|
||||||
|
if credProvider.retrieveCalled {
|
||||||
|
t.Errorf("expect not called")
|
||||||
|
}
|
||||||
|
|
||||||
|
req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||||
|
req.Send()
|
||||||
|
|
||||||
|
if !svc.Config.Credentials.IsExpired() {
|
||||||
|
t.Errorf("Expect to start out expired")
|
||||||
|
}
|
||||||
|
if credProvider.retrieveCalled {
|
||||||
|
t.Errorf("expect not called")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := svc.Config.Credentials.Get()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if !credProvider.retrieveCalled {
|
||||||
|
t.Errorf("expect not called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterRetryWithContextCanceled(t *testing.T) {
|
||||||
|
c := awstesting.NewClient()
|
||||||
|
|
||||||
|
req := c.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||||
|
|
||||||
|
ctx := &awstesting.FakeContext{DoneCh: make(chan struct{}, 0)}
|
||||||
|
req.SetContext(ctx)
|
||||||
|
|
||||||
|
req.Error = fmt.Errorf("some error")
|
||||||
|
req.Retryable = aws.Bool(true)
|
||||||
|
req.HTTPResponse = &http.Response{
|
||||||
|
StatusCode: 500,
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ctx.DoneCh)
|
||||||
|
ctx.Error = fmt.Errorf("context canceled")
|
||||||
|
|
||||||
|
corehandlers.AfterRetryHandler.Fn(req)
|
||||||
|
|
||||||
|
if req.Error == nil {
|
||||||
|
t.Fatalf("expect error but didn't receive one")
|
||||||
|
}
|
||||||
|
|
||||||
|
aerr := req.Error.(awserr.Error)
|
||||||
|
|
||||||
|
if e, a := request.CanceledErrorCode, aerr.Code(); e != a {
|
||||||
|
t.Errorf("expect %q, error code got %q", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterRetryWithContext(t *testing.T) {
|
||||||
|
c := awstesting.NewClient()
|
||||||
|
|
||||||
|
req := c.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||||
|
|
||||||
|
ctx := &awstesting.FakeContext{DoneCh: make(chan struct{}, 0)}
|
||||||
|
req.SetContext(ctx)
|
||||||
|
|
||||||
|
req.Error = fmt.Errorf("some error")
|
||||||
|
req.Retryable = aws.Bool(true)
|
||||||
|
req.HTTPResponse = &http.Response{
|
||||||
|
StatusCode: 500,
|
||||||
|
}
|
||||||
|
|
||||||
|
corehandlers.AfterRetryHandler.Fn(req)
|
||||||
|
|
||||||
|
if req.Error != nil {
|
||||||
|
t.Fatalf("expect no error, got %v", req.Error)
|
||||||
|
}
|
||||||
|
if e, a := 1, req.RetryCount; e != a {
|
||||||
|
t.Errorf("expect retry count to be %d, got %d", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendWithContextCanceled(t *testing.T) {
|
||||||
|
c := awstesting.NewClient(&aws.Config{
|
||||||
|
SleepDelay: func(dur time.Duration) {
|
||||||
|
t.Errorf("SleepDelay should not be called")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
req := c.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||||
|
|
||||||
|
ctx := &awstesting.FakeContext{DoneCh: make(chan struct{}, 0)}
|
||||||
|
req.SetContext(ctx)
|
||||||
|
|
||||||
|
req.Error = fmt.Errorf("some error")
|
||||||
|
req.Retryable = aws.Bool(true)
|
||||||
|
req.HTTPResponse = &http.Response{
|
||||||
|
StatusCode: 500,
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ctx.DoneCh)
|
||||||
|
ctx.Error = fmt.Errorf("context canceled")
|
||||||
|
|
||||||
|
corehandlers.SendHandler.Fn(req)
|
||||||
|
|
||||||
|
if req.Error == nil {
|
||||||
|
t.Fatalf("expect error but didn't receive one")
|
||||||
|
}
|
||||||
|
|
||||||
|
aerr := req.Error.(awserr.Error)
|
||||||
|
|
||||||
|
if e, a := request.CanceledErrorCode, aerr.Code(); e != a {
|
||||||
|
t.Errorf("expect %q, error code got %q", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testSendHandlerTransport struct{}
|
||||||
|
|
||||||
|
func (t *testSendHandlerTransport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||||
|
return nil, fmt.Errorf("mock error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendHandlerError(t *testing.T) {
|
||||||
|
svc := awstesting.NewClient(&aws.Config{
|
||||||
|
HTTPClient: &http.Client{
|
||||||
|
Transport: &testSendHandlerTransport{},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
svc.Handlers.Clear()
|
||||||
|
svc.Handlers.Send.PushBackNamed(corehandlers.SendHandler)
|
||||||
|
r := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil)
|
||||||
|
|
||||||
|
r.Send()
|
||||||
|
|
||||||
|
if r.Error == nil {
|
||||||
|
t.Errorf("expect error, got none")
|
||||||
|
}
|
||||||
|
if r.HTTPResponse == nil {
|
||||||
|
t.Errorf("expect response, got none")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendWithoutFollowRedirects(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case "/original":
|
||||||
|
w.Header().Set("Location", "/redirected")
|
||||||
|
w.WriteHeader(301)
|
||||||
|
case "/redirected":
|
||||||
|
t.Fatalf("expect not to redirect, but was")
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
svc := awstesting.NewClient(&aws.Config{
|
||||||
|
DisableSSL: aws.Bool(true),
|
||||||
|
Endpoint: aws.String(server.URL),
|
||||||
|
})
|
||||||
|
svc.Handlers.Clear()
|
||||||
|
svc.Handlers.Send.PushBackNamed(corehandlers.SendHandler)
|
||||||
|
|
||||||
|
r := svc.NewRequest(&request.Operation{
|
||||||
|
Name: "Operation",
|
||||||
|
HTTPPath: "/original",
|
||||||
|
}, nil, nil)
|
||||||
|
r.DisableFollowRedirects = true
|
||||||
|
|
||||||
|
err := r.Send()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if e, a := 301, r.HTTPResponse.StatusCode; e != a {
|
||||||
|
t.Errorf("expect %d status code, got %d", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateReqSigHandler(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Req *request.Request
|
||||||
|
Resign bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Req: &request.Request{
|
||||||
|
Config: aws.Config{Credentials: credentials.AnonymousCredentials},
|
||||||
|
Time: time.Now().Add(-15 * time.Minute),
|
||||||
|
},
|
||||||
|
Resign: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Req: &request.Request{
|
||||||
|
Time: time.Now().Add(-15 * time.Minute),
|
||||||
|
},
|
||||||
|
Resign: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Req: &request.Request{
|
||||||
|
Time: time.Now().Add(-1 * time.Minute),
|
||||||
|
},
|
||||||
|
Resign: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
resigned := false
|
||||||
|
c.Req.Handlers.Sign.PushBack(func(r *request.Request) {
|
||||||
|
resigned = true
|
||||||
|
})
|
||||||
|
|
||||||
|
corehandlers.ValidateReqSigHandler.Fn(c.Req)
|
||||||
|
|
||||||
|
if c.Req.Error != nil {
|
||||||
|
t.Errorf("expect no error, got %v", c.Req.Error)
|
||||||
|
}
|
||||||
|
if e, a := c.Resign, resigned; e != a {
|
||||||
|
t.Errorf("%d, expect %v to be %v", i, e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupContentLengthTestServer(t *testing.T, hasContentLength bool, contentLength int64) *httptest.Server {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_, ok := r.Header["Content-Length"]
|
||||||
|
if e, a := hasContentLength, ok; e != a {
|
||||||
|
t.Errorf("expect %v to be %v", e, a)
|
||||||
|
}
|
||||||
|
if hasContentLength {
|
||||||
|
if e, a := contentLength, r.ContentLength; e != a {
|
||||||
|
t.Errorf("expect %v to be %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
r.Body.Close()
|
||||||
|
|
||||||
|
authHeader := r.Header.Get("Authorization")
|
||||||
|
if hasContentLength {
|
||||||
|
if e, a := "content-length", authHeader; !strings.Contains(a, e) {
|
||||||
|
t.Errorf("expect %v to be in %v", e, a)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e, a := "content-length", authHeader; strings.Contains(a, e) {
|
||||||
|
t.Errorf("expect %v to not be in %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, a := contentLength, int64(len(b)); e != a {
|
||||||
|
t.Errorf("expect %v to be %v", e, a)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildContentLength_ZeroBody(t *testing.T) {
|
||||||
|
server := setupContentLengthTestServer(t, false, 0)
|
||||||
|
|
||||||
|
svc := s3.New(unit.Session, &aws.Config{
|
||||||
|
Endpoint: aws.String(server.URL),
|
||||||
|
S3ForcePathStyle: aws.Bool(true),
|
||||||
|
DisableSSL: aws.Bool(true),
|
||||||
|
})
|
||||||
|
_, err := svc.GetObject(&s3.GetObjectInput{
|
||||||
|
Bucket: aws.String("bucketname"),
|
||||||
|
Key: aws.String("keyname"),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildContentLength_NegativeBody(t *testing.T) {
|
||||||
|
server := setupContentLengthTestServer(t, false, 0)
|
||||||
|
|
||||||
|
svc := s3.New(unit.Session, &aws.Config{
|
||||||
|
Endpoint: aws.String(server.URL),
|
||||||
|
S3ForcePathStyle: aws.Bool(true),
|
||||||
|
DisableSSL: aws.Bool(true),
|
||||||
|
})
|
||||||
|
req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
|
||||||
|
Bucket: aws.String("bucketname"),
|
||||||
|
Key: aws.String("keyname"),
|
||||||
|
})
|
||||||
|
|
||||||
|
req.HTTPRequest.Header.Set("Content-Length", "-1")
|
||||||
|
|
||||||
|
if req.Error != nil {
|
||||||
|
t.Errorf("expect no error, got %v", req.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildContentLength_WithBody(t *testing.T) {
|
||||||
|
server := setupContentLengthTestServer(t, true, 1024)
|
||||||
|
|
||||||
|
svc := s3.New(unit.Session, &aws.Config{
|
||||||
|
Endpoint: aws.String(server.URL),
|
||||||
|
S3ForcePathStyle: aws.Bool(true),
|
||||||
|
DisableSSL: aws.Bool(true),
|
||||||
|
})
|
||||||
|
_, err := svc.PutObject(&s3.PutObjectInput{
|
||||||
|
Bucket: aws.String("bucketname"),
|
||||||
|
Key: aws.String("keyname"),
|
||||||
|
Body: bytes.NewReader(make([]byte, 1024)),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
143
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
generated
vendored
143
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
generated
vendored
|
@ -1,144 +1,17 @@
|
||||||
package corehandlers
|
package corehandlers
|
||||||
|
|
||||||
import (
|
import "github.com/aws/aws-sdk-go/aws/request"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
// ValidateParametersHandler is a request handler to validate the input parameters.
|
||||||
"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.
|
// Validating parameters only has meaning if done prior to the request being sent.
|
||||||
var ValidateParametersHandler = request.NamedHandler{"core.ValidateParametersHandler", func(r *request.Request) {
|
var ValidateParametersHandler = request.NamedHandler{Name: "core.ValidateParametersHandler", Fn: func(r *request.Request) {
|
||||||
if r.ParamsFilled() {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch value.Kind() {
|
if v, ok := r.Params.(request.Validator); ok {
|
||||||
case reflect.Struct:
|
if err := v.Validate(); err != nil {
|
||||||
v.validateStruct(value, path)
|
r.Error = err
|
||||||
case reflect.Slice:
|
|
||||||
for i := 0; i < value.Len(); i++ {
|
|
||||||
v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i))
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
for _, n := range value.MapKeys() {
|
|
||||||
v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
|
|
||||||
// validateStruct will validate the struct value's fields. If the structure has
|
|
||||||
// nested types those types will be validated also.
|
|
||||||
func (v *validator) validateStruct(value reflect.Value, path string) {
|
|
||||||
prefix := "."
|
|
||||||
if path == "" {
|
|
||||||
prefix = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < value.Type().NumField(); i++ {
|
|
||||||
f := value.Type().Field(i)
|
|
||||||
if strings.ToLower(f.Name[0:1]) == f.Name[0:1] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fvalue := value.FieldByName(f.Name)
|
|
||||||
|
|
||||||
err := validateField(f, fvalue, validateFieldRequired, validateFieldMin)
|
|
||||||
if err != nil {
|
|
||||||
v.errors = append(v.errors, fmt.Sprintf("%s: %s", err.Error(), path+prefix+f.Name))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
v.validateAny(fvalue, path+prefix+f.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type validatorFunc func(f reflect.StructField, fvalue reflect.Value) error
|
|
||||||
|
|
||||||
func validateField(f reflect.StructField, fvalue reflect.Value, funcs ...validatorFunc) error {
|
|
||||||
for _, fn := range funcs {
|
|
||||||
if err := fn(f, fvalue); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validates that a field has a valid value provided for required fields.
|
|
||||||
func validateFieldRequired(f reflect.StructField, fvalue reflect.Value) error {
|
|
||||||
if f.Tag.Get("required") == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch fvalue.Kind() {
|
|
||||||
case reflect.Ptr, reflect.Slice, reflect.Map:
|
|
||||||
if fvalue.IsNil() {
|
|
||||||
return fmt.Errorf("missing required parameter")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if !fvalue.IsValid() {
|
|
||||||
return fmt.Errorf("missing required parameter")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validates that if a value is provided for a field, that value must be at
|
|
||||||
// least a minimum length.
|
|
||||||
func validateFieldMin(f reflect.StructField, fvalue reflect.Value) error {
|
|
||||||
minStr := f.Tag.Get("min")
|
|
||||||
if minStr == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
min, _ := strconv.ParseInt(minStr, 10, 64)
|
|
||||||
|
|
||||||
kind := fvalue.Kind()
|
|
||||||
if kind == reflect.Ptr {
|
|
||||||
if fvalue.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
fvalue = fvalue.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch fvalue.Kind() {
|
|
||||||
case reflect.String:
|
|
||||||
if int64(fvalue.Len()) < min {
|
|
||||||
return fmt.Errorf("field too short, minimum length %d", min)
|
|
||||||
}
|
|
||||||
case reflect.Slice, reflect.Map:
|
|
||||||
if fvalue.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if int64(fvalue.Len()) < min {
|
|
||||||
return fmt.Errorf("field too short, minimum length %d", min)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO min can also apply to number minimum value.
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
286
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go
generated
vendored
Normal file
286
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go
generated
vendored
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
package corehandlers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||||
|
"github.com/aws/aws-sdk-go/service/kinesis"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testSvc = func() *client.Client {
|
||||||
|
s := &client.Client{
|
||||||
|
Config: aws.Config{},
|
||||||
|
ClientInfo: metadata.ClientInfo{
|
||||||
|
ServiceName: "mock-service",
|
||||||
|
APIVersion: "2015-01-01",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}()
|
||||||
|
|
||||||
|
type StructShape struct {
|
||||||
|
_ struct{} `type:"structure"`
|
||||||
|
|
||||||
|
RequiredList []*ConditionalStructShape `required:"true"`
|
||||||
|
RequiredMap map[string]*ConditionalStructShape `required:"true"`
|
||||||
|
RequiredBool *bool `required:"true"`
|
||||||
|
OptionalStruct *ConditionalStructShape
|
||||||
|
|
||||||
|
hiddenParameter *string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StructShape) Validate() error {
|
||||||
|
invalidParams := request.ErrInvalidParams{Context: "StructShape"}
|
||||||
|
if s.RequiredList == nil {
|
||||||
|
invalidParams.Add(request.NewErrParamRequired("RequiredList"))
|
||||||
|
}
|
||||||
|
if s.RequiredMap == nil {
|
||||||
|
invalidParams.Add(request.NewErrParamRequired("RequiredMap"))
|
||||||
|
}
|
||||||
|
if s.RequiredBool == nil {
|
||||||
|
invalidParams.Add(request.NewErrParamRequired("RequiredBool"))
|
||||||
|
}
|
||||||
|
if s.RequiredList != nil {
|
||||||
|
for i, v := range s.RequiredList {
|
||||||
|
if v == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := v.Validate(); err != nil {
|
||||||
|
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "RequiredList", i), err.(request.ErrInvalidParams))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.RequiredMap != nil {
|
||||||
|
for i, v := range s.RequiredMap {
|
||||||
|
if v == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := v.Validate(); err != nil {
|
||||||
|
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "RequiredMap", i), err.(request.ErrInvalidParams))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.OptionalStruct != nil {
|
||||||
|
if err := s.OptionalStruct.Validate(); err != nil {
|
||||||
|
invalidParams.AddNested("OptionalStruct", err.(request.ErrInvalidParams))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if invalidParams.Len() > 0 {
|
||||||
|
return invalidParams
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConditionalStructShape struct {
|
||||||
|
_ struct{} `type:"structure"`
|
||||||
|
|
||||||
|
Name *string `required:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConditionalStructShape) Validate() error {
|
||||||
|
invalidParams := request.ErrInvalidParams{Context: "ConditionalStructShape"}
|
||||||
|
if s.Name == nil {
|
||||||
|
invalidParams.Add(request.NewErrParamRequired("Name"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if invalidParams.Len() > 0 {
|
||||||
|
return invalidParams
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoErrors(t *testing.T) {
|
||||||
|
input := &StructShape{
|
||||||
|
RequiredList: []*ConditionalStructShape{},
|
||||||
|
RequiredMap: map[string]*ConditionalStructShape{
|
||||||
|
"key1": {Name: aws.String("Name")},
|
||||||
|
"key2": {Name: aws.String("Name")},
|
||||||
|
},
|
||||||
|
RequiredBool: aws.Bool(true),
|
||||||
|
OptionalStruct: &ConditionalStructShape{Name: aws.String("Name")},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := testSvc.NewRequest(&request.Operation{}, input, nil)
|
||||||
|
corehandlers.ValidateParametersHandler.Fn(req)
|
||||||
|
if req.Error != nil {
|
||||||
|
t.Fatalf("expect no error, got %v", req.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMissingRequiredParameters(t *testing.T) {
|
||||||
|
input := &StructShape{}
|
||||||
|
req := testSvc.NewRequest(&request.Operation{}, input, nil)
|
||||||
|
corehandlers.ValidateParametersHandler.Fn(req)
|
||||||
|
|
||||||
|
if req.Error == nil {
|
||||||
|
t.Fatalf("expect error")
|
||||||
|
}
|
||||||
|
if e, a := "InvalidParameter", req.Error.(awserr.Error).Code(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "3 validation error(s) found.", req.Error.(awserr.Error).Message(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
errs := req.Error.(awserr.BatchedErrors).OrigErrs()
|
||||||
|
if e, a := 3, len(errs); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "ParamRequiredError: missing required field, StructShape.RequiredList.", errs[0].Error(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "ParamRequiredError: missing required field, StructShape.RequiredMap.", errs[1].Error(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "ParamRequiredError: missing required field, StructShape.RequiredBool.", errs[2].Error(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, a := "InvalidParameter: 3 validation error(s) found.\n- missing required field, StructShape.RequiredList.\n- missing required field, StructShape.RequiredMap.\n- missing required field, StructShape.RequiredBool.\n", req.Error.Error(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNestedMissingRequiredParameters(t *testing.T) {
|
||||||
|
input := &StructShape{
|
||||||
|
RequiredList: []*ConditionalStructShape{{}},
|
||||||
|
RequiredMap: map[string]*ConditionalStructShape{
|
||||||
|
"key1": {Name: aws.String("Name")},
|
||||||
|
"key2": {},
|
||||||
|
},
|
||||||
|
RequiredBool: aws.Bool(true),
|
||||||
|
OptionalStruct: &ConditionalStructShape{},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := testSvc.NewRequest(&request.Operation{}, input, nil)
|
||||||
|
corehandlers.ValidateParametersHandler.Fn(req)
|
||||||
|
|
||||||
|
if req.Error == nil {
|
||||||
|
t.Fatalf("expect error")
|
||||||
|
}
|
||||||
|
if e, a := "InvalidParameter", req.Error.(awserr.Error).Code(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "3 validation error(s) found.", req.Error.(awserr.Error).Message(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
errs := req.Error.(awserr.BatchedErrors).OrigErrs()
|
||||||
|
if e, a := 3, len(errs); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "ParamRequiredError: missing required field, StructShape.RequiredList[0].Name.", errs[0].Error(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "ParamRequiredError: missing required field, StructShape.RequiredMap[key2].Name.", errs[1].Error(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "ParamRequiredError: missing required field, StructShape.OptionalStruct.Name.", errs[2].Error(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testInput struct {
|
||||||
|
StringField *string `min:"5"`
|
||||||
|
ListField []string `min:"3"`
|
||||||
|
MapField map[string]string `min:"4"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s testInput) Validate() error {
|
||||||
|
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||||
|
if s.StringField != nil && len(*s.StringField) < 5 {
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||||
|
}
|
||||||
|
if s.ListField != nil && len(s.ListField) < 3 {
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("ListField", 3))
|
||||||
|
}
|
||||||
|
if s.MapField != nil && len(s.MapField) < 4 {
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("MapField", 4))
|
||||||
|
}
|
||||||
|
|
||||||
|
if invalidParams.Len() > 0 {
|
||||||
|
return invalidParams
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var testsFieldMin = []struct {
|
||||||
|
err awserr.Error
|
||||||
|
in testInput
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
err: func() awserr.Error {
|
||||||
|
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||||
|
return invalidParams
|
||||||
|
}(),
|
||||||
|
in: testInput{StringField: aws.String("abcd")},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
err: func() awserr.Error {
|
||||||
|
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("ListField", 3))
|
||||||
|
return invalidParams
|
||||||
|
}(),
|
||||||
|
in: testInput{StringField: aws.String("abcd"), ListField: []string{"a", "b"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
err: func() awserr.Error {
|
||||||
|
invalidParams := request.ErrInvalidParams{Context: "testInput"}
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("StringField", 5))
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("ListField", 3))
|
||||||
|
invalidParams.Add(request.NewErrParamMinLen("MapField", 4))
|
||||||
|
return invalidParams
|
||||||
|
}(),
|
||||||
|
in: testInput{StringField: aws.String("abcd"), ListField: []string{"a", "b"}, MapField: map[string]string{"a": "a", "b": "b"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
err: nil,
|
||||||
|
in: testInput{StringField: aws.String("abcde"),
|
||||||
|
ListField: []string{"a", "b", "c"}, MapField: map[string]string{"a": "a", "b": "b", "c": "c", "d": "d"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateFieldMinParameter(t *testing.T) {
|
||||||
|
for i, c := range testsFieldMin {
|
||||||
|
req := testSvc.NewRequest(&request.Operation{}, &c.in, nil)
|
||||||
|
corehandlers.ValidateParametersHandler.Fn(req)
|
||||||
|
|
||||||
|
if e, a := c.err, req.Error; !reflect.DeepEqual(e,a) {
|
||||||
|
t.Errorf("%d, expect %v, got %v", i, e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkValidateAny(b *testing.B) {
|
||||||
|
input := &kinesis.PutRecordsInput{
|
||||||
|
StreamName: aws.String("stream"),
|
||||||
|
}
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
record := &kinesis.PutRecordsRequestEntry{
|
||||||
|
Data: make([]byte, 10000),
|
||||||
|
PartitionKey: aws.String("partition"),
|
||||||
|
}
|
||||||
|
input.Records = append(input.Records, record)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, _ := kinesis.New(unit.Session).PutRecordsRequest(input)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
corehandlers.ValidateParametersHandler.Fn(req)
|
||||||
|
if err := req.Error; err != nil {
|
||||||
|
b.Fatalf("validation failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
43
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
|
@ -8,8 +8,14 @@ var (
|
||||||
// ErrNoValidProvidersFoundInChain Is returned when there are no valid
|
// ErrNoValidProvidersFoundInChain Is returned when there are no valid
|
||||||
// providers in the ChainProvider.
|
// providers in the ChainProvider.
|
||||||
//
|
//
|
||||||
|
// This has been deprecated. For verbose error messaging set
|
||||||
|
// aws.Config.CredentialsChainVerboseErrors to true
|
||||||
|
//
|
||||||
// @readonly
|
// @readonly
|
||||||
ErrNoValidProvidersFoundInChain = awserr.New("NoCredentialProviders", "no valid providers in chain", nil)
|
ErrNoValidProvidersFoundInChain = awserr.New("NoCredentialProviders",
|
||||||
|
`no valid providers in chain. Deprecated.
|
||||||
|
For verbose messaging see aws.Config.CredentialsChainVerboseErrors`,
|
||||||
|
nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// A ChainProvider will search for a provider which returns credentials
|
// A ChainProvider will search for a provider which returns credentials
|
||||||
|
@ -28,23 +34,28 @@ var (
|
||||||
//
|
//
|
||||||
// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
|
// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
|
||||||
// In this example EnvProvider will first check if any credentials are available
|
// In this example EnvProvider will first check if any credentials are available
|
||||||
// vai the environment variables. If there are none ChainProvider will check
|
// via the environment variables. If there are none ChainProvider will check
|
||||||
// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
|
// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
|
||||||
// does not return any credentials ChainProvider will return the error
|
// does not return any credentials ChainProvider will return the error
|
||||||
// ErrNoValidProvidersFoundInChain
|
// ErrNoValidProvidersFoundInChain
|
||||||
//
|
//
|
||||||
// creds := NewChainCredentials(
|
// creds := credentials.NewChainCredentials(
|
||||||
// []Provider{
|
// []credentials.Provider{
|
||||||
// &EnvProvider{},
|
// &credentials.EnvProvider{},
|
||||||
// &EC2RoleProvider{},
|
// &ec2rolecreds.EC2RoleProvider{
|
||||||
|
// Client: ec2metadata.New(sess),
|
||||||
|
// },
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// // Usage of ChainCredentials with aws.Config
|
// // Usage of ChainCredentials with aws.Config
|
||||||
// svc := ec2.New(&aws.Config{Credentials: creds})
|
// svc := ec2.New(session.Must(session.NewSession(&aws.Config{
|
||||||
|
// Credentials: creds,
|
||||||
|
// })))
|
||||||
//
|
//
|
||||||
type ChainProvider struct {
|
type ChainProvider struct {
|
||||||
Providers []Provider
|
Providers []Provider
|
||||||
curr Provider
|
curr Provider
|
||||||
|
VerboseErrors bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChainCredentials returns a pointer to a new Credentials object
|
// NewChainCredentials returns a pointer to a new Credentials object
|
||||||
|
@ -61,17 +72,23 @@ func NewChainCredentials(providers []Provider) *Credentials {
|
||||||
// If a provider is found it will be cached and any calls to IsExpired()
|
// If a provider is found it will be cached and any calls to IsExpired()
|
||||||
// will return the expired state of the cached provider.
|
// will return the expired state of the cached provider.
|
||||||
func (c *ChainProvider) Retrieve() (Value, error) {
|
func (c *ChainProvider) Retrieve() (Value, error) {
|
||||||
|
var errs []error
|
||||||
for _, p := range c.Providers {
|
for _, p := range c.Providers {
|
||||||
if creds, err := p.Retrieve(); err == nil {
|
creds, err := p.Retrieve()
|
||||||
|
if err == nil {
|
||||||
c.curr = p
|
c.curr = p
|
||||||
return creds, nil
|
return creds, nil
|
||||||
}
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
c.curr = nil
|
c.curr = nil
|
||||||
|
|
||||||
// TODO better error reporting. maybe report error for each failed retrieve?
|
var err error
|
||||||
|
err = ErrNoValidProvidersFoundInChain
|
||||||
return Value{}, ErrNoValidProvidersFoundInChain
|
if c.VerboseErrors {
|
||||||
|
err = awserr.NewBatchError("NoCredentialProviders", "no valid providers in chain", errs)
|
||||||
|
}
|
||||||
|
return Value{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsExpired will returned the expired state of the currently cached provider
|
// IsExpired will returned the expired state of the currently cached provider
|
||||||
|
|
154
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go
generated
vendored
Normal file
154
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type secondStubProvider struct {
|
||||||
|
creds Value
|
||||||
|
expired bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *secondStubProvider) Retrieve() (Value, error) {
|
||||||
|
s.expired = false
|
||||||
|
s.creds.ProviderName = "secondStubProvider"
|
||||||
|
return s.creds, s.err
|
||||||
|
}
|
||||||
|
func (s *secondStubProvider) IsExpired() bool {
|
||||||
|
return s.expired
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainProviderWithNames(t *testing.T) {
|
||||||
|
p := &ChainProvider{
|
||||||
|
Providers: []Provider{
|
||||||
|
&stubProvider{err: awserr.New("FirstError", "first provider error", nil)},
|
||||||
|
&stubProvider{err: awserr.New("SecondError", "second provider error", nil)},
|
||||||
|
&secondStubProvider{
|
||||||
|
creds: Value{
|
||||||
|
AccessKeyID: "AKIF",
|
||||||
|
SecretAccessKey: "NOSECRET",
|
||||||
|
SessionToken: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&stubProvider{
|
||||||
|
creds: Value{
|
||||||
|
AccessKeyID: "AKID",
|
||||||
|
SecretAccessKey: "SECRET",
|
||||||
|
SessionToken: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
assert.Equal(t, "secondStubProvider", creds.ProviderName, "Expect provider name to match")
|
||||||
|
|
||||||
|
// Also check credentials
|
||||||
|
assert.Equal(t, "AKIF", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "NOSECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expect session token to be empty")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainProviderGet(t *testing.T) {
|
||||||
|
p := &ChainProvider{
|
||||||
|
Providers: []Provider{
|
||||||
|
&stubProvider{err: awserr.New("FirstError", "first provider error", nil)},
|
||||||
|
&stubProvider{err: awserr.New("SecondError", "second provider error", nil)},
|
||||||
|
&stubProvider{
|
||||||
|
creds: Value{
|
||||||
|
AccessKeyID: "AKID",
|
||||||
|
SecretAccessKey: "SECRET",
|
||||||
|
SessionToken: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expect session token to be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainProviderIsExpired(t *testing.T) {
|
||||||
|
stubProvider := &stubProvider{expired: true}
|
||||||
|
p := &ChainProvider{
|
||||||
|
Providers: []Provider{
|
||||||
|
stubProvider,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect expired to be true before any Retrieve")
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
assert.False(t, p.IsExpired(), "Expect not expired after retrieve")
|
||||||
|
|
||||||
|
stubProvider.expired = true
|
||||||
|
assert.True(t, p.IsExpired(), "Expect return of expired provider")
|
||||||
|
|
||||||
|
_, err = p.Retrieve()
|
||||||
|
assert.False(t, p.IsExpired(), "Expect not expired after retrieve")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainProviderWithNoProvider(t *testing.T) {
|
||||||
|
p := &ChainProvider{
|
||||||
|
Providers: []Provider{},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect expired with no providers")
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
assert.Equal(t,
|
||||||
|
ErrNoValidProvidersFoundInChain,
|
||||||
|
err,
|
||||||
|
"Expect no providers error returned")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainProviderWithNoValidProvider(t *testing.T) {
|
||||||
|
errs := []error{
|
||||||
|
awserr.New("FirstError", "first provider error", nil),
|
||||||
|
awserr.New("SecondError", "second provider error", nil),
|
||||||
|
}
|
||||||
|
p := &ChainProvider{
|
||||||
|
Providers: []Provider{
|
||||||
|
&stubProvider{err: errs[0]},
|
||||||
|
&stubProvider{err: errs[1]},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect expired with no providers")
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
|
||||||
|
assert.Equal(t,
|
||||||
|
ErrNoValidProvidersFoundInChain,
|
||||||
|
err,
|
||||||
|
"Expect no providers error returned")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChainProviderWithNoValidProviderWithVerboseEnabled(t *testing.T) {
|
||||||
|
errs := []error{
|
||||||
|
awserr.New("FirstError", "first provider error", nil),
|
||||||
|
awserr.New("SecondError", "second provider error", nil),
|
||||||
|
}
|
||||||
|
p := &ChainProvider{
|
||||||
|
VerboseErrors: true,
|
||||||
|
Providers: []Provider{
|
||||||
|
&stubProvider{err: errs[0]},
|
||||||
|
&stubProvider{err: errs[1]},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect expired with no providers")
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
|
||||||
|
assert.Equal(t,
|
||||||
|
awserr.NewBatchError("NoCredentialProviders", "no valid providers in chain", errs),
|
||||||
|
err,
|
||||||
|
"Expect no providers error returned")
|
||||||
|
}
|
40
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
generated
vendored
40
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
generated
vendored
|
@ -14,7 +14,7 @@
|
||||||
//
|
//
|
||||||
// Example of using the environment variable credentials.
|
// Example of using the environment variable credentials.
|
||||||
//
|
//
|
||||||
// creds := NewEnvCredentials()
|
// creds := credentials.NewEnvCredentials()
|
||||||
//
|
//
|
||||||
// // Retrieve the credentials value
|
// // Retrieve the credentials value
|
||||||
// credValue, err := creds.Get()
|
// credValue, err := creds.Get()
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
// This may be helpful to proactively expire credentials and refresh them sooner
|
// This may be helpful to proactively expire credentials and refresh them sooner
|
||||||
// than they would naturally expire on their own.
|
// than they would naturally expire on their own.
|
||||||
//
|
//
|
||||||
// creds := NewCredentials(&EC2RoleProvider{})
|
// creds := credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{})
|
||||||
// creds.Expire()
|
// creds.Expire()
|
||||||
// credsValue, err := creds.Get()
|
// credsValue, err := creds.Get()
|
||||||
// // New credentials will be retrieved instead of from cache.
|
// // New credentials will be retrieved instead of from cache.
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
// func (m *MyProvider) Retrieve() (Value, error) {...}
|
// func (m *MyProvider) Retrieve() (Value, error) {...}
|
||||||
// func (m *MyProvider) IsExpired() bool {...}
|
// func (m *MyProvider) IsExpired() bool {...}
|
||||||
//
|
//
|
||||||
// creds := NewCredentials(&MyProvider{})
|
// creds := credentials.NewCredentials(&MyProvider{})
|
||||||
// credValue, err := creds.Get()
|
// credValue, err := creds.Get()
|
||||||
//
|
//
|
||||||
package credentials
|
package credentials
|
||||||
|
@ -53,14 +53,16 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create an empty Credential object that can be used as dummy placeholder
|
// AnonymousCredentials is an empty Credential object that can be used as
|
||||||
// credentials for requests that do not need signed.
|
// dummy placeholder credentials for requests that do not need signed.
|
||||||
//
|
//
|
||||||
// This Credentials can be used to configure a service to not sign requests
|
// This Credentials can be used to configure a service to not sign requests
|
||||||
// when making service API calls. For example, when accessing public
|
// when making service API calls. For example, when accessing public
|
||||||
// s3 buckets.
|
// s3 buckets.
|
||||||
//
|
//
|
||||||
// svc := s3.New(&aws.Config{Credentials: AnonymousCredentials})
|
// svc := s3.New(session.Must(session.NewSession(&aws.Config{
|
||||||
|
// Credentials: credentials.AnonymousCredentials,
|
||||||
|
// })))
|
||||||
// // Access public S3 buckets.
|
// // Access public S3 buckets.
|
||||||
//
|
//
|
||||||
// @readonly
|
// @readonly
|
||||||
|
@ -76,6 +78,9 @@ type Value struct {
|
||||||
|
|
||||||
// AWS Session Token
|
// AWS Session Token
|
||||||
SessionToken string
|
SessionToken string
|
||||||
|
|
||||||
|
// Provider used to get credentials
|
||||||
|
ProviderName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Provider is the interface for any component which will provide credentials
|
// A Provider is the interface for any component which will provide credentials
|
||||||
|
@ -85,7 +90,7 @@ type Value struct {
|
||||||
// The Provider should not need to implement its own mutexes, because
|
// The Provider should not need to implement its own mutexes, because
|
||||||
// that will be managed by Credentials.
|
// that will be managed by Credentials.
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
// Refresh returns nil if it successfully retrieved the value.
|
// Retrieve returns nil if it successfully retrieved the value.
|
||||||
// Error is returned if the value were not obtainable, or empty.
|
// Error is returned if the value were not obtainable, or empty.
|
||||||
Retrieve() (Value, error)
|
Retrieve() (Value, error)
|
||||||
|
|
||||||
|
@ -94,6 +99,27 @@ type Provider interface {
|
||||||
IsExpired() bool
|
IsExpired() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An ErrorProvider is a stub credentials provider that always returns an error
|
||||||
|
// this is used by the SDK when construction a known provider is not possible
|
||||||
|
// due to an error.
|
||||||
|
type ErrorProvider struct {
|
||||||
|
// The error to be returned from Retrieve
|
||||||
|
Err error
|
||||||
|
|
||||||
|
// The provider name to set on the Retrieved returned Value
|
||||||
|
ProviderName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve will always return the error that the ErrorProvider was created with.
|
||||||
|
func (p ErrorProvider) Retrieve() (Value, error) {
|
||||||
|
return Value{ProviderName: p.ProviderName}, p.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired will always return not expired.
|
||||||
|
func (p ErrorProvider) IsExpired() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// A Expiry provides shared expiration logic to be used by credentials
|
// A Expiry provides shared expiration logic to be used by credentials
|
||||||
// providers to implement expiry functionality.
|
// providers to implement expiry functionality.
|
||||||
//
|
//
|
||||||
|
|
73
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go
generated
vendored
Normal file
73
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stubProvider struct {
|
||||||
|
creds Value
|
||||||
|
expired bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubProvider) Retrieve() (Value, error) {
|
||||||
|
s.expired = false
|
||||||
|
s.creds.ProviderName = "stubProvider"
|
||||||
|
return s.creds, s.err
|
||||||
|
}
|
||||||
|
func (s *stubProvider) IsExpired() bool {
|
||||||
|
return s.expired
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCredentialsGet(t *testing.T) {
|
||||||
|
c := NewCredentials(&stubProvider{
|
||||||
|
creds: Value{
|
||||||
|
AccessKeyID: "AKID",
|
||||||
|
SecretAccessKey: "SECRET",
|
||||||
|
SessionToken: "",
|
||||||
|
},
|
||||||
|
expired: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
creds, err := c.Get()
|
||||||
|
assert.Nil(t, err, "Expected no error")
|
||||||
|
assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expect session token to be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCredentialsGetWithError(t *testing.T) {
|
||||||
|
c := NewCredentials(&stubProvider{err: awserr.New("provider error", "", nil), expired: true})
|
||||||
|
|
||||||
|
_, err := c.Get()
|
||||||
|
assert.Equal(t, "provider error", err.(awserr.Error).Code(), "Expected provider error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCredentialsExpire(t *testing.T) {
|
||||||
|
stub := &stubProvider{}
|
||||||
|
c := NewCredentials(stub)
|
||||||
|
|
||||||
|
stub.expired = false
|
||||||
|
assert.True(t, c.IsExpired(), "Expected to start out expired")
|
||||||
|
c.Expire()
|
||||||
|
assert.True(t, c.IsExpired(), "Expected to be expired")
|
||||||
|
|
||||||
|
c.forceRefresh = false
|
||||||
|
assert.False(t, c.IsExpired(), "Expected not to be expired")
|
||||||
|
|
||||||
|
stub.expired = true
|
||||||
|
assert.True(t, c.IsExpired(), "Expected to be expired")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCredentialsGetWithProviderName(t *testing.T) {
|
||||||
|
stub := &stubProvider{}
|
||||||
|
|
||||||
|
c := NewCredentials(stub)
|
||||||
|
|
||||||
|
creds, err := c.Get()
|
||||||
|
assert.Nil(t, err, "Expected no error")
|
||||||
|
assert.Equal(t, creds.ProviderName, "stubProvider", "Expected provider name to match")
|
||||||
|
}
|
88
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
generated
vendored
88
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
generated
vendored
|
@ -9,10 +9,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ProviderName provides a name of EC2Role provider
|
||||||
|
const ProviderName = "EC2RoleProvider"
|
||||||
|
|
||||||
// A EC2RoleProvider retrieves credentials from the EC2 service, and keeps track if
|
// A EC2RoleProvider retrieves credentials from the EC2 service, and keeps track if
|
||||||
// those credentials are expired.
|
// those credentials are expired.
|
||||||
//
|
//
|
||||||
|
@ -22,12 +26,10 @@ import (
|
||||||
// p := &ec2rolecreds.EC2RoleProvider{
|
// p := &ec2rolecreds.EC2RoleProvider{
|
||||||
// // Pass in a custom timeout to be used when requesting
|
// // Pass in a custom timeout to be used when requesting
|
||||||
// // IAM EC2 Role credentials.
|
// // IAM EC2 Role credentials.
|
||||||
// Client: &http.Client{
|
// Client: ec2metadata.New(sess, aws.Config{
|
||||||
// Timeout: 10 * time.Second,
|
// HTTPClient: &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
|
// // Do not use early expiry of credentials. If a non zero value is
|
||||||
// // specified the credentials will be expired early
|
// // specified the credentials will be expired early
|
||||||
// ExpiryWindow: 0,
|
// ExpiryWindow: 0,
|
||||||
|
@ -35,8 +37,8 @@ import (
|
||||||
type EC2RoleProvider struct {
|
type EC2RoleProvider struct {
|
||||||
credentials.Expiry
|
credentials.Expiry
|
||||||
|
|
||||||
// EC2Metadata client to use when connecting to EC2 metadata service
|
// Required EC2Metadata client to use when connecting to EC2 metadata service.
|
||||||
Client *ec2metadata.Client
|
Client *ec2metadata.EC2Metadata
|
||||||
|
|
||||||
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
||||||
// the credentials actually expiring. This is beneficial so race conditions
|
// the credentials actually expiring. This is beneficial so race conditions
|
||||||
|
@ -50,46 +52,53 @@ type EC2RoleProvider struct {
|
||||||
ExpiryWindow time.Duration
|
ExpiryWindow time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCredentials returns a pointer to a new Credentials object
|
// NewCredentials returns a pointer to a new Credentials object wrapping
|
||||||
// wrapping the EC2RoleProvider.
|
// the EC2RoleProvider. Takes a ConfigProvider to create a EC2Metadata client.
|
||||||
//
|
// The ConfigProvider is satisfied by the session.Session type.
|
||||||
// Takes a custom http.Client which can be configured for custom handling of
|
func NewCredentials(c client.ConfigProvider, options ...func(*EC2RoleProvider)) *credentials.Credentials {
|
||||||
// things such as timeout.
|
p := &EC2RoleProvider{
|
||||||
//
|
Client: ec2metadata.New(c),
|
||||||
// Endpoint is the URL that the EC2RoleProvider will connect to when retrieving
|
}
|
||||||
// role and credentials.
|
|
||||||
//
|
for _, option := range options {
|
||||||
// Window is the expiry window that will be subtracted from the expiry returned
|
option(p)
|
||||||
// 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(p)
|
||||||
return credentials.NewCredentials(&EC2RoleProvider{
|
}
|
||||||
Client: client,
|
|
||||||
ExpiryWindow: window,
|
// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping
|
||||||
})
|
// the EC2RoleProvider. Takes a EC2Metadata client to use when connecting to EC2
|
||||||
|
// metadata service.
|
||||||
|
func NewCredentialsWithClient(client *ec2metadata.EC2Metadata, options ...func(*EC2RoleProvider)) *credentials.Credentials {
|
||||||
|
p := &EC2RoleProvider{
|
||||||
|
Client: client,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
option(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentials.NewCredentials(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve retrieves credentials from the EC2 service.
|
// Retrieve retrieves credentials from the EC2 service.
|
||||||
// Error will be returned if the request fails, or unable to extract
|
// Error will be returned if the request fails, or unable to extract
|
||||||
// the desired credentials.
|
// the desired credentials.
|
||||||
func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
|
func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
|
||||||
if m.Client == nil {
|
|
||||||
m.Client = ec2metadata.New(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
credsList, err := requestCredList(m.Client)
|
credsList, err := requestCredList(m.Client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return credentials.Value{}, err
|
return credentials.Value{ProviderName: ProviderName}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(credsList) == 0 {
|
if len(credsList) == 0 {
|
||||||
return credentials.Value{}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil)
|
return credentials.Value{ProviderName: ProviderName}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil)
|
||||||
}
|
}
|
||||||
credsName := credsList[0]
|
credsName := credsList[0]
|
||||||
|
|
||||||
roleCreds, err := requestCred(m.Client, credsName)
|
roleCreds, err := requestCred(m.Client, credsName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return credentials.Value{}, err
|
return credentials.Value{ProviderName: ProviderName}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow)
|
m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow)
|
||||||
|
@ -98,10 +107,11 @@ func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
|
||||||
AccessKeyID: roleCreds.AccessKeyID,
|
AccessKeyID: roleCreds.AccessKeyID,
|
||||||
SecretAccessKey: roleCreds.SecretAccessKey,
|
SecretAccessKey: roleCreds.SecretAccessKey,
|
||||||
SessionToken: roleCreds.Token,
|
SessionToken: roleCreds.Token,
|
||||||
|
ProviderName: ProviderName,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// A ec2RoleCredRespBody provides the shape for deserializing credential
|
// A ec2RoleCredRespBody provides the shape for unmarshaling credential
|
||||||
// request responses.
|
// request responses.
|
||||||
type ec2RoleCredRespBody struct {
|
type ec2RoleCredRespBody struct {
|
||||||
// Success State
|
// Success State
|
||||||
|
@ -119,10 +129,10 @@ const iamSecurityCredsPath = "/iam/security-credentials"
|
||||||
|
|
||||||
// requestCredList requests a list of credentials from the EC2 service.
|
// 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
|
// If there are no credentials, or there is an error making or receiving the request
|
||||||
func requestCredList(client *ec2metadata.Client) ([]string, error) {
|
func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) {
|
||||||
resp, err := client.GetMetadata(iamSecurityCredsPath)
|
resp, err := client.GetMetadata(iamSecurityCredsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, awserr.New("EC2RoleRequestError", "failed to list EC2 Roles", err)
|
return nil, awserr.New("EC2RoleRequestError", "no EC2 instance role found", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
credsList := []string{}
|
credsList := []string{}
|
||||||
|
@ -132,7 +142,7 @@ func requestCredList(client *ec2metadata.Client) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.Err(); err != nil {
|
if err := s.Err(); err != nil {
|
||||||
return nil, awserr.New("SerializationError", "failed to read list of EC2 Roles", err)
|
return nil, awserr.New("SerializationError", "failed to read EC2 instance role from metadata service", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return credsList, nil
|
return credsList, nil
|
||||||
|
@ -142,12 +152,12 @@ func requestCredList(client *ec2metadata.Client) ([]string, error) {
|
||||||
//
|
//
|
||||||
// If the credentials cannot be found, or there is an error reading the response
|
// If the credentials cannot be found, or there is an error reading the response
|
||||||
// and error will be returned.
|
// and error will be returned.
|
||||||
func requestCred(client *ec2metadata.Client, credsName string) (ec2RoleCredRespBody, error) {
|
func requestCred(client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) {
|
||||||
resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName))
|
resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ec2RoleCredRespBody{},
|
return ec2RoleCredRespBody{},
|
||||||
awserr.New("EC2RoleRequestError",
|
awserr.New("EC2RoleRequestError",
|
||||||
fmt.Sprintf("failed to get %s EC2 Role credentials", credsName),
|
fmt.Sprintf("failed to get %s EC2 instance role credentials", credsName),
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +165,7 @@ func requestCred(client *ec2metadata.Client, credsName string) (ec2RoleCredRespB
|
||||||
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil {
|
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil {
|
||||||
return ec2RoleCredRespBody{},
|
return ec2RoleCredRespBody{},
|
||||||
awserr.New("SerializationError",
|
awserr.New("SerializationError",
|
||||||
fmt.Sprintf("failed to decode %s EC2 Role credentials", credsName),
|
fmt.Sprintf("failed to decode %s EC2 instance role credentials", credsName),
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
159
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go
generated
vendored
Normal file
159
vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
package ec2rolecreds_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||||
|
)
|
||||||
|
|
||||||
|
const credsRespTmpl = `{
|
||||||
|
"Code": "Success",
|
||||||
|
"Type": "AWS-HMAC",
|
||||||
|
"AccessKeyId" : "accessKey",
|
||||||
|
"SecretAccessKey" : "secret",
|
||||||
|
"Token" : "token",
|
||||||
|
"Expiration" : "%s",
|
||||||
|
"LastUpdated" : "2009-11-23T0:00:00Z"
|
||||||
|
}`
|
||||||
|
|
||||||
|
const credsFailRespTmpl = `{
|
||||||
|
"Code": "ErrorCode",
|
||||||
|
"Message": "ErrorMsg",
|
||||||
|
"LastUpdated": "2009-11-23T0:00:00Z"
|
||||||
|
}`
|
||||||
|
|
||||||
|
func initTestServer(expireOn string, failAssume bool) *httptest.Server {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path == "/latest/meta-data/iam/security-credentials" {
|
||||||
|
fmt.Fprintln(w, "RoleName")
|
||||||
|
} else if r.URL.Path == "/latest/meta-data/iam/security-credentials/RoleName" {
|
||||||
|
if failAssume {
|
||||||
|
fmt.Fprintf(w, credsFailRespTmpl)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, credsRespTmpl, expireOn)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
http.Error(w, "bad request", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEC2RoleProvider(t *testing.T) {
|
||||||
|
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
p := &ec2rolecreds.EC2RoleProvider{
|
||||||
|
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error, %v", err)
|
||||||
|
|
||||||
|
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEC2RoleProviderFailAssume(t *testing.T) {
|
||||||
|
server := initTestServer("2014-12-16T01:51:37Z", true)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
p := &ec2rolecreds.EC2RoleProvider{
|
||||||
|
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Error(t, err, "Expect error")
|
||||||
|
|
||||||
|
e := err.(awserr.Error)
|
||||||
|
assert.Equal(t, "ErrorCode", e.Code())
|
||||||
|
assert.Equal(t, "ErrorMsg", e.Message())
|
||||||
|
assert.Nil(t, e.OrigErr())
|
||||||
|
|
||||||
|
assert.Equal(t, "", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEC2RoleProviderIsExpired(t *testing.T) {
|
||||||
|
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
p := &ec2rolecreds.EC2RoleProvider{
|
||||||
|
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||||
|
}
|
||||||
|
p.CurrentTime = func() time.Time {
|
||||||
|
return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
|
||||||
|
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error, %v", err)
|
||||||
|
|
||||||
|
assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
|
||||||
|
|
||||||
|
p.CurrentTime = func() time.Time {
|
||||||
|
return time.Date(3014, 12, 15, 21, 26, 0, 0, time.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect creds to be expired.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) {
|
||||||
|
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
p := &ec2rolecreds.EC2RoleProvider{
|
||||||
|
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||||
|
ExpiryWindow: time.Hour * 1,
|
||||||
|
}
|
||||||
|
p.CurrentTime = func() time.Time {
|
||||||
|
return time.Date(2014, 12, 15, 0, 51, 37, 0, time.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
|
||||||
|
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error, %v", err)
|
||||||
|
|
||||||
|
assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
|
||||||
|
|
||||||
|
p.CurrentTime = func() time.Time {
|
||||||
|
return time.Date(2014, 12, 16, 0, 55, 37, 0, time.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect creds to be expired.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEC3RoleProvider(b *testing.B) {
|
||||||
|
server := initTestServer("2014-12-16T01:51:37Z", false)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
p := &ec2rolecreds.EC2RoleProvider{
|
||||||
|
Client: ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
|
||||||
|
}
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if _, err := p.Retrieve(); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
191
vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go
generated
vendored
Normal file
191
vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
// Package endpointcreds provides support for retrieving credentials from an
|
||||||
|
// arbitrary HTTP endpoint.
|
||||||
|
//
|
||||||
|
// The credentials endpoint Provider can receive both static and refreshable
|
||||||
|
// credentials that will expire. Credentials are static when an "Expiration"
|
||||||
|
// value is not provided in the endpoint's response.
|
||||||
|
//
|
||||||
|
// Static credentials will never expire once they have been retrieved. The format
|
||||||
|
// of the static credentials response:
|
||||||
|
// {
|
||||||
|
// "AccessKeyId" : "MUA...",
|
||||||
|
// "SecretAccessKey" : "/7PC5om....",
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Refreshable credentials will expire within the "ExpiryWindow" of the Expiration
|
||||||
|
// value in the response. The format of the refreshable credentials response:
|
||||||
|
// {
|
||||||
|
// "AccessKeyId" : "MUA...",
|
||||||
|
// "SecretAccessKey" : "/7PC5om....",
|
||||||
|
// "Token" : "AQoDY....=",
|
||||||
|
// "Expiration" : "2016-02-25T06:03:31Z"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Errors should be returned in the following format and only returned with 400
|
||||||
|
// or 500 HTTP status codes.
|
||||||
|
// {
|
||||||
|
// "code": "ErrorCode",
|
||||||
|
// "message": "Helpful error message."
|
||||||
|
// }
|
||||||
|
package endpointcreds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProviderName is the name of the credentials provider.
|
||||||
|
const ProviderName = `CredentialsEndpointProvider`
|
||||||
|
|
||||||
|
// Provider satisfies the credentials.Provider interface, and is a client to
|
||||||
|
// retrieve credentials from an arbitrary endpoint.
|
||||||
|
type Provider struct {
|
||||||
|
staticCreds bool
|
||||||
|
credentials.Expiry
|
||||||
|
|
||||||
|
// Requires a AWS Client to make HTTP requests to the endpoint with.
|
||||||
|
// the Endpoint the request will be made to is provided by the aws.Config's
|
||||||
|
// Endpoint value.
|
||||||
|
Client *client.Client
|
||||||
|
|
||||||
|
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
||||||
|
// the credentials actually expiring. This is beneficial so race conditions
|
||||||
|
// with expiring credentials do not cause request to fail unexpectedly
|
||||||
|
// due to ExpiredTokenException exceptions.
|
||||||
|
//
|
||||||
|
// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
|
||||||
|
// 10 seconds before the credentials are actually expired.
|
||||||
|
//
|
||||||
|
// If ExpiryWindow is 0 or less it will be ignored.
|
||||||
|
ExpiryWindow time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProviderClient returns a credentials Provider for retrieving AWS credentials
|
||||||
|
// from arbitrary endpoint.
|
||||||
|
func NewProviderClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) credentials.Provider {
|
||||||
|
p := &Provider{
|
||||||
|
Client: client.New(
|
||||||
|
cfg,
|
||||||
|
metadata.ClientInfo{
|
||||||
|
ServiceName: "CredentialsEndpoint",
|
||||||
|
Endpoint: endpoint,
|
||||||
|
},
|
||||||
|
handlers,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Client.Handlers.Unmarshal.PushBack(unmarshalHandler)
|
||||||
|
p.Client.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||||
|
p.Client.Handlers.Validate.Clear()
|
||||||
|
p.Client.Handlers.Validate.PushBack(validateEndpointHandler)
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
option(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCredentialsClient returns a Credentials wrapper for retrieving credentials
|
||||||
|
// from an arbitrary endpoint concurrently. The client will request the
|
||||||
|
func NewCredentialsClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) *credentials.Credentials {
|
||||||
|
return credentials.NewCredentials(NewProviderClient(cfg, handlers, endpoint, options...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired returns true if the credentials retrieved are expired, or not yet
|
||||||
|
// retrieved.
|
||||||
|
func (p *Provider) IsExpired() bool {
|
||||||
|
if p.staticCreds {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return p.Expiry.IsExpired()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve will attempt to request the credentials from the endpoint the Provider
|
||||||
|
// was configured for. And error will be returned if the retrieval fails.
|
||||||
|
func (p *Provider) Retrieve() (credentials.Value, error) {
|
||||||
|
resp, err := p.getCredentials()
|
||||||
|
if err != nil {
|
||||||
|
return credentials.Value{ProviderName: ProviderName},
|
||||||
|
awserr.New("CredentialsEndpointError", "failed to load credentials", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Expiration != nil {
|
||||||
|
p.SetExpiration(*resp.Expiration, p.ExpiryWindow)
|
||||||
|
} else {
|
||||||
|
p.staticCreds = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentials.Value{
|
||||||
|
AccessKeyID: resp.AccessKeyID,
|
||||||
|
SecretAccessKey: resp.SecretAccessKey,
|
||||||
|
SessionToken: resp.Token,
|
||||||
|
ProviderName: ProviderName,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type getCredentialsOutput struct {
|
||||||
|
Expiration *time.Time
|
||||||
|
AccessKeyID string
|
||||||
|
SecretAccessKey string
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
|
type errorOutput struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getCredentials() (*getCredentialsOutput, error) {
|
||||||
|
op := &request.Operation{
|
||||||
|
Name: "GetCredentials",
|
||||||
|
HTTPMethod: "GET",
|
||||||
|
}
|
||||||
|
|
||||||
|
out := &getCredentialsOutput{}
|
||||||
|
req := p.Client.NewRequest(op, nil, out)
|
||||||
|
req.HTTPRequest.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
|
return out, req.Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateEndpointHandler(r *request.Request) {
|
||||||
|
if len(r.ClientInfo.Endpoint) == 0 {
|
||||||
|
r.Error = aws.ErrMissingEndpoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalHandler(r *request.Request) {
|
||||||
|
defer r.HTTPResponse.Body.Close()
|
||||||
|
|
||||||
|
out := r.Data.(*getCredentialsOutput)
|
||||||
|
if err := json.NewDecoder(r.HTTPResponse.Body).Decode(&out); err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError",
|
||||||
|
"failed to decode endpoint credentials",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalError(r *request.Request) {
|
||||||
|
defer r.HTTPResponse.Body.Close()
|
||||||
|
|
||||||
|
var errOut errorOutput
|
||||||
|
if err := json.NewDecoder(r.HTTPResponse.Body).Decode(&errOut); err != nil {
|
||||||
|
r.Error = awserr.New("SerializationError",
|
||||||
|
"failed to decode endpoint credentials",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response body format is not consistent between metadata endpoints.
|
||||||
|
// Grab the error message as a string and include that as the source error
|
||||||
|
r.Error = awserr.New(errOut.Code, errOut.Message, nil)
|
||||||
|
}
|
111
vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go
generated
vendored
Normal file
111
vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
package endpointcreds_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRetrieveRefreshableCredentials(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, "/path/to/endpoint", r.URL.Path)
|
||||||
|
assert.Equal(t, "application/json", r.Header.Get("Accept"))
|
||||||
|
assert.Equal(t, "else", r.URL.Query().Get("something"))
|
||||||
|
|
||||||
|
encoder := json.NewEncoder(w)
|
||||||
|
err := encoder.Encode(map[string]interface{}{
|
||||||
|
"AccessKeyID": "AKID",
|
||||||
|
"SecretAccessKey": "SECRET",
|
||||||
|
"Token": "TOKEN",
|
||||||
|
"Expiration": time.Now().Add(1 * time.Hour),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to write out creds", err)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
client := endpointcreds.NewProviderClient(*unit.Session.Config,
|
||||||
|
unit.Session.Handlers,
|
||||||
|
server.URL+"/path/to/endpoint?something=else",
|
||||||
|
)
|
||||||
|
creds, err := client.Retrieve()
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, "AKID", creds.AccessKeyID)
|
||||||
|
assert.Equal(t, "SECRET", creds.SecretAccessKey)
|
||||||
|
assert.Equal(t, "TOKEN", creds.SessionToken)
|
||||||
|
assert.False(t, client.IsExpired())
|
||||||
|
|
||||||
|
client.(*endpointcreds.Provider).CurrentTime = func() time.Time {
|
||||||
|
return time.Now().Add(2 * time.Hour)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.True(t, client.IsExpired())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRetrieveStaticCredentials(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
encoder := json.NewEncoder(w)
|
||||||
|
err := encoder.Encode(map[string]interface{}{
|
||||||
|
"AccessKeyID": "AKID",
|
||||||
|
"SecretAccessKey": "SECRET",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to write out creds", err)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
client := endpointcreds.NewProviderClient(*unit.Session.Config, unit.Session.Handlers, server.URL)
|
||||||
|
creds, err := client.Retrieve()
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, "AKID", creds.AccessKeyID)
|
||||||
|
assert.Equal(t, "SECRET", creds.SecretAccessKey)
|
||||||
|
assert.Empty(t, creds.SessionToken)
|
||||||
|
assert.False(t, client.IsExpired())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailedRetrieveCredentials(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(400)
|
||||||
|
encoder := json.NewEncoder(w)
|
||||||
|
err := encoder.Encode(map[string]interface{}{
|
||||||
|
"Code": "Error",
|
||||||
|
"Message": "Message",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to write error", err)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
client := endpointcreds.NewProviderClient(*unit.Session.Config, unit.Session.Handlers, server.URL)
|
||||||
|
creds, err := client.Retrieve()
|
||||||
|
|
||||||
|
assert.Error(t, err)
|
||||||
|
aerr := err.(awserr.Error)
|
||||||
|
|
||||||
|
assert.Equal(t, "CredentialsEndpointError", aerr.Code())
|
||||||
|
assert.Equal(t, "failed to load credentials", aerr.Message())
|
||||||
|
|
||||||
|
aerr = aerr.OrigErr().(awserr.Error)
|
||||||
|
assert.Equal(t, "Error", aerr.Code())
|
||||||
|
assert.Equal(t, "Message", aerr.Message())
|
||||||
|
|
||||||
|
assert.Empty(t, creds.AccessKeyID)
|
||||||
|
assert.Empty(t, creds.SecretAccessKey)
|
||||||
|
assert.Empty(t, creds.SessionToken)
|
||||||
|
assert.True(t, client.IsExpired())
|
||||||
|
}
|
9
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go
generated
vendored
9
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go
generated
vendored
|
@ -6,6 +6,9 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EnvProviderName provides a name of Env provider
|
||||||
|
const EnvProviderName = "EnvProvider"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be
|
// ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be
|
||||||
// found in the process's environment.
|
// found in the process's environment.
|
||||||
|
@ -26,6 +29,7 @@ var (
|
||||||
// Environment variables used:
|
// Environment variables used:
|
||||||
//
|
//
|
||||||
// * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY
|
// * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY
|
||||||
|
//
|
||||||
// * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
|
// * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
|
||||||
type EnvProvider struct {
|
type EnvProvider struct {
|
||||||
retrieved bool
|
retrieved bool
|
||||||
|
@ -52,11 +56,11 @@ func (e *EnvProvider) Retrieve() (Value, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return Value{}, ErrAccessKeyIDNotFound
|
return Value{ProviderName: EnvProviderName}, ErrAccessKeyIDNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
if secret == "" {
|
if secret == "" {
|
||||||
return Value{}, ErrSecretAccessKeyNotFound
|
return Value{ProviderName: EnvProviderName}, ErrSecretAccessKeyNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
e.retrieved = true
|
e.retrieved = true
|
||||||
|
@ -64,6 +68,7 @@ func (e *EnvProvider) Retrieve() (Value, error) {
|
||||||
AccessKeyID: id,
|
AccessKeyID: id,
|
||||||
SecretAccessKey: secret,
|
SecretAccessKey: secret,
|
||||||
SessionToken: os.Getenv("AWS_SESSION_TOKEN"),
|
SessionToken: os.Getenv("AWS_SESSION_TOKEN"),
|
||||||
|
ProviderName: EnvProviderName,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
70
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go
generated
vendored
Normal file
70
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnvProviderRetrieve(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("AWS_ACCESS_KEY_ID", "access")
|
||||||
|
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
|
||||||
|
os.Setenv("AWS_SESSION_TOKEN", "token")
|
||||||
|
|
||||||
|
e := EnvProvider{}
|
||||||
|
creds, err := e.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "access", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvProviderIsExpired(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("AWS_ACCESS_KEY_ID", "access")
|
||||||
|
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
|
||||||
|
os.Setenv("AWS_SESSION_TOKEN", "token")
|
||||||
|
|
||||||
|
e := EnvProvider{}
|
||||||
|
|
||||||
|
assert.True(t, e.IsExpired(), "Expect creds to be expired before retrieve.")
|
||||||
|
|
||||||
|
_, err := e.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.False(t, e.IsExpired(), "Expect creds to not be expired after retrieve.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvProviderNoAccessKeyID(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
|
||||||
|
|
||||||
|
e := EnvProvider{}
|
||||||
|
creds, err := e.Retrieve()
|
||||||
|
assert.Equal(t, ErrAccessKeyIDNotFound, err, "ErrAccessKeyIDNotFound expected, but was %#v error: %#v", creds, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvProviderNoSecretAccessKey(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("AWS_ACCESS_KEY_ID", "access")
|
||||||
|
|
||||||
|
e := EnvProvider{}
|
||||||
|
creds, err := e.Retrieve()
|
||||||
|
assert.Equal(t, ErrSecretAccessKeyNotFound, err, "ErrSecretAccessKeyNotFound expected, but was %#v error: %#v", creds, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvProviderAlternateNames(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("AWS_ACCESS_KEY", "access")
|
||||||
|
os.Setenv("AWS_SECRET_KEY", "secret")
|
||||||
|
|
||||||
|
e := EnvProvider{}
|
||||||
|
creds, err := e.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "access", creds.AccessKeyID, "Expected access key ID")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expected secret access key")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expected no token")
|
||||||
|
}
|
4
vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini
generated
vendored
4
vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini
generated
vendored
|
@ -6,3 +6,7 @@ aws_session_token = token
|
||||||
[no_token]
|
[no_token]
|
||||||
aws_access_key_id = accessKey
|
aws_access_key_id = accessKey
|
||||||
aws_secret_access_key = secret
|
aws_secret_access_key = secret
|
||||||
|
|
||||||
|
[with_colon]
|
||||||
|
aws_access_key_id: accessKey
|
||||||
|
aws_secret_access_key: secret
|
||||||
|
|
5
vendor/github.com/aws/aws-sdk-go/aws/credentials/plugincreds/doc_1_7.go
generated
vendored
Normal file
5
vendor/github.com/aws/aws-sdk-go/aws/credentials/plugincreds/doc_1_7.go
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// +build !go1.8
|
||||||
|
|
||||||
|
// Package plugincreds provides usage of Go plugins for providing credentials
|
||||||
|
// to the SDK. Only available with Go 1.8 and above.
|
||||||
|
package plugincreds
|
211
vendor/github.com/aws/aws-sdk-go/aws/credentials/plugincreds/provider.go
generated
vendored
Normal file
211
vendor/github.com/aws/aws-sdk-go/aws/credentials/plugincreds/provider.go
generated
vendored
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
// Package plugincreds implements a credentials provider sourced from a Go
|
||||||
|
// plugin. This package allows you to use a Go plugin to retrieve AWS credentials
|
||||||
|
// for the SDK to use for service API calls.
|
||||||
|
//
|
||||||
|
// As of Go 1.8 plugins are only supported on the Linux platform.
|
||||||
|
//
|
||||||
|
// Plugin Symbol Name
|
||||||
|
//
|
||||||
|
// The "GetAWSSDKCredentialProvider" is the symbol name that will be used to
|
||||||
|
// lookup the credentials provider getter from the plugin. If you want to use a
|
||||||
|
// custom symbol name you should use GetPluginProviderFnsByName to lookup the
|
||||||
|
// symbol by a custom name.
|
||||||
|
//
|
||||||
|
// This symbol is a function that returns two additional functions. One to
|
||||||
|
// retrieve the credentials, and another to determine if the credentials have
|
||||||
|
// expired.
|
||||||
|
//
|
||||||
|
// Plugin Symbol Signature
|
||||||
|
//
|
||||||
|
// The plugin credential provider requires the symbol to match the
|
||||||
|
// following signature.
|
||||||
|
//
|
||||||
|
// func() (RetrieveFn func() (key, secret, token string, err error), IsExpiredFn func() bool)
|
||||||
|
//
|
||||||
|
// Plugin Implementation Exmaple
|
||||||
|
//
|
||||||
|
// The following is an example implementation of a SDK credential provider using
|
||||||
|
// the plugin provider in this package. See the SDK's example/aws/credential/plugincreds/plugin
|
||||||
|
// folder for a runnable example of this.
|
||||||
|
//
|
||||||
|
// package main
|
||||||
|
//
|
||||||
|
// func main() {}
|
||||||
|
//
|
||||||
|
// var myCredProvider provider
|
||||||
|
//
|
||||||
|
// // Build: go build -o plugin.so -buildmode=plugin plugin.go
|
||||||
|
// func init() {
|
||||||
|
// // Initialize a mock credential provider with stubs
|
||||||
|
// myCredProvider = provider{"a","b","c"}
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // GetAWSSDKCredentialProvider is the symbol SDK will lookup and use to
|
||||||
|
// // get the credential provider's retrieve and isExpired functions.
|
||||||
|
// func GetAWSSDKCredentialProvider() (func() (key, secret, token string, err error), func() bool) {
|
||||||
|
// return myCredProvider.Retrieve, myCredProvider.IsExpired
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // mock implementation of a type that returns retrieves credentials and
|
||||||
|
// // returns if they have expired.
|
||||||
|
// type provider struct {
|
||||||
|
// key, secret, token string
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (p provider) Retrieve() (key, secret, token string, err error) {
|
||||||
|
// return p.key, p.secret, p.token, nil
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (p *provider) IsExpired() bool {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Configuring SDK for Plugin Credentials
|
||||||
|
//
|
||||||
|
// To configure the SDK to use a plugin's credential provider you'll need to first
|
||||||
|
// open the plugin file using the plugin standard library package. Once you have
|
||||||
|
// a handle to the plugin you can use the NewCredentials function of this package
|
||||||
|
// to create a new credentials.Credentials value that can be set as the
|
||||||
|
// credentials loader of a Session or Config. See the SDK's example/aws/credential/plugincreds
|
||||||
|
// folder for a runnable example of this.
|
||||||
|
//
|
||||||
|
// // Open plugin, and load it into the process.
|
||||||
|
// p, err := plugin.Open("somefile.so")
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Create a new Credentials value which will source the provider's Retrieve
|
||||||
|
// // and IsExpired functions from the plugin.
|
||||||
|
// creds, err := plugincreds.NewCredentials(p)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Example to configure a Session with the newly created credentials that
|
||||||
|
// // will be sourced using the plugin's functionality.
|
||||||
|
// sess := session.Must(session.NewSession(&aws.Config{
|
||||||
|
// Credentials: creds,
|
||||||
|
// }))
|
||||||
|
package plugincreds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"plugin"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProviderSymbolName the symbol name the SDK will use to lookup the plugin
|
||||||
|
// provider value from.
|
||||||
|
const ProviderSymbolName = `GetAWSSDKCredentialProvider`
|
||||||
|
|
||||||
|
// ProviderName is the name this credentials provider will label any returned
|
||||||
|
// credentials Value with.
|
||||||
|
const ProviderName = `PluginCredentialsProvider`
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ErrCodeLookupSymbolError failed to lookup symbol
|
||||||
|
ErrCodeLookupSymbolError = "LookupSymbolError"
|
||||||
|
|
||||||
|
// ErrCodeInvalidSymbolError symbol invalid
|
||||||
|
ErrCodeInvalidSymbolError = "InvalidSymbolError"
|
||||||
|
|
||||||
|
// ErrCodePluginRetrieveNil Retrieve function was nil
|
||||||
|
ErrCodePluginRetrieveNil = "PluginRetrieveNilError"
|
||||||
|
|
||||||
|
// ErrCodePluginIsExpiredNil IsExpired Function was nil
|
||||||
|
ErrCodePluginIsExpiredNil = "PluginIsExpiredNilError"
|
||||||
|
|
||||||
|
// ErrCodePluginProviderRetrieve plugin provider's retrieve returned error
|
||||||
|
ErrCodePluginProviderRetrieve = "PluginProviderRetrieveError"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider is the credentials provider that will use the plugin provided
|
||||||
|
// Retrieve and IsExpired functions to retrieve credentials.
|
||||||
|
type Provider struct {
|
||||||
|
RetrieveFn func() (key, secret, token string, err error)
|
||||||
|
IsExpiredFn func() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCredentials returns a new Credentials loader using the plugin provider.
|
||||||
|
// If the symbol isn't found or is invalid in the plugin an error will be
|
||||||
|
// returned.
|
||||||
|
func NewCredentials(p *plugin.Plugin) (*credentials.Credentials, error) {
|
||||||
|
retrieve, isExpired, err := GetPluginProviderFns(p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentials.NewCredentials(Provider{
|
||||||
|
RetrieveFn: retrieve,
|
||||||
|
IsExpiredFn: isExpired,
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve will return the credentials Value if they were successfully retrieved
|
||||||
|
// from the underlying plugin provider. An error will be returned otherwise.
|
||||||
|
func (p Provider) Retrieve() (credentials.Value, error) {
|
||||||
|
creds := credentials.Value{
|
||||||
|
ProviderName: ProviderName,
|
||||||
|
}
|
||||||
|
|
||||||
|
k, s, t, err := p.RetrieveFn()
|
||||||
|
if err != nil {
|
||||||
|
return creds, awserr.New(ErrCodePluginProviderRetrieve,
|
||||||
|
"failed to retrieve credentials with plugin provider", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
creds.AccessKeyID = k
|
||||||
|
creds.SecretAccessKey = s
|
||||||
|
creds.SessionToken = t
|
||||||
|
|
||||||
|
return creds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired will return the expired state of the underlying plugin provider.
|
||||||
|
func (p Provider) IsExpired() bool {
|
||||||
|
return p.IsExpiredFn()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPluginProviderFns returns the plugin's Retrieve and IsExpired functions
|
||||||
|
// returned by the plugin's credential provider getter.
|
||||||
|
//
|
||||||
|
// Uses ProviderSymbolName as the symbol name when lookup up the symbol. If you
|
||||||
|
// want to use a different symbol name, use GetPluginProviderFnsByName.
|
||||||
|
func GetPluginProviderFns(p *plugin.Plugin) (func() (key, secret, token string, err error), func() bool, error) {
|
||||||
|
return GetPluginProviderFnsByName(p, ProviderSymbolName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPluginProviderFnsByName returns the plugin's Retrieve and IsExpired functions
|
||||||
|
// returned by the plugin's credential provider getter.
|
||||||
|
//
|
||||||
|
// Same as GetPluginProviderFns, but takes a custom symbolName to lookup with.
|
||||||
|
func GetPluginProviderFnsByName(p *plugin.Plugin, symbolName string) (func() (key, secret, token string, err error), func() bool, error) {
|
||||||
|
sym, err := p.Lookup(symbolName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, awserr.New(ErrCodeLookupSymbolError,
|
||||||
|
fmt.Sprintf("failed to lookup %s plugin provider symbol", symbolName), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn, ok := sym.(func() (func() (key, secret, token string, err error), func() bool))
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, awserr.New(ErrCodeInvalidSymbolError,
|
||||||
|
fmt.Sprintf("symbol %T, does not match the 'func() (func() (key, secret, token string, err error), func() bool)' type", sym), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
retrieveFn, isExpiredFn := fn()
|
||||||
|
if retrieveFn == nil {
|
||||||
|
return nil, nil, awserr.New(ErrCodePluginRetrieveNil,
|
||||||
|
"the plugin provider retrieve function cannot be nil", nil)
|
||||||
|
}
|
||||||
|
if isExpiredFn == nil {
|
||||||
|
return nil, nil, awserr.New(ErrCodePluginIsExpiredNil,
|
||||||
|
"the plugin provider isExpired function cannot be nil", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return retrieveFn, isExpiredFn, nil
|
||||||
|
}
|
71
vendor/github.com/aws/aws-sdk-go/aws/credentials/plugincreds/provider_test.go
generated
vendored
Normal file
71
vendor/github.com/aws/aws-sdk-go/aws/credentials/plugincreds/provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// +build go1.8,awsinclude
|
||||||
|
|
||||||
|
package plugincreds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProvider_Passthrough(t *testing.T) {
|
||||||
|
p := Provider{
|
||||||
|
RetrieveFn: func() (string, string, string, error) {
|
||||||
|
return "key", "secret", "token", nil
|
||||||
|
},
|
||||||
|
IsExpiredFn: func() bool {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, err := p.Retrieve()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := credentials.Value{
|
||||||
|
AccessKeyID: "key",
|
||||||
|
SecretAccessKey: "secret",
|
||||||
|
SessionToken: "token",
|
||||||
|
ProviderName: ProviderName,
|
||||||
|
}
|
||||||
|
if expect != actual {
|
||||||
|
t.Errorf("expect %+v credentials, got %+v", expect, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_Error(t *testing.T) {
|
||||||
|
expectErr := fmt.Errorf("expect error")
|
||||||
|
|
||||||
|
p := Provider{
|
||||||
|
RetrieveFn: func() (string, string, string, error) {
|
||||||
|
return "", "", "", expectErr
|
||||||
|
},
|
||||||
|
IsExpiredFn: func() bool {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, err := p.Retrieve()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expect error, got none")
|
||||||
|
}
|
||||||
|
|
||||||
|
aerr := err.(awserr.Error)
|
||||||
|
if e, a := ErrCodePluginProviderRetrieve, aerr.Code(); e != a {
|
||||||
|
t.Errorf("expect %s error code, got %s", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, a := expectErr, aerr.OrigErr(); e != a {
|
||||||
|
t.Errorf("expect %v cause error, got %v", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := credentials.Value{
|
||||||
|
ProviderName: ProviderName,
|
||||||
|
}
|
||||||
|
if expect != actual {
|
||||||
|
t.Errorf("expect %+v credentials, got %+v", expect, actual)
|
||||||
|
}
|
||||||
|
}
|
75
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go
generated
vendored
75
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go
generated
vendored
|
@ -3,17 +3,18 @@ package credentials
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/vaughan0/go-ini"
|
"github.com/go-ini/ini"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/internal/shareddefaults"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SharedCredsProviderName provides a name of SharedCreds provider
|
||||||
|
const SharedCredsProviderName = "SharedCredentialsProvider"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found.
|
// ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found.
|
||||||
//
|
|
||||||
// @readonly
|
|
||||||
ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil)
|
ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,12 +56,12 @@ func (p *SharedCredentialsProvider) Retrieve() (Value, error) {
|
||||||
|
|
||||||
filename, err := p.filename()
|
filename, err := p.filename()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{ProviderName: SharedCredsProviderName}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
creds, err := loadProfile(filename, p.profile())
|
creds, err := loadProfile(filename, p.profile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, err
|
return Value{ProviderName: SharedCredsProviderName}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.retrieved = true
|
p.retrieved = true
|
||||||
|
@ -76,32 +77,37 @@ func (p *SharedCredentialsProvider) IsExpired() bool {
|
||||||
// The credentials retrieved from the profile will be returned or error. Error will be
|
// 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.
|
// returned if it fails to read from the file, or the data is invalid.
|
||||||
func loadProfile(filename, profile string) (Value, error) {
|
func loadProfile(filename, profile string) (Value, error) {
|
||||||
config, err := ini.LoadFile(filename)
|
config, err := ini.Load(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Value{}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err)
|
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err)
|
||||||
|
}
|
||||||
|
iniProfile, err := config.GetSection(profile)
|
||||||
|
if err != nil {
|
||||||
|
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to get profile", err)
|
||||||
}
|
}
|
||||||
iniProfile := config.Section(profile)
|
|
||||||
|
|
||||||
id, ok := iniProfile["aws_access_key_id"]
|
id, err := iniProfile.GetKey("aws_access_key_id")
|
||||||
if !ok {
|
if err != nil {
|
||||||
return Value{}, awserr.New("SharedCredsAccessKey",
|
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsAccessKey",
|
||||||
fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename),
|
fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename),
|
||||||
nil)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secret, ok := iniProfile["aws_secret_access_key"]
|
secret, err := iniProfile.GetKey("aws_secret_access_key")
|
||||||
if !ok {
|
if err != nil {
|
||||||
return Value{}, awserr.New("SharedCredsSecret",
|
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsSecret",
|
||||||
fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename),
|
fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename),
|
||||||
nil)
|
nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
token := iniProfile["aws_session_token"]
|
// Default to empty string if not found
|
||||||
|
token := iniProfile.Key("aws_session_token")
|
||||||
|
|
||||||
return Value{
|
return Value{
|
||||||
AccessKeyID: id,
|
AccessKeyID: id.String(),
|
||||||
SecretAccessKey: secret,
|
SecretAccessKey: secret.String(),
|
||||||
SessionToken: token,
|
SessionToken: token.String(),
|
||||||
|
ProviderName: SharedCredsProviderName,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,22 +115,23 @@ func loadProfile(filename, profile string) (Value, error) {
|
||||||
//
|
//
|
||||||
// Will return an error if the user's home directory path cannot be found.
|
// Will return an error if the user's home directory path cannot be found.
|
||||||
func (p *SharedCredentialsProvider) filename() (string, error) {
|
func (p *SharedCredentialsProvider) filename() (string, error) {
|
||||||
if p.Filename == "" {
|
if len(p.Filename) != 0 {
|
||||||
if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); p.Filename != "" {
|
return p.Filename, nil
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(p.Filename) != 0 {
|
||||||
|
return p.Filename, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if home := shareddefaults.UserHomeDir(); len(home) == 0 {
|
||||||
|
// Backwards compatibility of home directly not found error being returned.
|
||||||
|
// This error is too verbose, failure when opening the file would of been
|
||||||
|
// a better error to return.
|
||||||
|
return "", ErrSharedCredentialsHomeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Filename = shareddefaults.SharedCredentialsFilename()
|
||||||
|
|
||||||
return p.Filename, nil
|
return p.Filename, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
136
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go
generated
vendored
Normal file
136
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/internal/shareddefaults"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSharedCredentialsProvider(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
|
||||||
|
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSharedCredentialsProviderIsExpired(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
|
||||||
|
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||||
|
|
||||||
|
assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve")
|
||||||
|
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSharedCredentialsProviderWithAWS_SHARED_CREDENTIALS_FILE(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example.ini")
|
||||||
|
p := SharedCredentialsProvider{}
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSharedCredentialsProviderWithAWS_SHARED_CREDENTIALS_FILEAbsPath(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", filepath.Join(wd, "example.ini"))
|
||||||
|
p := SharedCredentialsProvider{}
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "token", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSharedCredentialsProviderWithAWS_PROFILE(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("AWS_PROFILE", "no_token")
|
||||||
|
|
||||||
|
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expect no token")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSharedCredentialsProviderWithoutTokenFromProfile(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
|
||||||
|
p := SharedCredentialsProvider{Filename: "example.ini", Profile: "no_token"}
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expect no token")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSharedCredentialsProviderColonInCredFile(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
|
||||||
|
p := SharedCredentialsProvider{Filename: "example.ini", Profile: "with_colon"}
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expect no token")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSharedCredentialsProvider_DefaultFilename(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
os.Setenv("USERPROFILE", "profile_dir")
|
||||||
|
os.Setenv("HOME", "home_dir")
|
||||||
|
|
||||||
|
// default filename and profile
|
||||||
|
p := SharedCredentialsProvider{}
|
||||||
|
|
||||||
|
filename, err := p.filename()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if e, a := shareddefaults.SharedCredentialsFilename(), filename; e != a {
|
||||||
|
t.Errorf("expect %q filename, got %q", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSharedCredentialsProvider(b *testing.B) {
|
||||||
|
os.Clearenv()
|
||||||
|
|
||||||
|
p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""}
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := p.Retrieve()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go
generated
vendored
17
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go
generated
vendored
|
@ -4,6 +4,9 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StaticProviderName provides a name of Static provider
|
||||||
|
const StaticProviderName = "StaticProvider"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrStaticCredentialsEmpty is emitted when static credentials are empty.
|
// ErrStaticCredentialsEmpty is emitted when static credentials are empty.
|
||||||
//
|
//
|
||||||
|
@ -11,7 +14,7 @@ var (
|
||||||
ErrStaticCredentialsEmpty = awserr.New("EmptyStaticCreds", "static credentials are empty", nil)
|
ErrStaticCredentialsEmpty = awserr.New("EmptyStaticCreds", "static credentials are empty", nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// A StaticProvider is a set of credentials which are set pragmatically,
|
// A StaticProvider is a set of credentials which are set programmatically,
|
||||||
// and will never expire.
|
// and will never expire.
|
||||||
type StaticProvider struct {
|
type StaticProvider struct {
|
||||||
Value
|
Value
|
||||||
|
@ -27,12 +30,22 @@ func NewStaticCredentials(id, secret, token string) *Credentials {
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewStaticCredentialsFromCreds returns a pointer to a new Credentials object
|
||||||
|
// wrapping the static credentials value provide. Same as NewStaticCredentials
|
||||||
|
// but takes the creds Value instead of individual fields
|
||||||
|
func NewStaticCredentialsFromCreds(creds Value) *Credentials {
|
||||||
|
return NewCredentials(&StaticProvider{Value: creds})
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve returns the credentials or error if the credentials are invalid.
|
// Retrieve returns the credentials or error if the credentials are invalid.
|
||||||
func (s *StaticProvider) Retrieve() (Value, error) {
|
func (s *StaticProvider) Retrieve() (Value, error) {
|
||||||
if s.AccessKeyID == "" || s.SecretAccessKey == "" {
|
if s.AccessKeyID == "" || s.SecretAccessKey == "" {
|
||||||
return Value{}, ErrStaticCredentialsEmpty
|
return Value{ProviderName: StaticProviderName}, ErrStaticCredentialsEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(s.Value.ProviderName) == 0 {
|
||||||
|
s.Value.ProviderName = StaticProviderName
|
||||||
|
}
|
||||||
return s.Value, nil
|
return s.Value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go
generated
vendored
Normal file
34
vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package credentials
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStaticProviderGet(t *testing.T) {
|
||||||
|
s := StaticProvider{
|
||||||
|
Value: Value{
|
||||||
|
AccessKeyID: "AKID",
|
||||||
|
SecretAccessKey: "SECRET",
|
||||||
|
SessionToken: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := s.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match")
|
||||||
|
assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Empty(t, creds.SessionToken, "Expect no session token")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStaticProviderIsExpired(t *testing.T) {
|
||||||
|
s := StaticProvider{
|
||||||
|
Value: Value{
|
||||||
|
AccessKeyID: "AKID",
|
||||||
|
SecretAccessKey: "SECRET",
|
||||||
|
SessionToken: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.False(t, s.IsExpired(), "Expect static credentials to never expire")
|
||||||
|
}
|
298
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
generated
vendored
Normal file
298
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
generated
vendored
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
/*
|
||||||
|
Package stscreds are credential Providers to retrieve STS AWS credentials.
|
||||||
|
|
||||||
|
STS provides multiple ways to retrieve credentials which can be used when making
|
||||||
|
future AWS service API operation calls.
|
||||||
|
|
||||||
|
The SDK will ensure that per instance of credentials.Credentials all requests
|
||||||
|
to refresh the credentials will be synchronized. But, the SDK is unable to
|
||||||
|
ensure synchronous usage of the AssumeRoleProvider if the value is shared
|
||||||
|
between multiple Credentials, Sessions or service clients.
|
||||||
|
|
||||||
|
Assume Role
|
||||||
|
|
||||||
|
To assume an IAM role using STS with the SDK you can create a new Credentials
|
||||||
|
with the SDKs's stscreds package.
|
||||||
|
|
||||||
|
// Initial credentials loaded from SDK's default credential chain. Such as
|
||||||
|
// the environment, shared credentials (~/.aws/credentials), or EC2 Instance
|
||||||
|
// Role. These credentials will be used to to make the STS Assume Role API.
|
||||||
|
sess := session.Must(session.NewSession())
|
||||||
|
|
||||||
|
// Create the credentials from AssumeRoleProvider to assume the role
|
||||||
|
// referenced by the "myRoleARN" ARN.
|
||||||
|
creds := stscreds.NewCredentials(sess, "myRoleArn")
|
||||||
|
|
||||||
|
// Create service client value configured for credentials
|
||||||
|
// from assumed role.
|
||||||
|
svc := s3.New(sess, &aws.Config{Credentials: creds})
|
||||||
|
|
||||||
|
Assume Role with static MFA Token
|
||||||
|
|
||||||
|
To assume an IAM role with a MFA token you can either specify a MFA token code
|
||||||
|
directly or provide a function to prompt the user each time the credentials
|
||||||
|
need to refresh the role's credentials. Specifying the TokenCode should be used
|
||||||
|
for short lived operations that will not need to be refreshed, and when you do
|
||||||
|
not want to have direct control over the user provides their MFA token.
|
||||||
|
|
||||||
|
With TokenCode the AssumeRoleProvider will be not be able to refresh the role's
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
// Create the credentials from AssumeRoleProvider to assume the role
|
||||||
|
// referenced by the "myRoleARN" ARN using the MFA token code provided.
|
||||||
|
creds := stscreds.NewCredentials(sess, "myRoleArn", func(p *stscreds.AssumeRoleProvider) {
|
||||||
|
p.SerialNumber = aws.String("myTokenSerialNumber")
|
||||||
|
p.TokenCode = aws.String("00000000")
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create service client value configured for credentials
|
||||||
|
// from assumed role.
|
||||||
|
svc := s3.New(sess, &aws.Config{Credentials: creds})
|
||||||
|
|
||||||
|
Assume Role with MFA Token Provider
|
||||||
|
|
||||||
|
To assume an IAM role with MFA for longer running tasks where the credentials
|
||||||
|
may need to be refreshed setting the TokenProvider field of AssumeRoleProvider
|
||||||
|
will allow the credential provider to prompt for new MFA token code when the
|
||||||
|
role's credentials need to be refreshed.
|
||||||
|
|
||||||
|
The StdinTokenProvider function is available to prompt on stdin to retrieve
|
||||||
|
the MFA token code from the user. You can also implement custom prompts by
|
||||||
|
satisfing the TokenProvider function signature.
|
||||||
|
|
||||||
|
Using StdinTokenProvider with multiple AssumeRoleProviders, or Credentials will
|
||||||
|
have undesirable results as the StdinTokenProvider will not be synchronized. A
|
||||||
|
single Credentials with an AssumeRoleProvider can be shared safely.
|
||||||
|
|
||||||
|
// Create the credentials from AssumeRoleProvider to assume the role
|
||||||
|
// referenced by the "myRoleARN" ARN. Prompting for MFA token from stdin.
|
||||||
|
creds := stscreds.NewCredentials(sess, "myRoleArn", func(p *stscreds.AssumeRoleProvider) {
|
||||||
|
p.SerialNumber = aws.String("myTokenSerialNumber")
|
||||||
|
p.TokenProvider = stscreds.StdinTokenProvider
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create service client value configured for credentials
|
||||||
|
// from assumed role.
|
||||||
|
svc := s3.New(sess, &aws.Config{Credentials: creds})
|
||||||
|
|
||||||
|
*/
|
||||||
|
package stscreds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/service/sts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StdinTokenProvider will prompt on stdout and read from stdin for a string value.
|
||||||
|
// An error is returned if reading from stdin fails.
|
||||||
|
//
|
||||||
|
// Use this function go read MFA tokens from stdin. The function makes no attempt
|
||||||
|
// to make atomic prompts from stdin across multiple gorouties.
|
||||||
|
//
|
||||||
|
// Using StdinTokenProvider with multiple AssumeRoleProviders, or Credentials will
|
||||||
|
// have undesirable results as the StdinTokenProvider will not be synchronized. A
|
||||||
|
// single Credentials with an AssumeRoleProvider can be shared safely
|
||||||
|
//
|
||||||
|
// Will wait forever until something is provided on the stdin.
|
||||||
|
func StdinTokenProvider() (string, error) {
|
||||||
|
var v string
|
||||||
|
fmt.Printf("Assume Role MFA token code: ")
|
||||||
|
_, err := fmt.Scanln(&v)
|
||||||
|
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderName provides a name of AssumeRole provider
|
||||||
|
const ProviderName = "AssumeRoleProvider"
|
||||||
|
|
||||||
|
// AssumeRoler represents the minimal subset of the STS client API used by this provider.
|
||||||
|
type AssumeRoler interface {
|
||||||
|
AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultDuration is the default amount of time in minutes that the credentials
|
||||||
|
// will be valid for.
|
||||||
|
var DefaultDuration = time.Duration(15) * time.Minute
|
||||||
|
|
||||||
|
// AssumeRoleProvider retrieves temporary credentials from the STS service, and
|
||||||
|
// keeps track of their expiration time.
|
||||||
|
//
|
||||||
|
// This credential provider will be used by the SDKs default credential change
|
||||||
|
// when shared configuration is enabled, and the shared config or shared credentials
|
||||||
|
// file configure assume role. See Session docs for how to do this.
|
||||||
|
//
|
||||||
|
// AssumeRoleProvider does not provide any synchronization and it is not safe
|
||||||
|
// to share this value across multiple Credentials, Sessions, or service clients
|
||||||
|
// without also sharing the same Credentials instance.
|
||||||
|
type AssumeRoleProvider struct {
|
||||||
|
credentials.Expiry
|
||||||
|
|
||||||
|
// STS client to make assume role request with.
|
||||||
|
Client AssumeRoler
|
||||||
|
|
||||||
|
// Role to be assumed.
|
||||||
|
RoleARN string
|
||||||
|
|
||||||
|
// Session name, if you wish to reuse the credentials elsewhere.
|
||||||
|
RoleSessionName string
|
||||||
|
|
||||||
|
// Expiry duration of the STS credentials. Defaults to 15 minutes if not set.
|
||||||
|
Duration time.Duration
|
||||||
|
|
||||||
|
// Optional ExternalID to pass along, defaults to nil if not set.
|
||||||
|
ExternalID *string
|
||||||
|
|
||||||
|
// The policy plain text must be 2048 bytes or shorter. However, an internal
|
||||||
|
// conversion compresses it into a packed binary format with a separate limit.
|
||||||
|
// The PackedPolicySize response element indicates by percentage how close to
|
||||||
|
// the upper size limit the policy is, with 100% equaling the maximum allowed
|
||||||
|
// size.
|
||||||
|
Policy *string
|
||||||
|
|
||||||
|
// The identification number of the MFA device that is associated with the user
|
||||||
|
// who is making the AssumeRole call. Specify this value if the trust policy
|
||||||
|
// of the role being assumed includes a condition that requires MFA authentication.
|
||||||
|
// The value is either the serial number for a hardware device (such as GAHT12345678)
|
||||||
|
// or an Amazon Resource Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user).
|
||||||
|
SerialNumber *string
|
||||||
|
|
||||||
|
// The value provided by the MFA device, if the trust policy of the role being
|
||||||
|
// assumed requires MFA (that is, if the policy includes a condition that tests
|
||||||
|
// for MFA). If the role being assumed requires MFA and if the TokenCode value
|
||||||
|
// is missing or expired, the AssumeRole call returns an "access denied" error.
|
||||||
|
//
|
||||||
|
// If SerialNumber is set and neither TokenCode nor TokenProvider are also
|
||||||
|
// set an error will be returned.
|
||||||
|
TokenCode *string
|
||||||
|
|
||||||
|
// Async method of providing MFA token code for assuming an IAM role with MFA.
|
||||||
|
// The value returned by the function will be used as the TokenCode in the Retrieve
|
||||||
|
// call. See StdinTokenProvider for a provider that prompts and reads from stdin.
|
||||||
|
//
|
||||||
|
// This token provider will be called when ever the assumed role's
|
||||||
|
// credentials need to be refreshed when SerialNumber is also set and
|
||||||
|
// TokenCode is not set.
|
||||||
|
//
|
||||||
|
// If both TokenCode and TokenProvider is set, TokenProvider will be used and
|
||||||
|
// TokenCode is ignored.
|
||||||
|
TokenProvider func() (string, error)
|
||||||
|
|
||||||
|
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
||||||
|
// the credentials actually expiring. This is beneficial so race conditions
|
||||||
|
// with expiring credentials do not cause request to fail unexpectedly
|
||||||
|
// due to ExpiredTokenException exceptions.
|
||||||
|
//
|
||||||
|
// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
|
||||||
|
// 10 seconds before the credentials are actually expired.
|
||||||
|
//
|
||||||
|
// If ExpiryWindow is 0 or less it will be ignored.
|
||||||
|
ExpiryWindow time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCredentials returns a pointer to a new Credentials object wrapping the
|
||||||
|
// AssumeRoleProvider. The credentials will expire every 15 minutes and the
|
||||||
|
// role will be named after a nanosecond timestamp of this operation.
|
||||||
|
//
|
||||||
|
// Takes a Config provider to create the STS client. The ConfigProvider is
|
||||||
|
// satisfied by the session.Session type.
|
||||||
|
//
|
||||||
|
// It is safe to share the returned Credentials with multiple Sessions and
|
||||||
|
// service clients. All access to the credentials and refreshing them
|
||||||
|
// will be synchronized.
|
||||||
|
func NewCredentials(c client.ConfigProvider, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: sts.New(c),
|
||||||
|
RoleARN: roleARN,
|
||||||
|
Duration: DefaultDuration,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
option(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentials.NewCredentials(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping the
|
||||||
|
// AssumeRoleProvider. The credentials will expire every 15 minutes and the
|
||||||
|
// role will be named after a nanosecond timestamp of this operation.
|
||||||
|
//
|
||||||
|
// Takes an AssumeRoler which can be satisfied by the STS client.
|
||||||
|
//
|
||||||
|
// It is safe to share the returned Credentials with multiple Sessions and
|
||||||
|
// service clients. All access to the credentials and refreshing them
|
||||||
|
// will be synchronized.
|
||||||
|
func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: svc,
|
||||||
|
RoleARN: roleARN,
|
||||||
|
Duration: DefaultDuration,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
option(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentials.NewCredentials(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve generates a new set of temporary credentials using STS.
|
||||||
|
func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
|
||||||
|
|
||||||
|
// Apply defaults where parameters are not set.
|
||||||
|
if p.RoleSessionName == "" {
|
||||||
|
// Try to work out a role name that will hopefully end up unique.
|
||||||
|
p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano())
|
||||||
|
}
|
||||||
|
if p.Duration == 0 {
|
||||||
|
// Expire as often as AWS permits.
|
||||||
|
p.Duration = DefaultDuration
|
||||||
|
}
|
||||||
|
input := &sts.AssumeRoleInput{
|
||||||
|
DurationSeconds: aws.Int64(int64(p.Duration / time.Second)),
|
||||||
|
RoleArn: aws.String(p.RoleARN),
|
||||||
|
RoleSessionName: aws.String(p.RoleSessionName),
|
||||||
|
ExternalId: p.ExternalID,
|
||||||
|
}
|
||||||
|
if p.Policy != nil {
|
||||||
|
input.Policy = p.Policy
|
||||||
|
}
|
||||||
|
if p.SerialNumber != nil {
|
||||||
|
if p.TokenCode != nil {
|
||||||
|
input.SerialNumber = p.SerialNumber
|
||||||
|
input.TokenCode = p.TokenCode
|
||||||
|
} else if p.TokenProvider != nil {
|
||||||
|
input.SerialNumber = p.SerialNumber
|
||||||
|
code, err := p.TokenProvider()
|
||||||
|
if err != nil {
|
||||||
|
return credentials.Value{ProviderName: ProviderName}, err
|
||||||
|
}
|
||||||
|
input.TokenCode = aws.String(code)
|
||||||
|
} else {
|
||||||
|
return credentials.Value{ProviderName: ProviderName},
|
||||||
|
awserr.New("AssumeRoleTokenNotAvailable",
|
||||||
|
"assume role with MFA enabled, but neither TokenCode nor TokenProvider are set", nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
roleOutput, err := p.Client.AssumeRole(input)
|
||||||
|
if err != nil {
|
||||||
|
return credentials.Value{ProviderName: ProviderName}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will proactively generate new credentials before they expire.
|
||||||
|
p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow)
|
||||||
|
|
||||||
|
return credentials.Value{
|
||||||
|
AccessKeyID: *roleOutput.Credentials.AccessKeyId,
|
||||||
|
SecretAccessKey: *roleOutput.Credentials.SecretAccessKey,
|
||||||
|
SessionToken: *roleOutput.Credentials.SessionToken,
|
||||||
|
ProviderName: ProviderName,
|
||||||
|
}, nil
|
||||||
|
}
|
150
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go
generated
vendored
Normal file
150
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go
generated
vendored
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
package stscreds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/sts"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stubSTS struct {
|
||||||
|
TestInput func(*sts.AssumeRoleInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stubSTS) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
|
||||||
|
if s.TestInput != nil {
|
||||||
|
s.TestInput(input)
|
||||||
|
}
|
||||||
|
expiry := time.Now().Add(60 * time.Minute)
|
||||||
|
return &sts.AssumeRoleOutput{
|
||||||
|
Credentials: &sts.Credentials{
|
||||||
|
// Just reflect the role arn to the provider.
|
||||||
|
AccessKeyId: input.RoleArn,
|
||||||
|
SecretAccessKey: aws.String("assumedSecretAccessKey"),
|
||||||
|
SessionToken: aws.String("assumedSessionToken"),
|
||||||
|
Expiration: &expiry,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssumeRoleProvider(t *testing.T) {
|
||||||
|
stub := &stubSTS{}
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: stub,
|
||||||
|
RoleARN: "roleARN",
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "roleARN", creds.AccessKeyID, "Expect access key ID to be reflected role ARN")
|
||||||
|
assert.Equal(t, "assumedSecretAccessKey", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "assumedSessionToken", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssumeRoleProvider_WithTokenCode(t *testing.T) {
|
||||||
|
stub := &stubSTS{
|
||||||
|
TestInput: func(in *sts.AssumeRoleInput) {
|
||||||
|
assert.Equal(t, "0123456789", *in.SerialNumber)
|
||||||
|
assert.Equal(t, "code", *in.TokenCode)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: stub,
|
||||||
|
RoleARN: "roleARN",
|
||||||
|
SerialNumber: aws.String("0123456789"),
|
||||||
|
TokenCode: aws.String("code"),
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "roleARN", creds.AccessKeyID, "Expect access key ID to be reflected role ARN")
|
||||||
|
assert.Equal(t, "assumedSecretAccessKey", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "assumedSessionToken", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssumeRoleProvider_WithTokenProvider(t *testing.T) {
|
||||||
|
stub := &stubSTS{
|
||||||
|
TestInput: func(in *sts.AssumeRoleInput) {
|
||||||
|
assert.Equal(t, "0123456789", *in.SerialNumber)
|
||||||
|
assert.Equal(t, "code", *in.TokenCode)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: stub,
|
||||||
|
RoleARN: "roleARN",
|
||||||
|
SerialNumber: aws.String("0123456789"),
|
||||||
|
TokenProvider: func() (string, error) {
|
||||||
|
return "code", nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Nil(t, err, "Expect no error")
|
||||||
|
|
||||||
|
assert.Equal(t, "roleARN", creds.AccessKeyID, "Expect access key ID to be reflected role ARN")
|
||||||
|
assert.Equal(t, "assumedSecretAccessKey", creds.SecretAccessKey, "Expect secret access key to match")
|
||||||
|
assert.Equal(t, "assumedSessionToken", creds.SessionToken, "Expect session token to match")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssumeRoleProvider_WithTokenProviderError(t *testing.T) {
|
||||||
|
stub := &stubSTS{
|
||||||
|
TestInput: func(in *sts.AssumeRoleInput) {
|
||||||
|
assert.Fail(t, "API request should not of been called")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: stub,
|
||||||
|
RoleARN: "roleARN",
|
||||||
|
SerialNumber: aws.String("0123456789"),
|
||||||
|
TokenProvider: func() (string, error) {
|
||||||
|
return "", fmt.Errorf("error occurred")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
assert.Empty(t, creds.AccessKeyID)
|
||||||
|
assert.Empty(t, creds.SecretAccessKey)
|
||||||
|
assert.Empty(t, creds.SessionToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssumeRoleProvider_MFAWithNoToken(t *testing.T) {
|
||||||
|
stub := &stubSTS{
|
||||||
|
TestInput: func(in *sts.AssumeRoleInput) {
|
||||||
|
assert.Fail(t, "API request should not of been called")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: stub,
|
||||||
|
RoleARN: "roleARN",
|
||||||
|
SerialNumber: aws.String("0123456789"),
|
||||||
|
}
|
||||||
|
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
assert.Empty(t, creds.AccessKeyID)
|
||||||
|
assert.Empty(t, creds.SecretAccessKey)
|
||||||
|
assert.Empty(t, creds.SessionToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAssumeRoleProvider(b *testing.B) {
|
||||||
|
stub := &stubSTS{}
|
||||||
|
p := &AssumeRoleProvider{
|
||||||
|
Client: stub,
|
||||||
|
RoleARN: "roleARN",
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if _, err := p.Retrieve(); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
174
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
174
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
|
@ -1,39 +1,163 @@
|
||||||
|
// Package defaults is a collection of helpers to retrieve the SDK's default
|
||||||
|
// configuration and handlers.
|
||||||
|
//
|
||||||
|
// Generally this package shouldn't be used directly, but session.Session
|
||||||
|
// instead. This package is useful when you need to reset the defaults
|
||||||
|
// of a session or service client to the SDK defaults before setting
|
||||||
|
// additional parameters.
|
||||||
package defaults
|
package defaults
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/corehandlers"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/endpoints"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultChainCredentials is a Credentials which will find the first available
|
// A Defaults provides a collection of default values for SDK clients.
|
||||||
// credentials Value from the list of Providers.
|
type Defaults struct {
|
||||||
//
|
Config *aws.Config
|
||||||
// This should be used in the default case. Once the type of credentials are
|
Handlers request.Handlers
|
||||||
// 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.
|
// Get returns the SDK's default values with Config and handlers pre-configured.
|
||||||
// By default, all clients use this structure for initialization options unless
|
func Get() Defaults {
|
||||||
// a custom configuration object is passed in.
|
cfg := Config()
|
||||||
|
handlers := Handlers()
|
||||||
|
cfg.Credentials = CredChain(cfg, handlers)
|
||||||
|
|
||||||
|
return Defaults{
|
||||||
|
Config: cfg,
|
||||||
|
Handlers: handlers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config returns the default configuration without credentials.
|
||||||
|
// To retrieve a config with credentials also included use
|
||||||
|
// `defaults.Get().Config` instead.
|
||||||
//
|
//
|
||||||
// You may modify this global structure to change all default configuration
|
// Generally you shouldn't need to use this method directly, but
|
||||||
// in the SDK. Note that configuration options are copied by value, so any
|
// is available if you need to reset the configuration of an
|
||||||
// modifications must happen before constructing a client.
|
// existing service client or session.
|
||||||
var DefaultConfig = aws.NewConfig().
|
func Config() *aws.Config {
|
||||||
WithCredentials(DefaultChainCredentials).
|
return aws.NewConfig().
|
||||||
WithRegion(os.Getenv("AWS_REGION")).
|
WithCredentials(credentials.AnonymousCredentials).
|
||||||
WithHTTPClient(http.DefaultClient).
|
WithRegion(os.Getenv("AWS_REGION")).
|
||||||
WithMaxRetries(aws.DefaultRetries).
|
WithHTTPClient(http.DefaultClient).
|
||||||
WithLogger(aws.NewDefaultLogger()).
|
WithMaxRetries(aws.UseServiceDefaultRetries).
|
||||||
WithLogLevel(aws.LogOff).
|
WithLogger(aws.NewDefaultLogger()).
|
||||||
WithSleepDelay(time.Sleep)
|
WithLogLevel(aws.LogOff).
|
||||||
|
WithEndpointResolver(endpoints.DefaultResolver())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handlers returns the default request handlers.
|
||||||
|
//
|
||||||
|
// Generally you shouldn't need to use this method directly, but
|
||||||
|
// is available if you need to reset the request handlers of an
|
||||||
|
// existing service client or session.
|
||||||
|
func Handlers() request.Handlers {
|
||||||
|
var handlers request.Handlers
|
||||||
|
|
||||||
|
handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
|
||||||
|
handlers.Validate.AfterEachFn = request.HandlerListStopOnError
|
||||||
|
handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
|
||||||
|
handlers.Build.AfterEachFn = request.HandlerListStopOnError
|
||||||
|
handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
|
||||||
|
handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
|
||||||
|
handlers.Send.PushBackNamed(corehandlers.SendHandler)
|
||||||
|
handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
|
||||||
|
handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
|
||||||
|
|
||||||
|
return handlers
|
||||||
|
}
|
||||||
|
|
||||||
|
// CredChain returns the default credential chain.
|
||||||
|
//
|
||||||
|
// Generally you shouldn't need to use this method directly, but
|
||||||
|
// is available if you need to reset the credentials of an
|
||||||
|
// existing service client or session's Config.
|
||||||
|
func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
|
||||||
|
return credentials.NewCredentials(&credentials.ChainProvider{
|
||||||
|
VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
|
||||||
|
Providers: []credentials.Provider{
|
||||||
|
&credentials.EnvProvider{},
|
||||||
|
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
|
||||||
|
RemoteCredProvider(*cfg, handlers),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
httpProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
|
||||||
|
ecsCredsProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemoteCredProvider returns a credentials provider for the default remote
|
||||||
|
// endpoints such as EC2 or ECS Roles.
|
||||||
|
func RemoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
|
||||||
|
if u := os.Getenv(httpProviderEnvVar); len(u) > 0 {
|
||||||
|
return localHTTPCredProvider(cfg, handlers, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
if uri := os.Getenv(ecsCredsProviderEnvVar); len(uri) > 0 {
|
||||||
|
u := fmt.Sprintf("http://169.254.170.2%s", uri)
|
||||||
|
return httpCredProvider(cfg, handlers, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ec2RoleProvider(cfg, handlers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func localHTTPCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
|
||||||
|
var errMsg string
|
||||||
|
|
||||||
|
parsed, err := url.Parse(u)
|
||||||
|
if err != nil {
|
||||||
|
errMsg = fmt.Sprintf("invalid URL, %v", err)
|
||||||
|
} else if host := aws.URLHostname(parsed); !(host == "localhost" || host == "127.0.0.1") {
|
||||||
|
errMsg = fmt.Sprintf("invalid host address, %q, only localhost and 127.0.0.1 are valid.", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errMsg) > 0 {
|
||||||
|
if cfg.Logger != nil {
|
||||||
|
cfg.Logger.Log("Ignoring, HTTP credential provider", errMsg, err)
|
||||||
|
}
|
||||||
|
return credentials.ErrorProvider{
|
||||||
|
Err: awserr.New("CredentialsEndpointError", errMsg, err),
|
||||||
|
ProviderName: endpointcreds.ProviderName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpCredProvider(cfg, handlers, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func httpCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
|
||||||
|
return endpointcreds.NewProviderClient(cfg, handlers, u,
|
||||||
|
func(p *endpointcreds.Provider) {
|
||||||
|
p.ExpiryWindow = 5 * time.Minute
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ec2RoleProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
|
||||||
|
resolver := cfg.EndpointResolver
|
||||||
|
if resolver == nil {
|
||||||
|
resolver = endpoints.DefaultResolver()
|
||||||
|
}
|
||||||
|
|
||||||
|
e, _ := resolver.EndpointFor(endpoints.Ec2metadataServiceID, "")
|
||||||
|
return &ec2rolecreds.EC2RoleProvider{
|
||||||
|
Client: ec2metadata.NewClient(cfg, handlers, e.URL, e.SigningRegion),
|
||||||
|
ExpiryWindow: 5 * time.Minute,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
88
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go
generated
vendored
Normal file
88
vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
package defaults
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHTTPCredProvider(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Host string
|
||||||
|
Fail bool
|
||||||
|
}{
|
||||||
|
{"localhost", false}, {"127.0.0.1", false},
|
||||||
|
{"www.example.com", true}, {"169.254.170.2", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
defer os.Clearenv()
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
u := fmt.Sprintf("http://%s/abc/123", c.Host)
|
||||||
|
os.Setenv(httpProviderEnvVar, u)
|
||||||
|
|
||||||
|
provider := RemoteCredProvider(aws.Config{}, request.Handlers{})
|
||||||
|
if provider == nil {
|
||||||
|
t.Fatalf("%d, expect provider not to be nil, but was", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Fail {
|
||||||
|
creds, err := provider.Retrieve()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("%d, expect error but got none", i)
|
||||||
|
} else {
|
||||||
|
aerr := err.(awserr.Error)
|
||||||
|
if e, a := "CredentialsEndpointError", aerr.Code(); e != a {
|
||||||
|
t.Errorf("%d, expect %s error code, got %s", i, e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e, a := endpointcreds.ProviderName, creds.ProviderName; e != a {
|
||||||
|
t.Errorf("%d, expect %s provider name got %s", i, e, a)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
httpProvider := provider.(*endpointcreds.Provider)
|
||||||
|
if e, a := u, httpProvider.Client.Endpoint; e != a {
|
||||||
|
t.Errorf("%d, expect %q endpoint, got %q", i, e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestECSCredProvider(t *testing.T) {
|
||||||
|
defer os.Clearenv()
|
||||||
|
os.Setenv(ecsCredsProviderEnvVar, "/abc/123")
|
||||||
|
|
||||||
|
provider := RemoteCredProvider(aws.Config{}, request.Handlers{})
|
||||||
|
if provider == nil {
|
||||||
|
t.Fatalf("expect provider not to be nil, but was")
|
||||||
|
}
|
||||||
|
|
||||||
|
httpProvider := provider.(*endpointcreds.Provider)
|
||||||
|
if httpProvider == nil {
|
||||||
|
t.Fatalf("expect provider not to be nil, but was")
|
||||||
|
}
|
||||||
|
if e, a := "http://169.254.170.2/abc/123", httpProvider.Client.Endpoint; e != a {
|
||||||
|
t.Errorf("expect %q endpoint, got %q", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultEC2RoleProvider(t *testing.T) {
|
||||||
|
provider := RemoteCredProvider(aws.Config{}, request.Handlers{})
|
||||||
|
if provider == nil {
|
||||||
|
t.Fatalf("expect provider not to be nil, but was")
|
||||||
|
}
|
||||||
|
|
||||||
|
ec2Provider := provider.(*ec2rolecreds.EC2RoleProvider)
|
||||||
|
if ec2Provider == nil {
|
||||||
|
t.Fatalf("expect provider not to be nil, but was")
|
||||||
|
}
|
||||||
|
if e, a := "http://169.254.169.254/latest", ec2Provider.Client.Endpoint; e != a {
|
||||||
|
t.Errorf("expect %q endpoint, got %q", e, a)
|
||||||
|
}
|
||||||
|
}
|
27
vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go
generated
vendored
Normal file
27
vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package defaults
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aws/aws-sdk-go/internal/shareddefaults"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SharedCredentialsFilename returns the SDK's default file path
|
||||||
|
// for the shared credentials file.
|
||||||
|
//
|
||||||
|
// Builds the shared config file path based on the OS's platform.
|
||||||
|
//
|
||||||
|
// - Linux/Unix: $HOME/.aws/credentials
|
||||||
|
// - Windows: %USERPROFILE%\.aws\credentials
|
||||||
|
func SharedCredentialsFilename() string {
|
||||||
|
return shareddefaults.SharedCredentialsFilename()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SharedConfigFilename returns the SDK's default file path for
|
||||||
|
// the shared config file.
|
||||||
|
//
|
||||||
|
// Builds the shared config file path based on the OS's platform.
|
||||||
|
//
|
||||||
|
// - Linux/Unix: $HOME/.aws/config
|
||||||
|
// - Windows: %USERPROFILE%\.aws\config
|
||||||
|
func SharedConfigFilename() string {
|
||||||
|
return shareddefaults.SharedConfigFilename()
|
||||||
|
}
|
56
vendor/github.com/aws/aws-sdk-go/aws/doc.go
generated
vendored
Normal file
56
vendor/github.com/aws/aws-sdk-go/aws/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// Package aws provides the core SDK's utilities and shared types. Use this package's
|
||||||
|
// utilities to simplify setting and reading API operations parameters.
|
||||||
|
//
|
||||||
|
// Value and Pointer Conversion Utilities
|
||||||
|
//
|
||||||
|
// This package includes a helper conversion utility for each scalar type the SDK's
|
||||||
|
// API use. These utilities make getting a pointer of the scalar, and dereferencing
|
||||||
|
// a pointer easier.
|
||||||
|
//
|
||||||
|
// Each conversion utility comes in two forms. Value to Pointer and Pointer to Value.
|
||||||
|
// The Pointer to value will safely dereference the pointer and return its value.
|
||||||
|
// If the pointer was nil, the scalar's zero value will be returned.
|
||||||
|
//
|
||||||
|
// The value to pointer functions will be named after the scalar type. So get a
|
||||||
|
// *string from a string value use the "String" function. This makes it easy to
|
||||||
|
// to get pointer of a literal string value, because getting the address of a
|
||||||
|
// literal requires assigning the value to a variable first.
|
||||||
|
//
|
||||||
|
// var strPtr *string
|
||||||
|
//
|
||||||
|
// // Without the SDK's conversion functions
|
||||||
|
// str := "my string"
|
||||||
|
// strPtr = &str
|
||||||
|
//
|
||||||
|
// // With the SDK's conversion functions
|
||||||
|
// strPtr = aws.String("my string")
|
||||||
|
//
|
||||||
|
// // Convert *string to string value
|
||||||
|
// str = aws.StringValue(strPtr)
|
||||||
|
//
|
||||||
|
// In addition to scalars the aws package also includes conversion utilities for
|
||||||
|
// map and slice for commonly types used in API parameters. The map and slice
|
||||||
|
// conversion functions use similar naming pattern as the scalar conversion
|
||||||
|
// functions.
|
||||||
|
//
|
||||||
|
// var strPtrs []*string
|
||||||
|
// var strs []string = []string{"Go", "Gophers", "Go"}
|
||||||
|
//
|
||||||
|
// // Convert []string to []*string
|
||||||
|
// strPtrs = aws.StringSlice(strs)
|
||||||
|
//
|
||||||
|
// // Convert []*string to []string
|
||||||
|
// strs = aws.StringValueSlice(strPtrs)
|
||||||
|
//
|
||||||
|
// SDK Default HTTP Client
|
||||||
|
//
|
||||||
|
// The SDK will use the http.DefaultClient if a HTTP client is not provided to
|
||||||
|
// the SDK's Session, or service client constructor. This means that if the
|
||||||
|
// http.DefaultClient is modified by other components of your application the
|
||||||
|
// modifications will be picked up by the SDK as well.
|
||||||
|
//
|
||||||
|
// In some cases this might be intended, but it is a better practice to create
|
||||||
|
// a custom HTTP Client to share explicitly through your application. You can
|
||||||
|
// configure the SDK to use the custom HTTP Client by setting the HTTPClient
|
||||||
|
// value of the SDK's Config type when creating a Session or service client.
|
||||||
|
package aws
|
129
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
generated
vendored
129
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
generated
vendored
|
@ -1,13 +1,21 @@
|
||||||
package ec2metadata
|
package ec2metadata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetMetadata uses the path provided to request
|
// GetMetadata uses the path provided to request information from the EC2
|
||||||
func (c *Client) GetMetadata(p string) (string, error) {
|
// instance metdata service. The content will be returned as a string, or
|
||||||
|
// error if the request failed.
|
||||||
|
func (c *EC2Metadata) GetMetadata(p string) (string, error) {
|
||||||
op := &request.Operation{
|
op := &request.Operation{
|
||||||
Name: "GetMetadata",
|
Name: "GetMetadata",
|
||||||
HTTPMethod: "GET",
|
HTTPMethod: "GET",
|
||||||
|
@ -15,13 +23,96 @@ func (c *Client) GetMetadata(p string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
output := &metadataOutput{}
|
output := &metadataOutput{}
|
||||||
req := request.New(c.Service.ServiceInfo, c.Service.Handlers, c.Service.Retryer, op, nil, output)
|
req := c.NewRequest(op, nil, output)
|
||||||
|
|
||||||
return output.Content, req.Send()
|
return output.Content, req.Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserData returns the userdata that was configured for the service. If
|
||||||
|
// there is no user-data setup for the EC2 instance a "NotFoundError" error
|
||||||
|
// code will be returned.
|
||||||
|
func (c *EC2Metadata) GetUserData() (string, error) {
|
||||||
|
op := &request.Operation{
|
||||||
|
Name: "GetUserData",
|
||||||
|
HTTPMethod: "GET",
|
||||||
|
HTTPPath: path.Join("/", "user-data"),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := &metadataOutput{}
|
||||||
|
req := c.NewRequest(op, nil, output)
|
||||||
|
req.Handlers.UnmarshalError.PushBack(func(r *request.Request) {
|
||||||
|
if r.HTTPResponse.StatusCode == http.StatusNotFound {
|
||||||
|
r.Error = awserr.New("NotFoundError", "user-data not found", r.Error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return output.Content, req.Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDynamicData uses the path provided to request information from the EC2
|
||||||
|
// instance metadata service for dynamic data. The content will be returned
|
||||||
|
// as a string, or error if the request failed.
|
||||||
|
func (c *EC2Metadata) GetDynamicData(p string) (string, error) {
|
||||||
|
op := &request.Operation{
|
||||||
|
Name: "GetDynamicData",
|
||||||
|
HTTPMethod: "GET",
|
||||||
|
HTTPPath: path.Join("/", "dynamic", p),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := &metadataOutput{}
|
||||||
|
req := c.NewRequest(op, nil, output)
|
||||||
|
|
||||||
|
return output.Content, req.Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInstanceIdentityDocument retrieves an identity document describing an
|
||||||
|
// instance. Error is returned if the request fails or is unable to parse
|
||||||
|
// the response.
|
||||||
|
func (c *EC2Metadata) GetInstanceIdentityDocument() (EC2InstanceIdentityDocument, error) {
|
||||||
|
resp, err := c.GetDynamicData("instance-identity/document")
|
||||||
|
if err != nil {
|
||||||
|
return EC2InstanceIdentityDocument{},
|
||||||
|
awserr.New("EC2MetadataRequestError",
|
||||||
|
"failed to get EC2 instance identity document", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
doc := EC2InstanceIdentityDocument{}
|
||||||
|
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&doc); err != nil {
|
||||||
|
return EC2InstanceIdentityDocument{},
|
||||||
|
awserr.New("SerializationError",
|
||||||
|
"failed to decode EC2 instance identity document", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IAMInfo retrieves IAM info from the metadata API
|
||||||
|
func (c *EC2Metadata) IAMInfo() (EC2IAMInfo, error) {
|
||||||
|
resp, err := c.GetMetadata("iam/info")
|
||||||
|
if err != nil {
|
||||||
|
return EC2IAMInfo{},
|
||||||
|
awserr.New("EC2MetadataRequestError",
|
||||||
|
"failed to get EC2 IAM info", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info := EC2IAMInfo{}
|
||||||
|
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&info); err != nil {
|
||||||
|
return EC2IAMInfo{},
|
||||||
|
awserr.New("SerializationError",
|
||||||
|
"failed to decode EC2 IAM info", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Code != "Success" {
|
||||||
|
errMsg := fmt.Sprintf("failed to get EC2 IAM Info (%s)", info.Code)
|
||||||
|
return EC2IAMInfo{},
|
||||||
|
awserr.New("EC2MetadataError", errMsg, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Region returns the region the instance is running in.
|
// Region returns the region the instance is running in.
|
||||||
func (c *Client) Region() (string, error) {
|
func (c *EC2Metadata) Region() (string, error) {
|
||||||
resp, err := c.GetMetadata("placement/availability-zone")
|
resp, err := c.GetMetadata("placement/availability-zone")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -34,10 +125,38 @@ func (c *Client) Region() (string, error) {
|
||||||
// Available returns if the application has access to the EC2 Metadata service.
|
// 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
|
// Can be used to determine if application is running within an EC2 Instance and
|
||||||
// the metadata service is available.
|
// the metadata service is available.
|
||||||
func (c *Client) Available() bool {
|
func (c *EC2Metadata) Available() bool {
|
||||||
if _, err := c.GetMetadata("instance-id"); err != nil {
|
if _, err := c.GetMetadata("instance-id"); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An EC2IAMInfo provides the shape for unmarshaling
|
||||||
|
// an IAM info from the metadata API
|
||||||
|
type EC2IAMInfo struct {
|
||||||
|
Code string
|
||||||
|
LastUpdated time.Time
|
||||||
|
InstanceProfileArn string
|
||||||
|
InstanceProfileID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// An EC2InstanceIdentityDocument provides the shape for unmarshaling
|
||||||
|
// an instance identity document
|
||||||
|
type EC2InstanceIdentityDocument struct {
|
||||||
|
DevpayProductCodes []string `json:"devpayProductCodes"`
|
||||||
|
AvailabilityZone string `json:"availabilityZone"`
|
||||||
|
PrivateIP string `json:"privateIp"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
InstanceID string `json:"instanceId"`
|
||||||
|
BillingProducts []string `json:"billingProducts"`
|
||||||
|
InstanceType string `json:"instanceType"`
|
||||||
|
AccountID string `json:"accountId"`
|
||||||
|
PendingTime time.Time `json:"pendingTime"`
|
||||||
|
ImageID string `json:"imageId"`
|
||||||
|
KernelID string `json:"kernelId"`
|
||||||
|
RamdiskID string `json:"ramdiskId"`
|
||||||
|
Architecture string `json:"architecture"`
|
||||||
|
}
|
||||||
|
|
289
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go
generated
vendored
Normal file
289
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go
generated
vendored
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
package ec2metadata_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||||
|
)
|
||||||
|
|
||||||
|
const instanceIdentityDocument = `{
|
||||||
|
"devpayProductCodes" : null,
|
||||||
|
"availabilityZone" : "us-east-1d",
|
||||||
|
"privateIp" : "10.158.112.84",
|
||||||
|
"version" : "2010-08-31",
|
||||||
|
"region" : "us-east-1",
|
||||||
|
"instanceId" : "i-1234567890abcdef0",
|
||||||
|
"billingProducts" : null,
|
||||||
|
"instanceType" : "t1.micro",
|
||||||
|
"accountId" : "123456789012",
|
||||||
|
"pendingTime" : "2015-11-19T16:32:11Z",
|
||||||
|
"imageId" : "ami-5fb8c835",
|
||||||
|
"kernelId" : "aki-919dcaf8",
|
||||||
|
"ramdiskId" : null,
|
||||||
|
"architecture" : "x86_64"
|
||||||
|
}`
|
||||||
|
|
||||||
|
const validIamInfo = `{
|
||||||
|
"Code" : "Success",
|
||||||
|
"LastUpdated" : "2016-03-17T12:27:32Z",
|
||||||
|
"InstanceProfileArn" : "arn:aws:iam::123456789012:instance-profile/my-instance-profile",
|
||||||
|
"InstanceProfileId" : "AIPAABCDEFGHIJKLMN123"
|
||||||
|
}`
|
||||||
|
|
||||||
|
const unsuccessfulIamInfo = `{
|
||||||
|
"Code" : "Failed",
|
||||||
|
"LastUpdated" : "2016-03-17T12:27:32Z",
|
||||||
|
"InstanceProfileArn" : "arn:aws:iam::123456789012:instance-profile/my-instance-profile",
|
||||||
|
"InstanceProfileId" : "AIPAABCDEFGHIJKLMN123"
|
||||||
|
}`
|
||||||
|
|
||||||
|
func initTestServer(path string, resp string) *httptest.Server {
|
||||||
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.RequestURI != path {
|
||||||
|
http.Error(w, "not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(resp))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEndpoint(t *testing.T) {
|
||||||
|
c := ec2metadata.New(unit.Session)
|
||||||
|
op := &request.Operation{
|
||||||
|
Name: "GetMetadata",
|
||||||
|
HTTPMethod: "GET",
|
||||||
|
HTTPPath: path.Join("/", "meta-data", "testpath"),
|
||||||
|
}
|
||||||
|
|
||||||
|
req := c.NewRequest(op, nil, nil)
|
||||||
|
if e, a := "http://169.254.169.254/latest", req.ClientInfo.Endpoint; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "http://169.254.169.254/latest/meta-data/testpath", req.HTTPRequest.URL.String(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetMetadata(t *testing.T) {
|
||||||
|
server := initTestServer(
|
||||||
|
"/latest/meta-data/some/path",
|
||||||
|
"success", // real response includes suffix
|
||||||
|
)
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
resp, err := c.GetMetadata("some/path")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if e, a := "success", resp; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUserData(t *testing.T) {
|
||||||
|
server := initTestServer(
|
||||||
|
"/latest/user-data",
|
||||||
|
"success", // real response includes suffix
|
||||||
|
)
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
resp, err := c.GetUserData()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if e, a := "success", resp; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUserData_Error(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
reader := strings.NewReader(`<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<title>404 - Not Found</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>404 - Not Found</h1>
|
||||||
|
</body>
|
||||||
|
</html>`)
|
||||||
|
w.Header().Set("Content-Type", "text/html")
|
||||||
|
w.Header().Set("Content-Length", fmt.Sprintf("%d", reader.Len()))
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
io.Copy(w, reader)
|
||||||
|
}))
|
||||||
|
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
resp, err := c.GetUserData()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expect error")
|
||||||
|
}
|
||||||
|
if len(resp) != 0 {
|
||||||
|
t.Errorf("expect empty, got %v", resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
aerr := err.(awserr.Error)
|
||||||
|
if e, a := "NotFoundError", aerr.Code(); e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetRegion(t *testing.T) {
|
||||||
|
server := initTestServer(
|
||||||
|
"/latest/meta-data/placement/availability-zone",
|
||||||
|
"us-west-2a", // real response includes suffix
|
||||||
|
)
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
region, err := c.Region()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if e, a := "us-west-2", region; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMetadataAvailable(t *testing.T) {
|
||||||
|
server := initTestServer(
|
||||||
|
"/latest/meta-data/instance-id",
|
||||||
|
"instance-id",
|
||||||
|
)
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
if !c.Available() {
|
||||||
|
t.Errorf("expect available")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMetadataIAMInfo_success(t *testing.T) {
|
||||||
|
server := initTestServer(
|
||||||
|
"/latest/meta-data/iam/info",
|
||||||
|
validIamInfo,
|
||||||
|
)
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
iamInfo, err := c.IAMInfo()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if e, a := "Success", iamInfo.Code; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "arn:aws:iam::123456789012:instance-profile/my-instance-profile", iamInfo.InstanceProfileArn; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "AIPAABCDEFGHIJKLMN123", iamInfo.InstanceProfileID; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMetadataIAMInfo_failure(t *testing.T) {
|
||||||
|
server := initTestServer(
|
||||||
|
"/latest/meta-data/iam/info",
|
||||||
|
unsuccessfulIamInfo,
|
||||||
|
)
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
iamInfo, err := c.IAMInfo()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expect error")
|
||||||
|
}
|
||||||
|
if e, a := "", iamInfo.Code; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "", iamInfo.InstanceProfileArn; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := "", iamInfo.InstanceProfileID; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMetadataNotAvailable(t *testing.T) {
|
||||||
|
c := ec2metadata.New(unit.Session)
|
||||||
|
c.Handlers.Send.Clear()
|
||||||
|
c.Handlers.Send.PushBack(func(r *request.Request) {
|
||||||
|
r.HTTPResponse = &http.Response{
|
||||||
|
StatusCode: int(0),
|
||||||
|
Status: http.StatusText(int(0)),
|
||||||
|
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
||||||
|
}
|
||||||
|
r.Error = awserr.New("RequestError", "send request failed", nil)
|
||||||
|
r.Retryable = aws.Bool(true) // network errors are retryable
|
||||||
|
})
|
||||||
|
|
||||||
|
if c.Available() {
|
||||||
|
t.Errorf("expect not available")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMetadataErrorResponse(t *testing.T) {
|
||||||
|
c := ec2metadata.New(unit.Session)
|
||||||
|
c.Handlers.Send.Clear()
|
||||||
|
c.Handlers.Send.PushBack(func(r *request.Request) {
|
||||||
|
r.HTTPResponse = &http.Response{
|
||||||
|
StatusCode: http.StatusBadRequest,
|
||||||
|
Status: http.StatusText(http.StatusBadRequest),
|
||||||
|
Body: ioutil.NopCloser(strings.NewReader("error message text")),
|
||||||
|
}
|
||||||
|
r.Retryable = aws.Bool(false) // network errors are retryable
|
||||||
|
})
|
||||||
|
|
||||||
|
data, err := c.GetMetadata("uri/path")
|
||||||
|
if len(data) != 0 {
|
||||||
|
t.Errorf("expect empty, got %v", data)
|
||||||
|
}
|
||||||
|
if e, a := "error message text", err.Error(); !strings.Contains(a, e) {
|
||||||
|
t.Errorf("expect %v to be in %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEC2RoleProviderInstanceIdentity(t *testing.T) {
|
||||||
|
server := initTestServer(
|
||||||
|
"/latest/dynamic/instance-identity/document",
|
||||||
|
instanceIdentityDocument,
|
||||||
|
)
|
||||||
|
defer server.Close()
|
||||||
|
c := ec2metadata.New(unit.Session, &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
|
||||||
|
|
||||||
|
doc, err := c.GetInstanceIdentityDocument()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expect no error, got %v", err)
|
||||||
|
}
|
||||||
|
if e, a := doc.AccountID, "123456789012"; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := doc.AvailabilityZone, "us-east-1d"; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
if e, a := doc.Region, "us-east-1"; e != a {
|
||||||
|
t.Errorf("expect %v, got %v", e, a)
|
||||||
|
}
|
||||||
|
}
|
169
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
generated
vendored
169
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
generated
vendored
|
@ -1,106 +1,90 @@
|
||||||
|
// Package ec2metadata provides the client for making API calls to the
|
||||||
|
// EC2 Metadata service.
|
||||||
package ec2metadata
|
package ec2metadata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/client"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
"github.com/aws/aws-sdk-go/aws/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
|
// ServiceName is the name of the service.
|
||||||
// attempt to retry a failed request before failing.
|
const ServiceName = "ec2metadata"
|
||||||
const DefaultRetries = 3
|
|
||||||
|
|
||||||
// A Config provides the configuration for the EC2 Metadata service.
|
// A EC2Metadata is an EC2 Metadata service Client.
|
||||||
type Config struct {
|
type EC2Metadata struct {
|
||||||
// An optional endpoint URL (hostname only or fully qualified URI)
|
*client.Client
|
||||||
// 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.
|
// New creates a new instance of the EC2Metadata client with a session.
|
||||||
type Client struct {
|
// This client is safe to use across multiple goroutines.
|
||||||
*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
|
// Example:
|
||||||
// client configuration `defaults.DefaultConfig`. Due to circular dependencies
|
// // Create a EC2Metadata client from just a session.
|
||||||
// with the defaults package and credentials EC2 Role Provider.
|
// svc := ec2metadata.New(mySession)
|
||||||
func New(config *Config) *Client {
|
//
|
||||||
service := &service.Service{
|
// // Create a EC2Metadata client with additional configuration
|
||||||
ServiceInfo: serviceinfo.ServiceInfo{
|
// svc := ec2metadata.New(mySession, aws.NewConfig().WithLogLevel(aws.LogDebugHTTPBody))
|
||||||
Config: copyConfig(config),
|
func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2Metadata {
|
||||||
ServiceName: "Client",
|
c := p.ClientConfig(ServiceName, cfgs...)
|
||||||
Endpoint: "http://169.254.169.254/latest",
|
return NewClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
|
||||||
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 {
|
// NewClient returns a new EC2Metadata client. Should be used to create
|
||||||
if config == nil {
|
// a client when not using a session. Generally using just New with a session
|
||||||
config = &Config{}
|
// is preferred.
|
||||||
}
|
//
|
||||||
c := &aws.Config{
|
// If an unmodified HTTP client is provided from the stdlib default, or no client
|
||||||
Credentials: credentials.AnonymousCredentials,
|
// the EC2RoleProvider's EC2Metadata HTTP client's timeout will be shortened.
|
||||||
Endpoint: config.Endpoint,
|
// To disable this set Config.EC2MetadataDisableTimeoutOverride to false. Enabled by default.
|
||||||
HTTPClient: config.HTTPClient,
|
func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string, opts ...func(*client.Client)) *EC2Metadata {
|
||||||
Logger: config.Logger,
|
if !aws.BoolValue(cfg.EC2MetadataDisableTimeoutOverride) && httpClientZero(cfg.HTTPClient) {
|
||||||
LogLevel: config.LogLevel,
|
// If the http client is unmodified and this feature is not disabled
|
||||||
MaxRetries: config.MaxRetries,
|
// set custom timeouts for EC2Metadata requests.
|
||||||
|
cfg.HTTPClient = &http.Client{
|
||||||
|
// use a shorter timeout than default because the metadata
|
||||||
|
// service is local if it is running, and to fail faster
|
||||||
|
// if not running on an ec2 instance.
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.HTTPClient == nil {
|
svc := &EC2Metadata{
|
||||||
c.HTTPClient = http.DefaultClient
|
Client: client.New(
|
||||||
}
|
cfg,
|
||||||
if c.Logger == nil {
|
metadata.ClientInfo{
|
||||||
c.Logger = aws.NewDefaultLogger()
|
ServiceName: ServiceName,
|
||||||
}
|
Endpoint: endpoint,
|
||||||
if c.LogLevel == nil {
|
APIVersion: "latest",
|
||||||
c.LogLevel = aws.LogLevel(aws.LogOff)
|
},
|
||||||
}
|
handlers,
|
||||||
if c.MaxRetries == nil {
|
),
|
||||||
c.MaxRetries = aws.Int(DefaultRetries)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
svc.Handlers.Unmarshal.PushBack(unmarshalHandler)
|
||||||
|
svc.Handlers.UnmarshalError.PushBack(unmarshalError)
|
||||||
|
svc.Handlers.Validate.Clear()
|
||||||
|
svc.Handlers.Validate.PushBack(validateEndpointHandler)
|
||||||
|
|
||||||
|
// Add additional options to the service config
|
||||||
|
for _, option := range opts {
|
||||||
|
option(svc.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
func httpClientZero(c *http.Client) bool {
|
||||||
|
return c == nil || (c.Transport == nil && c.CheckRedirect == nil && c.Jar == nil && c.Timeout == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
type metadataOutput struct {
|
type metadataOutput struct {
|
||||||
|
@ -109,27 +93,32 @@ type metadataOutput struct {
|
||||||
|
|
||||||
func unmarshalHandler(r *request.Request) {
|
func unmarshalHandler(r *request.Request) {
|
||||||
defer r.HTTPResponse.Body.Close()
|
defer r.HTTPResponse.Body.Close()
|
||||||
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
b := &bytes.Buffer{}
|
||||||
if err != nil {
|
if _, err := io.Copy(b, r.HTTPResponse.Body); err != nil {
|
||||||
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err)
|
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := r.Data.(*metadataOutput)
|
if data, ok := r.Data.(*metadataOutput); ok {
|
||||||
data.Content = string(b)
|
data.Content = b.String()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalError(r *request.Request) {
|
func unmarshalError(r *request.Request) {
|
||||||
defer r.HTTPResponse.Body.Close()
|
defer r.HTTPResponse.Body.Close()
|
||||||
_, err := ioutil.ReadAll(r.HTTPResponse.Body)
|
b := &bytes.Buffer{}
|
||||||
if err != nil {
|
if _, err := io.Copy(b, r.HTTPResponse.Body); err != nil {
|
||||||
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err)
|
r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO extract the error...
|
// Response body format is not consistent between metadata endpoints.
|
||||||
|
// Grab the error message as a string and include that as the source error
|
||||||
|
r.Error = awserr.New("EC2MetadataError", "failed to make EC2Metadata request", errors.New(b.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateEndpointHandler(r *request.Request) {
|
func validateEndpointHandler(r *request.Request) {
|
||||||
if r.Service.Endpoint == "" {
|
if r.ClientInfo.Endpoint == "" {
|
||||||
r.Error = aws.ErrMissingEndpoint
|
r.Error = aws.ErrMissingEndpoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
78
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go
generated
vendored
Normal file
78
vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package ec2metadata_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||||
|
"github.com/aws/aws-sdk-go/awstesting/unit"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClientOverrideDefaultHTTPClientTimeout(t *testing.T) {
|
||||||
|
svc := ec2metadata.New(unit.Session)
|
||||||
|
|
||||||
|
assert.NotEqual(t, http.DefaultClient, svc.Config.HTTPClient)
|
||||||
|
assert.Equal(t, 5*time.Second, svc.Config.HTTPClient.Timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientNotOverrideDefaultHTTPClientTimeout(t *testing.T) {
|
||||||
|
http.DefaultClient.Transport = &http.Transport{}
|
||||||
|
defer func() {
|
||||||
|
http.DefaultClient.Transport = nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
svc := ec2metadata.New(unit.Session)
|
||||||
|
|
||||||
|
assert.Equal(t, http.DefaultClient, svc.Config.HTTPClient)
|
||||||
|
|
||||||
|
tr, ok := svc.Config.HTTPClient.Transport.(*http.Transport)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.NotNil(t, tr)
|
||||||
|
assert.Nil(t, tr.Dial)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientDisableOverrideDefaultHTTPClientTimeout(t *testing.T) {
|
||||||
|
svc := ec2metadata.New(unit.Session, aws.NewConfig().WithEC2MetadataDisableTimeoutOverride(true))
|
||||||
|
|
||||||
|
assert.Equal(t, http.DefaultClient, svc.Config.HTTPClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientOverrideDefaultHTTPClientTimeoutRace(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("us-east-1a"))
|
||||||
|
}))
|
||||||
|
|
||||||
|
cfg := aws.NewConfig().WithEndpoint(server.URL)
|
||||||
|
runEC2MetadataClients(t, cfg, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientOverrideDefaultHTTPClientTimeoutRaceWithTransport(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("us-east-1a"))
|
||||||
|
}))
|
||||||
|
|
||||||
|
cfg := aws.NewConfig().WithEndpoint(server.URL).WithHTTPClient(&http.Client{
|
||||||
|
Transport: http.DefaultTransport,
|
||||||
|
})
|
||||||
|
|
||||||
|
runEC2MetadataClients(t, cfg, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runEC2MetadataClients(t *testing.T, cfg *aws.Config, atOnce int) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(atOnce)
|
||||||
|
for i := 0; i < atOnce; i++ {
|
||||||
|
go func() {
|
||||||
|
svc := ec2metadata.New(unit.Session, cfg)
|
||||||
|
_, err := svc.Region()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
133
vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go
generated
vendored
Normal file
133
vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
)
|
||||||
|
|
||||||
|
type modelDefinition map[string]json.RawMessage
|
||||||
|
|
||||||
|
// A DecodeModelOptions are the options for how the endpoints model definition
|
||||||
|
// are decoded.
|
||||||
|
type DecodeModelOptions struct {
|
||||||
|
SkipCustomizations bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set combines all of the option functions together.
|
||||||
|
func (d *DecodeModelOptions) Set(optFns ...func(*DecodeModelOptions)) {
|
||||||
|
for _, fn := range optFns {
|
||||||
|
fn(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeModel unmarshals a Regions and Endpoint model definition file into
|
||||||
|
// a endpoint Resolver. If the file format is not supported, or an error occurs
|
||||||
|
// when unmarshaling the model an error will be returned.
|
||||||
|
//
|
||||||
|
// Casting the return value of this func to a EnumPartitions will
|
||||||
|
// allow you to get a list of the partitions in the order the endpoints
|
||||||
|
// will be resolved in.
|
||||||
|
//
|
||||||
|
// resolver, err := endpoints.DecodeModel(reader)
|
||||||
|
//
|
||||||
|
// partitions := resolver.(endpoints.EnumPartitions).Partitions()
|
||||||
|
// for _, p := range partitions {
|
||||||
|
// // ... inspect partitions
|
||||||
|
// }
|
||||||
|
func DecodeModel(r io.Reader, optFns ...func(*DecodeModelOptions)) (Resolver, error) {
|
||||||
|
var opts DecodeModelOptions
|
||||||
|
opts.Set(optFns...)
|
||||||
|
|
||||||
|
// Get the version of the partition file to determine what
|
||||||
|
// unmarshaling model to use.
|
||||||
|
modelDef := modelDefinition{}
|
||||||
|
if err := json.NewDecoder(r).Decode(&modelDef); err != nil {
|
||||||
|
return nil, newDecodeModelError("failed to decode endpoints model", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var version string
|
||||||
|
if b, ok := modelDef["version"]; ok {
|
||||||
|
version = string(b)
|
||||||
|
} else {
|
||||||
|
return nil, newDecodeModelError("endpoints version not found in model", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if version == "3" {
|
||||||
|
return decodeV3Endpoints(modelDef, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, newDecodeModelError(
|
||||||
|
fmt.Sprintf("endpoints version %s, not supported", version), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeV3Endpoints(modelDef modelDefinition, opts DecodeModelOptions) (Resolver, error) {
|
||||||
|
b, ok := modelDef["partitions"]
|
||||||
|
if !ok {
|
||||||
|
return nil, newDecodeModelError("endpoints model missing partitions", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
ps := partitions{}
|
||||||
|
if err := json.Unmarshal(b, &ps); err != nil {
|
||||||
|
return nil, newDecodeModelError("failed to decode endpoints model", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.SkipCustomizations {
|
||||||
|
return ps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customization
|
||||||
|
for i := 0; i < len(ps); i++ {
|
||||||
|
p := &ps[i]
|
||||||
|
custAddEC2Metadata(p)
|
||||||
|
custAddS3DualStack(p)
|
||||||
|
custRmIotDataService(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func custAddS3DualStack(p *partition) {
|
||||||
|
if p.ID != "aws" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s, ok := p.Services["s3"]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Defaults.HasDualStack = boxedTrue
|
||||||
|
s.Defaults.DualStackHostname = "{service}.dualstack.{region}.{dnsSuffix}"
|
||||||
|
|
||||||
|
p.Services["s3"] = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func custAddEC2Metadata(p *partition) {
|
||||||
|
p.Services["ec2metadata"] = service{
|
||||||
|
IsRegionalized: boxedFalse,
|
||||||
|
PartitionEndpoint: "aws-global",
|
||||||
|
Endpoints: endpoints{
|
||||||
|
"aws-global": endpoint{
|
||||||
|
Hostname: "169.254.169.254/latest",
|
||||||
|
Protocols: []string{"http"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func custRmIotDataService(p *partition) {
|
||||||
|
delete(p.Services, "data.iot")
|
||||||
|
}
|
||||||
|
|
||||||
|
type decodeModelError struct {
|
||||||
|
awsError
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDecodeModelError(msg string, err error) decodeModelError {
|
||||||
|
return decodeModelError{
|
||||||
|
awsError: awserr.New("DecodeEndpointsModelError", msg, err),
|
||||||
|
}
|
||||||
|
}
|
117
vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode_test.go
generated
vendored
Normal file
117
vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode_test.go
generated
vendored
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecodeEndpoints_V3(t *testing.T) {
|
||||||
|
const v3Doc = `
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"partitions": [
|
||||||
|
{
|
||||||
|
"defaults": {
|
||||||
|
"hostname": "{service}.{region}.{dnsSuffix}",
|
||||||
|
"protocols": [
|
||||||
|
"https"
|
||||||
|
],
|
||||||
|
"signatureVersions": [
|
||||||
|
"v4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dnsSuffix": "amazonaws.com",
|
||||||
|
"partition": "aws",
|
||||||
|
"partitionName": "AWS Standard",
|
||||||
|
"regionRegex": "^(us|eu|ap|sa|ca)\\-\\w+\\-\\d+$",
|
||||||
|
"regions": {
|
||||||
|
"ap-northeast-1": {
|
||||||
|
"description": "Asia Pacific (Tokyo)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"services": {
|
||||||
|
"acm": {
|
||||||
|
"endpoints": {
|
||||||
|
"ap-northeast-1": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"s3": {
|
||||||
|
"endpoints": {
|
||||||
|
"ap-northeast-1": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
resolver, err := DecodeModel(strings.NewReader(v3Doc))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint, err := resolver.EndpointFor("acm", "ap-northeast-1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to resolve endpoint, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a, e := endpoint.URL, "https://acm.ap-northeast-1.amazonaws.com"; a != e {
|
||||||
|
t.Errorf("expected %q URL got %q", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := resolver.(partitions)[0]
|
||||||
|
|
||||||
|
s3Defaults := p.Services["s3"].Defaults
|
||||||
|
if a, e := s3Defaults.HasDualStack, boxedTrue; a != e {
|
||||||
|
t.Errorf("expect s3 service to have dualstack enabled")
|
||||||
|
}
|
||||||
|
if a, e := s3Defaults.DualStackHostname, "{service}.dualstack.{region}.{dnsSuffix}"; a != e {
|
||||||
|
t.Errorf("expect s3 dualstack host pattern to be %q, got %q", e, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
ec2metaEndpoint := p.Services["ec2metadata"].Endpoints["aws-global"]
|
||||||
|
if a, e := ec2metaEndpoint.Hostname, "169.254.169.254/latest"; a != e {
|
||||||
|
t.Errorf("expect ec2metadata host to be %q, got %q", e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecodeEndpoints_NoPartitions(t *testing.T) {
|
||||||
|
const doc = `{ "version": 3 }`
|
||||||
|
|
||||||
|
resolver, err := DecodeModel(strings.NewReader(doc))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolver != nil {
|
||||||
|
t.Errorf("expect resolver to be nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecodeEndpoints_UnsupportedVersion(t *testing.T) {
|
||||||
|
const doc = `{ "version": 2 }`
|
||||||
|
|
||||||
|
resolver, err := DecodeModel(strings.NewReader(doc))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error decoding model")
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolver != nil {
|
||||||
|
t.Errorf("expect resolver to be nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecodeModelOptionsSet(t *testing.T) {
|
||||||
|
var actual DecodeModelOptions
|
||||||
|
actual.Set(func(o *DecodeModelOptions) {
|
||||||
|
o.SkipCustomizations = true
|
||||||
|
})
|
||||||
|
|
||||||
|
expect := DecodeModelOptions{
|
||||||
|
SkipCustomizations: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual != expect {
|
||||||
|
t.Errorf("expect %v options got %v", expect, actual)
|
||||||
|
}
|
||||||
|
}
|
2518
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
Normal file
2518
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
66
vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go
generated
vendored
Normal file
66
vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Package endpoints provides the types and functionality for defining regions
|
||||||
|
// and endpoints, as well as querying those definitions.
|
||||||
|
//
|
||||||
|
// The SDK's Regions and Endpoints metadata is code generated into the endpoints
|
||||||
|
// package, and is accessible via the DefaultResolver function. This function
|
||||||
|
// returns a endpoint Resolver will search the metadata and build an associated
|
||||||
|
// endpoint if one is found. The default resolver will search all partitions
|
||||||
|
// known by the SDK. e.g AWS Standard (aws), AWS China (aws-cn), and
|
||||||
|
// AWS GovCloud (US) (aws-us-gov).
|
||||||
|
// .
|
||||||
|
//
|
||||||
|
// Enumerating Regions and Endpoint Metadata
|
||||||
|
//
|
||||||
|
// Casting the Resolver returned by DefaultResolver to a EnumPartitions interface
|
||||||
|
// will allow you to get access to the list of underlying Partitions with the
|
||||||
|
// Partitions method. This is helpful if you want to limit the SDK's endpoint
|
||||||
|
// resolving to a single partition, or enumerate regions, services, and endpoints
|
||||||
|
// in the partition.
|
||||||
|
//
|
||||||
|
// resolver := endpoints.DefaultResolver()
|
||||||
|
// partitions := resolver.(endpoints.EnumPartitions).Partitions()
|
||||||
|
//
|
||||||
|
// for _, p := range partitions {
|
||||||
|
// fmt.Println("Regions for", p.ID())
|
||||||
|
// for id, _ := range p.Regions() {
|
||||||
|
// fmt.Println("*", id)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fmt.Println("Services for", p.ID())
|
||||||
|
// for id, _ := range p.Services() {
|
||||||
|
// fmt.Println("*", id)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Using Custom Endpoints
|
||||||
|
//
|
||||||
|
// The endpoints package also gives you the ability to use your own logic how
|
||||||
|
// endpoints are resolved. This is a great way to define a custom endpoint
|
||||||
|
// for select services, without passing that logic down through your code.
|
||||||
|
//
|
||||||
|
// If a type implements the Resolver interface it can be used to resolve
|
||||||
|
// endpoints. To use this with the SDK's Session and Config set the value
|
||||||
|
// of the type to the EndpointsResolver field of aws.Config when initializing
|
||||||
|
// the session, or service client.
|
||||||
|
//
|
||||||
|
// In addition the ResolverFunc is a wrapper for a func matching the signature
|
||||||
|
// of Resolver.EndpointFor, converting it to a type that satisfies the
|
||||||
|
// Resolver interface.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// myCustomResolver := func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) {
|
||||||
|
// if service == endpoints.S3ServiceID {
|
||||||
|
// return endpoints.ResolvedEndpoint{
|
||||||
|
// URL: "s3.custom.endpoint.com",
|
||||||
|
// SigningRegion: "custom-signing-region",
|
||||||
|
// }, nil
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return endpoints.DefaultResolver().EndpointFor(service, region, optFns...)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// sess := session.Must(session.NewSession(&aws.Config{
|
||||||
|
// Region: aws.String("us-west-2"),
|
||||||
|
// EndpointResolver: endpoints.ResolverFunc(myCustomResolver),
|
||||||
|
// }))
|
||||||
|
package endpoints
|
439
vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
generated
vendored
Normal file
439
vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
generated
vendored
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options provide the configuration needed to direct how the
|
||||||
|
// endpoints will be resolved.
|
||||||
|
type Options struct {
|
||||||
|
// DisableSSL forces the endpoint to be resolved as HTTP.
|
||||||
|
// instead of HTTPS if the service supports it.
|
||||||
|
DisableSSL bool
|
||||||
|
|
||||||
|
// Sets the resolver to resolve the endpoint as a dualstack endpoint
|
||||||
|
// for the service. If dualstack support for a service is not known and
|
||||||
|
// StrictMatching is not enabled a dualstack endpoint for the service will
|
||||||
|
// be returned. This endpoint may not be valid. If StrictMatching is
|
||||||
|
// enabled only services that are known to support dualstack will return
|
||||||
|
// dualstack endpoints.
|
||||||
|
UseDualStack bool
|
||||||
|
|
||||||
|
// Enables strict matching of services and regions resolved endpoints.
|
||||||
|
// If the partition doesn't enumerate the exact service and region an
|
||||||
|
// error will be returned. This option will prevent returning endpoints
|
||||||
|
// that look valid, but may not resolve to any real endpoint.
|
||||||
|
StrictMatching bool
|
||||||
|
|
||||||
|
// Enables resolving a service endpoint based on the region provided if the
|
||||||
|
// service does not exist. The service endpoint ID will be used as the service
|
||||||
|
// domain name prefix. By default the endpoint resolver requires the service
|
||||||
|
// to be known when resolving endpoints.
|
||||||
|
//
|
||||||
|
// If resolving an endpoint on the partition list the provided region will
|
||||||
|
// be used to determine which partition's domain name pattern to the service
|
||||||
|
// endpoint ID with. If both the service and region are unkonwn and resolving
|
||||||
|
// the endpoint on partition list an UnknownEndpointError error will be returned.
|
||||||
|
//
|
||||||
|
// If resolving and endpoint on a partition specific resolver that partition's
|
||||||
|
// domain name pattern will be used with the service endpoint ID. If both
|
||||||
|
// region and service do not exist when resolving an endpoint on a specific
|
||||||
|
// partition the partition's domain pattern will be used to combine the
|
||||||
|
// endpoint and region together.
|
||||||
|
//
|
||||||
|
// This option is ignored if StrictMatching is enabled.
|
||||||
|
ResolveUnknownService bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set combines all of the option functions together.
|
||||||
|
func (o *Options) Set(optFns ...func(*Options)) {
|
||||||
|
for _, fn := range optFns {
|
||||||
|
fn(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableSSLOption sets the DisableSSL options. Can be used as a functional
|
||||||
|
// option when resolving endpoints.
|
||||||
|
func DisableSSLOption(o *Options) {
|
||||||
|
o.DisableSSL = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseDualStackOption sets the UseDualStack option. Can be used as a functional
|
||||||
|
// option when resolving endpoints.
|
||||||
|
func UseDualStackOption(o *Options) {
|
||||||
|
o.UseDualStack = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// StrictMatchingOption sets the StrictMatching option. Can be used as a functional
|
||||||
|
// option when resolving endpoints.
|
||||||
|
func StrictMatchingOption(o *Options) {
|
||||||
|
o.StrictMatching = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveUnknownServiceOption sets the ResolveUnknownService option. Can be used
|
||||||
|
// as a functional option when resolving endpoints.
|
||||||
|
func ResolveUnknownServiceOption(o *Options) {
|
||||||
|
o.ResolveUnknownService = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Resolver provides the interface for functionality to resolve endpoints.
|
||||||
|
// The build in Partition and DefaultResolver return value satisfy this interface.
|
||||||
|
type Resolver interface {
|
||||||
|
EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolverFunc is a helper utility that wraps a function so it satisfies the
|
||||||
|
// Resolver interface. This is useful when you want to add additional endpoint
|
||||||
|
// resolving logic, or stub out specific endpoints with custom values.
|
||||||
|
type ResolverFunc func(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
|
||||||
|
|
||||||
|
// EndpointFor wraps the ResolverFunc function to satisfy the Resolver interface.
|
||||||
|
func (fn ResolverFunc) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
|
||||||
|
return fn(service, region, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var schemeRE = regexp.MustCompile("^([^:]+)://")
|
||||||
|
|
||||||
|
// AddScheme adds the HTTP or HTTPS schemes to a endpoint URL if there is no
|
||||||
|
// scheme. If disableSSL is true HTTP will set HTTP instead of the default HTTPS.
|
||||||
|
//
|
||||||
|
// If disableSSL is set, it will only set the URL's scheme if the URL does not
|
||||||
|
// contain a scheme.
|
||||||
|
func AddScheme(endpoint string, disableSSL bool) string {
|
||||||
|
if !schemeRE.MatchString(endpoint) {
|
||||||
|
scheme := "https"
|
||||||
|
if disableSSL {
|
||||||
|
scheme = "http"
|
||||||
|
}
|
||||||
|
endpoint = fmt.Sprintf("%s://%s", scheme, endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnumPartitions a provides a way to retrieve the underlying partitions that
|
||||||
|
// make up the SDK's default Resolver, or any resolver decoded from a model
|
||||||
|
// file.
|
||||||
|
//
|
||||||
|
// Use this interface with DefaultResolver and DecodeModels to get the list of
|
||||||
|
// Partitions.
|
||||||
|
type EnumPartitions interface {
|
||||||
|
Partitions() []Partition
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegionsForService returns a map of regions for the partition and service.
|
||||||
|
// If either the partition or service does not exist false will be returned
|
||||||
|
// as the second parameter.
|
||||||
|
//
|
||||||
|
// This example shows how to get the regions for DynamoDB in the AWS partition.
|
||||||
|
// rs, exists := endpoints.RegionsForService(endpoints.DefaultPartitions(), endpoints.AwsPartitionID, endpoints.DynamodbServiceID)
|
||||||
|
//
|
||||||
|
// This is equivalent to using the partition directly.
|
||||||
|
// rs := endpoints.AwsPartition().Services()[endpoints.DynamodbServiceID].Regions()
|
||||||
|
func RegionsForService(ps []Partition, partitionID, serviceID string) (map[string]Region, bool) {
|
||||||
|
for _, p := range ps {
|
||||||
|
if p.ID() != partitionID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := p.p.Services[serviceID]; !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
s := Service{
|
||||||
|
id: serviceID,
|
||||||
|
p: p.p,
|
||||||
|
}
|
||||||
|
return s.Regions(), true
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]Region{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionForRegion returns the first partition which includes the region
|
||||||
|
// passed in. This includes both known regions and regions which match
|
||||||
|
// a pattern supported by the partition which may include regions that are
|
||||||
|
// not explicitly known by the partition. Use the Regions method of the
|
||||||
|
// returned Partition if explicit support is needed.
|
||||||
|
func PartitionForRegion(ps []Partition, regionID string) (Partition, bool) {
|
||||||
|
for _, p := range ps {
|
||||||
|
if _, ok := p.p.Regions[regionID]; ok || p.p.RegionRegex.MatchString(regionID) {
|
||||||
|
return p, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Partition{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Partition provides the ability to enumerate the partition's regions
|
||||||
|
// and services.
|
||||||
|
type Partition struct {
|
||||||
|
id string
|
||||||
|
p *partition
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the identifier of the partition.
|
||||||
|
func (p Partition) ID() string { return p.id }
|
||||||
|
|
||||||
|
// EndpointFor attempts to resolve the endpoint based on service and region.
|
||||||
|
// See Options for information on configuring how the endpoint is resolved.
|
||||||
|
//
|
||||||
|
// If the service cannot be found in the metadata the UnknownServiceError
|
||||||
|
// error will be returned. This validation will occur regardless if
|
||||||
|
// StrictMatching is enabled. To enable resolving unknown services set the
|
||||||
|
// "ResolveUnknownService" option to true. When StrictMatching is disabled
|
||||||
|
// this option allows the partition resolver to resolve a endpoint based on
|
||||||
|
// the service endpoint ID provided.
|
||||||
|
//
|
||||||
|
// When resolving endpoints you can choose to enable StrictMatching. This will
|
||||||
|
// require the provided service and region to be known by the partition.
|
||||||
|
// If the endpoint cannot be strictly resolved an error will be returned. This
|
||||||
|
// mode is useful to ensure the endpoint resolved is valid. Without
|
||||||
|
// StrictMatching enabled the endpoint returned my look valid but may not work.
|
||||||
|
// StrictMatching requires the SDK to be updated if you want to take advantage
|
||||||
|
// of new regions and services expansions.
|
||||||
|
//
|
||||||
|
// Errors that can be returned.
|
||||||
|
// * UnknownServiceError
|
||||||
|
// * UnknownEndpointError
|
||||||
|
func (p Partition) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
|
||||||
|
return p.p.EndpointFor(service, region, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regions returns a map of Regions indexed by their ID. This is useful for
|
||||||
|
// enumerating over the regions in a partition.
|
||||||
|
func (p Partition) Regions() map[string]Region {
|
||||||
|
rs := map[string]Region{}
|
||||||
|
for id := range p.p.Regions {
|
||||||
|
rs[id] = Region{
|
||||||
|
id: id,
|
||||||
|
p: p.p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Services returns a map of Service indexed by their ID. This is useful for
|
||||||
|
// enumerating over the services in a partition.
|
||||||
|
func (p Partition) Services() map[string]Service {
|
||||||
|
ss := map[string]Service{}
|
||||||
|
for id := range p.p.Services {
|
||||||
|
ss[id] = Service{
|
||||||
|
id: id,
|
||||||
|
p: p.p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Region provides information about a region, and ability to resolve an
|
||||||
|
// endpoint from the context of a region, given a service.
|
||||||
|
type Region struct {
|
||||||
|
id, desc string
|
||||||
|
p *partition
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the region's identifier.
|
||||||
|
func (r Region) ID() string { return r.id }
|
||||||
|
|
||||||
|
// ResolveEndpoint resolves an endpoint from the context of the region given
|
||||||
|
// a service. See Partition.EndpointFor for usage and errors that can be returned.
|
||||||
|
func (r Region) ResolveEndpoint(service string, opts ...func(*Options)) (ResolvedEndpoint, error) {
|
||||||
|
return r.p.EndpointFor(service, r.id, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Services returns a list of all services that are known to be in this region.
|
||||||
|
func (r Region) Services() map[string]Service {
|
||||||
|
ss := map[string]Service{}
|
||||||
|
for id, s := range r.p.Services {
|
||||||
|
if _, ok := s.Endpoints[r.id]; ok {
|
||||||
|
ss[id] = Service{
|
||||||
|
id: id,
|
||||||
|
p: r.p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Service provides information about a service, and ability to resolve an
|
||||||
|
// endpoint from the context of a service, given a region.
|
||||||
|
type Service struct {
|
||||||
|
id string
|
||||||
|
p *partition
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the identifier for the service.
|
||||||
|
func (s Service) ID() string { return s.id }
|
||||||
|
|
||||||
|
// ResolveEndpoint resolves an endpoint from the context of a service given
|
||||||
|
// a region. See Partition.EndpointFor for usage and errors that can be returned.
|
||||||
|
func (s Service) ResolveEndpoint(region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
|
||||||
|
return s.p.EndpointFor(s.id, region, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regions returns a map of Regions that the service is present in.
|
||||||
|
//
|
||||||
|
// A region is the AWS region the service exists in. Whereas a Endpoint is
|
||||||
|
// an URL that can be resolved to a instance of a service.
|
||||||
|
func (s Service) Regions() map[string]Region {
|
||||||
|
rs := map[string]Region{}
|
||||||
|
for id := range s.p.Services[s.id].Endpoints {
|
||||||
|
if _, ok := s.p.Regions[id]; ok {
|
||||||
|
rs[id] = Region{
|
||||||
|
id: id,
|
||||||
|
p: s.p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoints returns a map of Endpoints indexed by their ID for all known
|
||||||
|
// endpoints for a service.
|
||||||
|
//
|
||||||
|
// A region is the AWS region the service exists in. Whereas a Endpoint is
|
||||||
|
// an URL that can be resolved to a instance of a service.
|
||||||
|
func (s Service) Endpoints() map[string]Endpoint {
|
||||||
|
es := map[string]Endpoint{}
|
||||||
|
for id := range s.p.Services[s.id].Endpoints {
|
||||||
|
es[id] = Endpoint{
|
||||||
|
id: id,
|
||||||
|
serviceID: s.id,
|
||||||
|
p: s.p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Endpoint provides information about endpoints, and provides the ability
|
||||||
|
// to resolve that endpoint for the service, and the region the endpoint
|
||||||
|
// represents.
|
||||||
|
type Endpoint struct {
|
||||||
|
id string
|
||||||
|
serviceID string
|
||||||
|
p *partition
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the identifier for an endpoint.
|
||||||
|
func (e Endpoint) ID() string { return e.id }
|
||||||
|
|
||||||
|
// ServiceID returns the identifier the endpoint belongs to.
|
||||||
|
func (e Endpoint) ServiceID() string { return e.serviceID }
|
||||||
|
|
||||||
|
// ResolveEndpoint resolves an endpoint from the context of a service and
|
||||||
|
// region the endpoint represents. See Partition.EndpointFor for usage and
|
||||||
|
// errors that can be returned.
|
||||||
|
func (e Endpoint) ResolveEndpoint(opts ...func(*Options)) (ResolvedEndpoint, error) {
|
||||||
|
return e.p.EndpointFor(e.serviceID, e.id, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ResolvedEndpoint is an endpoint that has been resolved based on a partition
|
||||||
|
// service, and region.
|
||||||
|
type ResolvedEndpoint struct {
|
||||||
|
// The endpoint URL
|
||||||
|
URL string
|
||||||
|
|
||||||
|
// The region that should be used for signing requests.
|
||||||
|
SigningRegion string
|
||||||
|
|
||||||
|
// The service name that should be used for signing requests.
|
||||||
|
SigningName string
|
||||||
|
|
||||||
|
// The signing method that should be used for signing requests.
|
||||||
|
SigningMethod string
|
||||||
|
}
|
||||||
|
|
||||||
|
// So that the Error interface type can be included as an anonymous field
|
||||||
|
// in the requestError struct and not conflict with the error.Error() method.
|
||||||
|
type awsError awserr.Error
|
||||||
|
|
||||||
|
// A EndpointNotFoundError is returned when in StrictMatching mode, and the
|
||||||
|
// endpoint for the service and region cannot be found in any of the partitions.
|
||||||
|
type EndpointNotFoundError struct {
|
||||||
|
awsError
|
||||||
|
Partition string
|
||||||
|
Service string
|
||||||
|
Region string
|
||||||
|
}
|
||||||
|
|
||||||
|
// A UnknownServiceError is returned when the service does not resolve to an
|
||||||
|
// endpoint. Includes a list of all known services for the partition. Returned
|
||||||
|
// when a partition does not support the service.
|
||||||
|
type UnknownServiceError struct {
|
||||||
|
awsError
|
||||||
|
Partition string
|
||||||
|
Service string
|
||||||
|
Known []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUnknownServiceError builds and returns UnknownServiceError.
|
||||||
|
func NewUnknownServiceError(p, s string, known []string) UnknownServiceError {
|
||||||
|
return UnknownServiceError{
|
||||||
|
awsError: awserr.New("UnknownServiceError",
|
||||||
|
"could not resolve endpoint for unknown service", nil),
|
||||||
|
Partition: p,
|
||||||
|
Service: s,
|
||||||
|
Known: known,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the error.
|
||||||
|
func (e UnknownServiceError) Error() string {
|
||||||
|
extra := fmt.Sprintf("partition: %q, service: %q",
|
||||||
|
e.Partition, e.Service)
|
||||||
|
if len(e.Known) > 0 {
|
||||||
|
extra += fmt.Sprintf(", known: %v", e.Known)
|
||||||
|
}
|
||||||
|
return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the error.
|
||||||
|
func (e UnknownServiceError) String() string {
|
||||||
|
return e.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A UnknownEndpointError is returned when in StrictMatching mode and the
|
||||||
|
// service is valid, but the region does not resolve to an endpoint. Includes
|
||||||
|
// a list of all known endpoints for the service.
|
||||||
|
type UnknownEndpointError struct {
|
||||||
|
awsError
|
||||||
|
Partition string
|
||||||
|
Service string
|
||||||
|
Region string
|
||||||
|
Known []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUnknownEndpointError builds and returns UnknownEndpointError.
|
||||||
|
func NewUnknownEndpointError(p, s, r string, known []string) UnknownEndpointError {
|
||||||
|
return UnknownEndpointError{
|
||||||
|
awsError: awserr.New("UnknownEndpointError",
|
||||||
|
"could not resolve endpoint", nil),
|
||||||
|
Partition: p,
|
||||||
|
Service: s,
|
||||||
|
Region: r,
|
||||||
|
Known: known,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the error.
|
||||||
|
func (e UnknownEndpointError) Error() string {
|
||||||
|
extra := fmt.Sprintf("partition: %q, service: %q, region: %q",
|
||||||
|
e.Partition, e.Service, e.Region)
|
||||||
|
if len(e.Known) > 0 {
|
||||||
|
extra += fmt.Sprintf(", known: %v", e.Known)
|
||||||
|
}
|
||||||
|
return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the error.
|
||||||
|
func (e UnknownEndpointError) String() string {
|
||||||
|
return e.Error()
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue