From 3fc7bce7e03254a4fa4d53c4dbba5c190ca4a5e6 Mon Sep 17 00:00:00 2001 From: dmitri Date: Wed, 13 Dec 2017 12:10:19 +0100 Subject: [PATCH 1/2] Update to accommodate changes for teleport v2.3.5 Fixes #16, #32. --- Dockerfile | 19 +++ Gopkg.lock | 437 +++++++++++++++++++++++++++++++++++++++++++++++ Gopkg.toml | 37 ++++ Makefile | 21 ++- clt/clt.go | 38 +++-- clt/httperror.go | 1 - clt/main.go | 31 ++-- lib/net.go | 7 +- main.go | 37 ++-- 9 files changed, 562 insertions(+), 66 deletions(-) create mode 100644 Dockerfile create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6867fd1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM golang:1.9 + +ARG UID +ARG GID + +RUN groupadd builder --gid=$GID -o; \ + useradd builder --uid=$UID --gid=$GID --create-home --shell=/bin/bash; + +RUN (mkdir -p /go/src/github.com/gravitational/teleconsole && chown -R builder /go) +RUN (mkdir -p /go/bin) + +ENV LANGUAGE="en_US.UTF-8" \ + LANG="en_US.UTF-8" \ + LC_ALL="en_US.UTF-8" \ + LC_CTYPE="en_US.UTF-8" \ + GOPATH="/go" \ + PATH="$PATH:/opt/go/bin:/go/bin" + +VOLUME ["/go/src/github.com/gravitational/teleconsole"] diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..4a664e1 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,437 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/Azure/go-ansiterm" + packages = [".","winterm"] + revision = "d6e3b3328b783f23731bc4d058875b0371ff8109" + +[[projects]] + branch = "master" + name = "github.com/alecthomas/template" + packages = [".","parse"] + revision = "a0175ee3bccc567396460bf5acd36800cb10c49c" + +[[projects]] + branch = "master" + name = "github.com/alecthomas/units" + packages = ["."] + revision = "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a" + +[[projects]] + name = "github.com/aws/aws-sdk-go" + packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/json/jsonutil","private/protocol/jsonrpc","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/xml/xmlutil","service/dynamodb","service/dynamodb/dynamodbattribute","service/sts"] + revision = "25ef42b41b82230caae56ab23d872c81fb5c0eae" + version = "v1.12.46" + +[[projects]] + name = "github.com/beevik/etree" + packages = ["."] + revision = "15a30b44cfd6c5a16a7ddfe271bf146aaf2d3195" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9" + +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + +[[projects]] + name = "github.com/boombuler/barcode" + packages = [".","qr","utils"] + revision = "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d" + version = "v1.0.0" + +[[projects]] + name = "github.com/cenkalti/backoff" + packages = ["."] + revision = "61153c768f31ee5f130071d08fc82b85208528de" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/codahale/hdrhistogram" + packages = ["."] + revision = "3a0bb77429bd3a61596f5e8a3172445844342120" + +[[projects]] + name = "github.com/coreos/etcd" + packages = ["client","pkg/pathutil","pkg/srv","pkg/tlsutil","pkg/transport","pkg/types","version"] + revision = "1e1dbb23924672c6cd72c62ee0db2b45f778da71" + version = "v3.2.11" + +[[projects]] + name = "github.com/coreos/go-oidc" + packages = ["http","jose","key","oauth2","oidc"] + revision = "e51edf2e47e65e5708600d4da6fca1388ee437b4" + source = "github.com/gravitational/go-oidc" + version = "v0.0.1" + +[[projects]] + name = "github.com/coreos/go-semver" + packages = ["semver"] + revision = "8ab6407b697782a06568d4b7f1db25550ec2e4c6" + version = "v0.2.0" + +[[projects]] + name = "github.com/coreos/pkg" + packages = ["health","httputil","timeutil"] + revision = "3ac0863d7acf3bc44daf49afef8919af12f704ef" + version = "v3" + +[[projects]] + branch = "master" + name = "github.com/docker/docker" + packages = ["pkg/term/windows"] + revision = "5dc791c2debd561f61f04ec5a947f261fe79b275" + +[[projects]] + name = "github.com/fatih/color" + packages = ["."] + revision = "570b54cabe6b8eb0bc2dfce68d964677d63b5260" + version = "v1.5.0" + +[[projects]] + name = "github.com/fatih/structs" + packages = ["."] + revision = "a720dfa8df582c51dee1b36feabb906bde1588bd" + version = "v1.0" + +[[projects]] + name = "github.com/ghodss/yaml" + packages = ["."] + revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" + version = "v1.0.0" + +[[projects]] + name = "github.com/go-ini/ini" + packages = ["."] + revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a" + version = "v1.32.0" + +[[projects]] + branch = "master" + name = "github.com/gokyle/hotp" + packages = ["."] + revision = "c180d57d286b385101c999a60087a40d7f48fc77" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = ["proto","protoc-gen-go/descriptor","ptypes","ptypes/any","ptypes/duration","ptypes/empty","ptypes/timestamp"] + revision = "1e59b77b52bf8e4b449a57e6f79f21226d571845" + +[[projects]] + branch = "master" + name = "github.com/gravitational/configure" + packages = ["cstrings","jsonschema"] + revision = "4e0f2df8846ee9557b5c88307a769ff2f85e89cd" + +[[projects]] + branch = "master" + name = "github.com/gravitational/form" + packages = ["."] + revision = "c4048f792f70d207e6d8b9c1bf52319247f202b8" + +[[projects]] + branch = "master" + name = "github.com/gravitational/kingpin" + packages = ["."] + revision = "52bc17adf63c0807b5e5b5d91350703630f621c7" + +[[projects]] + name = "github.com/gravitational/roundtrip" + packages = ["."] + revision = "ad87871f2c4d31b9bef3f3c6224c3f5e50d0bac1" + version = "0.0.2" + +[[projects]] + name = "github.com/gravitational/teleport" + packages = [".","integration","lib","lib/auth","lib/auth/native","lib/auth/testauthority","lib/backend","lib/backend/boltbk","lib/backend/dir","lib/backend/dynamo","lib/backend/etcdbk","lib/client","lib/defaults","lib/events","lib/httplib","lib/httplib/csrf","lib/limiter","lib/reversetunnel","lib/service","lib/services","lib/services/local","lib/session","lib/shell","lib/srv","lib/sshutils","lib/sshutils/scp","lib/state","lib/teleagent","lib/utils","lib/utils/parse","lib/utils/proxy","lib/web","lib/web/ui"] + revision = "d19f8e79a4aec6dc3007969ac4b2d846c6dad4a0" + version = "v2.3.6" + +[[projects]] + name = "github.com/gravitational/trace" + packages = ["."] + revision = "0bd13642feb8f57acc0d8e3a568edc34e05a74b9" + version = "1.1.3" + +[[projects]] + name = "github.com/gravitational/ttlmap" + packages = ["."] + revision = "91fd36b9004c1ee5a778739752ea1aba5638c03a" + version = "0.0.1" + +[[projects]] + name = "github.com/grpc-ecosystem/grpc-gateway" + packages = ["third_party/googleapis/google/api"] + revision = "a8f25bd1ab549f8b87afd48aa9181221e9d439bb" + version = "v1.1.0" + +[[projects]] + name = "github.com/jmespath/go-jmespath" + packages = ["."] + revision = "0b12d6b5" + +[[projects]] + name = "github.com/jonboulle/clockwork" + packages = ["."] + revision = "2eee05ed794112d45db504eb05aa693efd2b8b09" + version = "v0.1.0" + +[[projects]] + name = "github.com/julienschmidt/httprouter" + packages = ["."] + revision = "8c199fb6259ffc1af525cc3ad52ee60ba8359669" + version = "v1.1" + +[[projects]] + branch = "master" + name = "github.com/kardianos/osext" + packages = ["."] + revision = "ae77be60afb1dcacde03767a8c37337fad28ac14" + +[[projects]] + name = "github.com/kr/pty" + packages = ["."] + revision = "95d05c1eef33a45bd58676b6ce28d105839b8d0b" + version = "v1.0.1" + +[[projects]] + name = "github.com/mailgun/holster" + packages = ["."] + revision = "0a24431be9a21b8044ddbd9e26ebcbcb294865b1" + version = "v1.5.2" + +[[projects]] + name = "github.com/mailgun/lemma" + packages = ["random","secret"] + revision = "e8b0cd607f5855f9a4a33f8ae5d033178f559964" + version = "0.0.2" + +[[projects]] + branch = "master" + name = "github.com/mailgun/metrics" + packages = ["."] + revision = "fd99b46995bd989df0d163e320e18ea7285f211f" + +[[projects]] + branch = "master" + name = "github.com/mailgun/minheap" + packages = ["."] + revision = "3dbe6c6bf55f94c5efcf460dc7f86830c21a90b2" + +[[projects]] + branch = "alexander/copy" + name = "github.com/mailgun/oxy" + packages = ["forward","utils"] + revision = "0c3e45a1f7b20e1f818612ad4f42abfc0923f3d5" + +[[projects]] + branch = "master" + name = "github.com/mailgun/timetools" + packages = ["."] + revision = "f3a7b8ffff474320c4f5cc564c9abb2c52ded8bc" + +[[projects]] + branch = "master" + name = "github.com/mailgun/ttlmap" + packages = ["."] + revision = "c1c17f74874f2a5ea48bfb06b5459d4ef2689749" + +[[projects]] + name = "github.com/mattn/go-colorable" + packages = ["."] + revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" + version = "v0.0.9" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/mdp/rsc" + packages = ["gf256","qr","qr/coding"] + revision = "90f07065088deccf50b28eb37c93dad3078c0f3c" + +[[projects]] + name = "github.com/moby/moby" + packages = ["pkg/term"] + revision = "092cba3727bb9b4a2f0e922cd6c0f93ea270e363" + version = "v1.13.1" + +[[projects]] + name = "github.com/pborman/uuid" + packages = ["."] + revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53" + version = "v1.1" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pquerna/otp" + packages = [".","hotp","totp"] + revision = "b7b89250c468c06871d3837bee02e2d5c155ae19" + version = "v1.0.0" + +[[projects]] + name = "github.com/prometheus/client_golang" + packages = ["prometheus"] + revision = "c5b7fccd204277076155f10851dad72b76a49317" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" + +[[projects]] + branch = "master" + name = "github.com/prometheus/common" + packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"] + revision = "2e54d0b93cba2fd133edc32211dcc32c06ef72ca" + +[[projects]] + branch = "master" + name = "github.com/prometheus/procfs" + packages = [".","xfs"] + revision = "a6e9df898b1336106c743392c48ee0b71f5c4efa" + +[[projects]] + name = "github.com/russellhaering/gosaml2" + packages = [".","types"] + revision = "82a6e6132741c96a25969cec66912b6c24fcbd5f" + +[[projects]] + branch = "master" + name = "github.com/russellhaering/goxmldsig" + packages = [".","etreeutils","types"] + revision = "b7efc6231e45b10bfd779852831c8bb59b350ec5" + +[[projects]] + name = "github.com/satori/go.uuid" + packages = ["."] + revision = "879c5887cd475cd7864858769793b2ceb0d44feb" + version = "v1.1.0" + +[[projects]] + name = "github.com/sirupsen/logrus" + packages = [".","hooks/syslog"] + revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" + version = "v1.0.4" + +[[projects]] + name = "github.com/tstranex/u2f" + packages = ["."] + revision = "eb799ce68da4150b16ff5d0c89a24e2a2ad993d8" + +[[projects]] + name = "github.com/ugorji/go" + packages = ["codec"] + revision = "646ae4a518c1c3be0739df898118d9bccf993858" + +[[projects]] + branch = "master" + name = "github.com/vulcand/oxy" + packages = ["connlimit","ratelimit","utils"] + revision = "4ce46c197bfa755a828cf04a083e20291f98f590" + +[[projects]] + name = "github.com/vulcand/predicate" + packages = ["."] + revision = "939c094524d124c55fa8afe0e077701db4a865e2" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/xeipuuv/gojsonpointer" + packages = ["."] + revision = "6fe8760cad3569743d51ddbb243b26f8456742dc" + +[[projects]] + branch = "master" + name = "github.com/xeipuuv/gojsonreference" + packages = ["."] + revision = "e02fc20de94c78484cd5ffb007f8af96be030a45" + +[[projects]] + branch = "master" + name = "github.com/xeipuuv/gojsonschema" + packages = ["."] + revision = "212d8a0df7acfab8bdd190a7a69f0ab7376edcc8" + +[[projects]] + name = "golang.org/x/crypto" + packages = ["bcrypt","blowfish","curve25519","ed25519","ed25519/internal/edwards25519","nacl/secretbox","poly1305","salsa20/salsa","ssh","ssh/agent","ssh/terminal"] + revision = "453249f01cfeb54c3d549ddb75ff152ca243f9d8" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["context","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace","websocket"] + revision = "d866cfc389cec985d6fda2859936a575a55a3ab6" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "53aa286056ef226755cd898109dbcdaba8ac0b81" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = ["collate","collate/build","encoding","encoding/internal","encoding/internal/identifier","encoding/unicode","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","internal/utf8internal","language","runes","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] + revision = "3b24cac7bc3a458991ab409aa2a339ac9e0d60d6" + +[[projects]] + branch = "master" + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + revision = "a8101f21cf983e773d0c1133ebc5424792003214" + +[[projects]] + name = "google.golang.org/grpc" + packages = [".","balancer","balancer/roundrobin","codes","connectivity","credentials","encoding","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"] + revision = "e687fa4e6424368ece6e4fe727cea2c806a0fcb4" + version = "v1.8.2" + +[[projects]] + branch = "v2" + name = "gopkg.in/mgo.v2" + packages = ["bson","internal/json"] + revision = "3f83fa5005286a7fe593b055f0d7771a7dce4655" + +[[projects]] + branch = "v2" + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "287cf08546ab5e7e37d55a84f7ed3fd1db036de5" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "2fdc7de43790570bb667515f20f4d4198bcbeb6706801390d7242020d79b8eae" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..e92fd41 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,37 @@ + +[[constraint]] + name = "github.com/gravitational/teleport" + version = "v2.3.5" + +[[constraint]] + name = "github.com/sirupsen/logrus" + version = "v1.0.3" + +[[constraint]] + name = "github.com/gravitational/trace" + version = "1.1.3" + +[[constraint]] + name = "github.com/fatih/color" + version = "v1.5.0" + +[[override]] + name = "github.com/russellhaering/gosaml2" + revision = "82a6e6132741c96a25969cec66912b6c24fcbd5f" + +[[override]] + name = "github.com/coreos/etcd" + version="v3.2.4" + +[[override]] + name = "github.com/ugorji/go" + #version = "v1.1" + revision = "646ae4a518c1c3be0739df898118d9bccf993858" + +[[override]] + name = "github.com/tstranex/u2f" + revision = "eb799ce68da4150b16ff5d0c89a24e2a2ad993d8" + +[[override]] + name = "golang.org/x/crypto" + revision = "453249f01cfeb54c3d549ddb75ff152ca243f9d8" diff --git a/Makefile b/Makefile index aafa9a7..a6ca40a 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,19 @@ # To bump the version, edit this variable and run `make version` export VERSION=0.3.2-alpha -OUT=out/teleconsole +OUT=build/teleconsole GOSRC=$(shell find -name "*.go" -print) +BUILDBOX_TAG:=teleconsole-buildbox:0.0.1 -# Default target: out/teleconsole -$(OUT): $(GOSRC) Makefile +$(OUT): $(GOSRC) Makefile buildbox + docker run \ + -v $(shell pwd):/go/src/github.com/gravitational/teleconsole \ + $(BUILDBOX_TAG) \ + $(MAKE) -C /go/src/github.com/gravitational/teleconsole build-container + +.PHONY: build-container +build-container: + mkdir -p build $(MAKE) -C version CGO_ENABLED=1 go build -i -ldflags -w -o $(OUT) @@ -28,3 +36,10 @@ clean: .PHONY:test test: go test ./... -v + +# buildbox builds a docker image used to compile the binaries +.PHONY: buildbox +buildbox: + docker build \ + --build-arg UID=$$(id -u) --build-arg GID=$$(id -g) \ + -t $(BUILDBOX_TAG) . diff --git a/clt/clt.go b/clt/clt.go index c20291f..636afe8 100644 --- a/clt/clt.go +++ b/clt/clt.go @@ -11,29 +11,31 @@ import ( "strconv" "time" - log "github.com/sirupsen/logrus" + "github.com/gravitational/teleconsole/conf" + "github.com/gravitational/teleconsole/geo" + "github.com/gravitational/teleconsole/lib" + "github.com/fatih/color" "github.com/gravitational/teleport/integration" "github.com/gravitational/teleport/lib/client" "github.com/gravitational/teleport/lib/defaults" tservice "github.com/gravitational/teleport/lib/service" - - "github.com/gravitational/teleconsole/conf" - "github.com/gravitational/teleconsole/geo" - "github.com/gravitational/teleconsole/lib" - tsession "github.com/gravitational/teleport/lib/session" "github.com/gravitational/trace" + log "github.com/sirupsen/logrus" + "golang.org/x/crypto/ssh" ) -var ( - tunnelError = fmt.Errorf("Unable to initialize the API for the local Teleport instance") - DefaultSiteName = "teleconsole-client" +var tunnelError = fmt.Errorf("Unable to initialize the API for the local Teleport instance") + +const ( + hostID = "00000000-0000-0000-0000-000000000000" + defaultClusterName = "teleconsole-client" - // SyncRefreshIntervalMs defines the minimum amount of time it takes for + // syncRefreshIntervalMs defines the minimum amount of time it takes for // the local SSH server and the disposable proxy to synchronize the session // state (milliseconds) - SyncRefreshInterval = time.Second + syncRefreshInterval = time.Second ) // StartBroadcast starts a new SSH session exposed to the world via disposable @@ -85,7 +87,7 @@ func StartBroadcast(c *conf.Config, api *APIClient, cmd []string) error { } // create a new (local) teleport server instance and add ourselves as a user to it: fmt.Printf("Starting local SSH server on %s...\n", hostName) - localServer := integration.NewInstance(DefaultSiteName, hostName, ports, nil, nil) + localServer := integration.NewInstance(defaultClusterName, hostID, hostName, ports, nil, nil) localServer.Secrets.Users = them.AnnounceUsers() // request Teleconsole server to create a remote teleport proxy we can @@ -111,7 +113,7 @@ func StartBroadcast(c *conf.Config, api *APIClient, cmd []string) error { tconf.SSH.Enabled = true tconf.Console = nil tconf.Auth.NoAudit = true - tconf.Proxy.DisableWebUI = true + tconf.Proxy.DisableWebInterface = true trustedSecrets := sess.Secrets for uname, user := range me.LoginUsers() { trustedSecrets.Users[uname] = user @@ -129,12 +131,12 @@ func StartBroadcast(c *conf.Config, api *APIClient, cmd []string) error { // create a local client to "SSH into ourselves": port, _ := strconv.Atoi(localServer.GetPortSSH()) - sshClient, err := localServer.NewClient(me.Username, DefaultSiteName, hostName, port) + sshClient, err := localServer.NewClient(me.Username, defaultClusterName, hostName, port) if err != nil { return trace.Wrap(err) } // Define "shell created" callback - sshClient.OnShellCreated = func(shell io.ReadWriteCloser) (exit bool, err error) { + sshClient.OnShellCreated = func(_ *ssh.Session, _ *ssh.Client, shell io.ReadWriteCloser) (exit bool, err error) { // publish the session (when it's ready) so the server-side disposable // proxy will locate this client by a session ID if err = publishSession(localServer, api); err != nil { @@ -146,7 +148,7 @@ func StartBroadcast(c *conf.Config, api *APIClient, cmd []string) error { var brokenSessionError = fmt.Errorf("SSH tunnel cannot be established, please try again.") const attempts = 10 for i := 0; i < attempts; i++ { - time.Sleep(SyncRefreshInterval) + time.Sleep(syncRefreshInterval) sessionStats, err := api.GetSessionStats(api.SessionID) if err != nil { log.Debug(err) @@ -195,7 +197,7 @@ func publishSession(local *integration.TeleInstance, api *APIClient) error { if local.Tunnel == nil { return trace.Wrap(tunnelError) } - site, err := local.Tunnel.GetSite(local.Config.Auth.DomainName) + site, err := local.Tunnel.GetSite(local.Config.Auth.ClusterName.GetClusterName()) if err != nil { log.Error(err) return trace.Wrap(err) @@ -294,7 +296,7 @@ func Join(c *conf.Config, api *APIClient, sid string) error { HostLogin: session.Login, InsecureSkipVerify: false, KeysDir: "/tmp/", - SiteName: DefaultSiteName, + SiteName: defaultClusterName, LocalForwardPorts: c.ForwardPorts, }) if err != nil { diff --git a/clt/httperror.go b/clt/httperror.go index 685ffa5..48e3c56 100644 --- a/clt/httperror.go +++ b/clt/httperror.go @@ -3,7 +3,6 @@ package clt import ( "encoding/json" "fmt" - "io/ioutil" "net/http" diff --git a/clt/main.go b/clt/main.go index e295a10..bed0acb 100644 --- a/clt/main.go +++ b/clt/main.go @@ -15,9 +15,7 @@ import ( "github.com/gravitational/teleport/lib/client" teleport "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/utils" - "github.com/gravitational/trace" - log "github.com/sirupsen/logrus" ) @@ -39,28 +37,21 @@ func (this *App) DebugDump() { } func initLogging(verbosity int) { - // our log: - log.SetLevel(log.ErrorLevel) log.SetOutput(os.Stderr) - // teleport log: - utils.InitLoggerCLI() - + level, teleLevel := log.ErrorLevel, log.ErrorLevel switch verbosity { case 1: - // our log: - log.SetLevel(log.InfoLevel) + level, teleLevel = log.InfoLevel, log.InfoLevel case 2: - // our log: - log.SetLevel(log.DebugLevel) - // teleport log: - utils.InitLoggerVerbose() + level, teleLevel = log.DebugLevel, log.InfoLevel case 3: - // our log: - log.SetLevel(log.DebugLevel) - // teleport log: - utils.InitLoggerDebug() + level, teleLevel = log.DebugLevel, log.DebugLevel } + // local log + log.SetLevel(level) + // teleport log + utils.InitLogger(utils.LoggingForCLI, teleLevel) } // NewApp constructs and returns a "Teleconsole application object" @@ -99,9 +90,9 @@ func NewApp(fs *flag.FlagSet) (*App, error) { // configure teleport internals to use our ping interval. // IMPORANT: these must be similar for proxies and servers - teleport.SessionRefreshPeriod = SyncRefreshInterval - teleport.ReverseTunnelAgentHeartbeatPeriod = SyncRefreshInterval * 2 - teleport.ServerHeartbeatTTL = SyncRefreshInterval * 2 + teleport.SessionRefreshPeriod = syncRefreshInterval + teleport.ReverseTunnelAgentHeartbeatPeriod = syncRefreshInterval * 2 + teleport.ServerHeartbeatTTL = syncRefreshInterval * 2 // this disables costly Teleport "key pool" native.PrecalculatedKeysNum = 0 diff --git a/lib/net.go b/lib/net.go index 6987a8a..c63828d 100644 --- a/lib/net.go +++ b/lib/net.go @@ -1,13 +1,12 @@ package lib import ( - "github.com/gravitational/teleport/lib/client" - "github.com/gravitational/trace" + "net" "net/url" "strconv" - "net" - // log "github.com/sirupsen/logrus" + "github.com/gravitational/teleport/lib/client" + "github.com/gravitational/trace" ) const ( diff --git a/main.go b/main.go index ab0bd4e..4c27b8a 100644 --- a/main.go +++ b/main.go @@ -1,17 +1,15 @@ package main import ( - //"crypto/x509" - "crypto/x509" "fmt" "net/url" "os" - "github.com/sirupsen/logrus" "github.com/gravitational/teleconsole/clt" "github.com/gravitational/teleconsole/version" "github.com/gravitational/trace" + "github.com/sirupsen/logrus" ) func main() { @@ -27,24 +25,23 @@ func main() { app.DebugDump() } - // we have CLI args? - if len(app.Args) > 0 { - switch app.Args[0] { - case "help": - app.Usage() - case "join": - err = app.Join() - case "version": - version.Print("Teleconsole", conf.Verbosity > 0) - os.Exit(0) - default: - app.Usage() - } - // no CLI args? Start a new broadcast! - } else { - err = app.Start() + if len(app.Args) == 0 { + // start new broadcast if no arguments were specified + fatalIf(app.Start()) + return + } + + switch app.Args[0] { + case "help": + app.Usage() + case "join": + fatalIf(app.Join()) + case "version": + version.Print("Teleconsole", conf.Verbosity > 0) + os.Exit(0) + default: + app.Usage() } - fatalIf(err) } func fatalIf(err error) { From 8f85087843aad5a6e695603cd1ec583c61852da2 Mon Sep 17 00:00:00 2001 From: dmitri Date: Wed, 13 Dec 2017 12:12:29 +0100 Subject: [PATCH 2/2] Vendor dependencies --- vendor/github.com/Azure/go-ansiterm/LICENSE | 21 + vendor/github.com/Azure/go-ansiterm/README.md | 12 + .../github.com/Azure/go-ansiterm/constants.go | 188 + .../github.com/Azure/go-ansiterm/context.go | 7 + .../Azure/go-ansiterm/csi_entry_state.go | 49 + .../Azure/go-ansiterm/csi_param_state.go | 38 + .../go-ansiterm/escape_intermediate_state.go | 36 + .../Azure/go-ansiterm/escape_state.go | 47 + .../Azure/go-ansiterm/event_handler.go | 90 + .../Azure/go-ansiterm/ground_state.go | 24 + .../Azure/go-ansiterm/osc_string_state.go | 31 + vendor/github.com/Azure/go-ansiterm/parser.go | 151 + .../go-ansiterm/parser_action_helpers.go | 99 + .../Azure/go-ansiterm/parser_actions.go | 119 + .../Azure/go-ansiterm/parser_test.go | 141 + .../go-ansiterm/parser_test_helpers_test.go | 114 + .../go-ansiterm/parser_test_utilities_test.go | 66 + vendor/github.com/Azure/go-ansiterm/states.go | 71 + .../go-ansiterm/test_event_handler_test.go | 173 + .../github.com/Azure/go-ansiterm/utilities.go | 21 + .../Azure/go-ansiterm/winterm/ansi.go | 182 + .../Azure/go-ansiterm/winterm/api.go | 327 + .../go-ansiterm/winterm/attr_translation.go | 100 + .../go-ansiterm/winterm/cursor_helpers.go | 101 + .../go-ansiterm/winterm/erase_helpers.go | 84 + .../go-ansiterm/winterm/scroll_helper.go | 118 + .../Azure/go-ansiterm/winterm/utilities.go | 9 + .../go-ansiterm/winterm/win_event_handler.go | 743 + vendor/github.com/alecthomas/template/LICENSE | 27 + .../github.com/alecthomas/template/README.md | 25 + vendor/github.com/alecthomas/template/doc.go | 406 + .../alecthomas/template/example_test.go | 72 + .../alecthomas/template/examplefiles_test.go | 183 + .../alecthomas/template/examplefunc_test.go | 55 + vendor/github.com/alecthomas/template/exec.go | 845 + .../alecthomas/template/exec_test.go | 1044 + .../github.com/alecthomas/template/funcs.go | 598 + .../github.com/alecthomas/template/helper.go | 108 + .../alecthomas/template/multi_test.go | 293 + .../alecthomas/template/parse/lex.go | 556 + .../alecthomas/template/parse/lex_test.go | 468 + .../alecthomas/template/parse/node.go | 834 + .../alecthomas/template/parse/parse.go | 700 + .../alecthomas/template/parse/parse_test.go | 426 + .../alecthomas/template/template.go | 218 + vendor/github.com/alecthomas/units/COPYING | 19 + vendor/github.com/alecthomas/units/README.md | 11 + vendor/github.com/alecthomas/units/bytes.go | 83 + .../github.com/alecthomas/units/bytes_test.go | 49 + vendor/github.com/alecthomas/units/doc.go | 13 + vendor/github.com/alecthomas/units/si.go | 26 + vendor/github.com/alecthomas/units/util.go | 138 + vendor/github.com/aws/aws-sdk-go/.gitignore | 11 + .../github.com/aws/aws-sdk-go/.godoc_config | 14 + vendor/github.com/aws/aws-sdk-go/.travis.yml | 29 + vendor/github.com/aws/aws-sdk-go/CHANGELOG.md | 2472 + .../aws/aws-sdk-go/CHANGELOG_PENDING.md | 5 + .../github.com/aws/aws-sdk-go/CONTRIBUTING.md | 127 + vendor/github.com/aws/aws-sdk-go/Gopkg.lock | 20 + vendor/github.com/aws/aws-sdk-go/Gopkg.toml | 48 + vendor/github.com/aws/aws-sdk-go/LICENSE.txt | 202 + vendor/github.com/aws/aws-sdk-go/Makefile | 187 + vendor/github.com/aws/aws-sdk-go/NOTICE.txt | 3 + vendor/github.com/aws/aws-sdk-go/README.md | 449 + .../aws/aws-sdk-go/aws/awserr/error.go | 145 + .../aws/aws-sdk-go/aws/awserr/types.go | 194 + .../aws/aws-sdk-go/aws/awsutil/copy.go | 108 + .../aws/aws-sdk-go/aws/awsutil/copy_test.go | 353 + .../aws/aws-sdk-go/aws/awsutil/equal.go | 27 + .../aws/aws-sdk-go/aws/awsutil/equal_test.go | 30 + .../aws/aws-sdk-go/aws/awsutil/path_value.go | 222 + .../aws-sdk-go/aws/awsutil/path_value_test.go | 182 + .../aws/aws-sdk-go/aws/awsutil/prettify.go | 113 + .../aws-sdk-go/aws/awsutil/string_value.go | 89 + .../aws/aws-sdk-go/aws/client/client.go | 90 + .../aws/aws-sdk-go/aws/client/client_test.go | 78 + .../aws-sdk-go/aws/client/default_retryer.go | 138 + .../aws/client/default_retryer_test.go | 189 + .../aws/aws-sdk-go/aws/client/logger.go | 108 + .../aws/aws-sdk-go/aws/client/logger_test.go | 57 + .../aws/client/metadata/client_info.go | 12 + .../github.com/aws/aws-sdk-go/aws/config.go | 470 + .../aws/aws-sdk-go/aws/config_test.go | 86 + .../github.com/aws/aws-sdk-go/aws/context.go | 71 + .../aws/aws-sdk-go/aws/context_1_6.go | 41 + .../aws/aws-sdk-go/aws/context_1_7.go | 9 + .../aws/aws-sdk-go/aws/context_test.go | 37 + .../aws/aws-sdk-go/aws/convert_types.go | 387 + .../aws/aws-sdk-go/aws/convert_types_test.go | 641 + .../aws-sdk-go/aws/corehandlers/handlers.go | 242 + .../aws/corehandlers/handlers_1_8_test.go | 64 + .../aws/corehandlers/handlers_test.go | 398 + .../aws/corehandlers/param_validator.go | 17 + .../aws/corehandlers/param_validator_test.go | 286 + .../aws/credentials/chain_provider.go | 102 + .../aws/credentials/chain_provider_test.go | 154 + .../aws-sdk-go/aws/credentials/credentials.go | 246 + .../aws/credentials/credentials_test.go | 73 + .../ec2rolecreds/ec2_role_provider.go | 178 + .../ec2rolecreds/ec2_role_provider_test.go | 159 + .../aws/credentials/endpointcreds/provider.go | 191 + .../endpointcreds/provider_test.go | 111 + .../aws/credentials/env_provider.go | 78 + .../aws/credentials/env_provider_test.go | 70 + .../aws-sdk-go/aws/credentials/example.ini | 12 + .../shared_credentials_provider.go | 150 + .../shared_credentials_provider_test.go | 136 + .../aws/credentials/static_provider.go | 57 + .../aws/credentials/static_provider_test.go | 34 + .../stscreds/assume_role_provider.go | 298 + .../stscreds/assume_role_provider_test.go | 150 + .../aws/aws-sdk-go/aws/defaults/defaults.go | 163 + .../aws-sdk-go/aws/defaults/defaults_test.go | 88 + .../aws-sdk-go/aws/defaults/shared_config.go | 27 + vendor/github.com/aws/aws-sdk-go/aws/doc.go | 56 + .../aws/aws-sdk-go/aws/ec2metadata/api.go | 162 + .../aws-sdk-go/aws/ec2metadata/api_test.go | 289 + .../aws/aws-sdk-go/aws/ec2metadata/service.go | 124 + .../aws/ec2metadata/service_test.go | 78 + .../aws/aws-sdk-go/aws/endpoints/decode.go | 133 + .../aws-sdk-go/aws/endpoints/decode_test.go | 117 + .../aws/aws-sdk-go/aws/endpoints/defaults.go | 2551 + .../aws/aws-sdk-go/aws/endpoints/doc.go | 66 + .../aws/aws-sdk-go/aws/endpoints/endpoints.go | 439 + .../aws/endpoints/endpoints_test.go | 335 + .../aws-sdk-go/aws/endpoints/example_test.go | 66 + .../aws/aws-sdk-go/aws/endpoints/v3model.go | 303 + .../aws/endpoints/v3model_codegen.go | 337 + .../aws-sdk-go/aws/endpoints/v3model_test.go | 354 + .../github.com/aws/aws-sdk-go/aws/errors.go | 17 + .../aws/aws-sdk-go/aws/jsonvalue.go | 12 + .../github.com/aws/aws-sdk-go/aws/logger.go | 112 + .../aws/request/connection_reset_error.go | 19 + .../request/connection_reset_error_other.go | 11 + .../connection_reset_error_other_test.go | 9 + .../request/connection_reset_error_test.go | 11 + .../aws/aws-sdk-go/aws/request/handlers.go | 256 + .../aws-sdk-go/aws/request/handlers_test.go | 266 + .../aws-sdk-go/aws/request/http_request.go | 24 + .../aws/request/http_request_copy_test.go | 34 + .../aws/request/http_request_retry_test.go | 37 + .../aws-sdk-go/aws/request/offset_reader.go | 58 + .../aws/request/offset_reader_test.go | 139 + .../aws/aws-sdk-go/aws/request/request.go | 679 + .../aws/request/request_1_5_test.go | 11 + .../aws/request/request_1_6_test.go | 51 + .../aws/aws-sdk-go/aws/request/request_1_7.go | 39 + .../aws/request/request_1_7_test.go | 24 + .../aws/aws-sdk-go/aws/request/request_1_8.go | 33 + .../aws/request/request_1_8_test.go | 85 + .../aws-sdk-go/aws/request/request_context.go | 14 + .../aws/request/request_context_1_6.go | 14 + .../aws/request/request_context_test.go | 46 + .../aws/request/request_internal_test.go | 27 + .../aws/request/request_pagination.go | 236 + .../aws/request/request_pagination_test.go | 604 + .../aws/request/request_resetbody_test.go | 58 + .../aws-sdk-go/aws/request/request_test.go | 1004 + .../aws/aws-sdk-go/aws/request/retryer.go | 161 + .../aws-sdk-go/aws/request/retryer_test.go | 62 + .../aws/request/timeout_read_closer.go | 94 + .../timeout_read_closer_benchmark_test.go | 76 + .../aws/request/timeout_read_closer_test.go | 118 + .../aws/aws-sdk-go/aws/request/validation.go | 234 + .../aws/aws-sdk-go/aws/request/waiter.go | 295 + .../aws/aws-sdk-go/aws/request/waiter_test.go | 654 + .../aws/session/custom_ca_bundle_test.go | 243 + .../aws/aws-sdk-go/aws/session/doc.go | 273 + .../aws/aws-sdk-go/aws/session/env_config.go | 191 + .../aws-sdk-go/aws/session/env_config_test.go | 279 + .../aws/aws-sdk-go/aws/session/session.go | 606 + .../aws-sdk-go/aws/session/session_test.go | 446 + .../aws-sdk-go/aws/session/shared_config.go | 295 + .../aws/session/shared_config_test.go | 274 + .../aws/signer/v4/functional_1_5_test.go | 86 + .../aws/signer/v4/functional_test.go | 254 + .../aws-sdk-go/aws/signer/v4/header_rules.go | 82 + .../aws/signer/v4/header_rules_test.go | 77 + .../aws/aws-sdk-go/aws/signer/v4/options.go | 7 + .../aws/aws-sdk-go/aws/signer/v4/uri_path.go | 24 + .../aws/aws-sdk-go/aws/signer/v4/v4.go | 767 + .../aws/aws-sdk-go/aws/signer/v4/v4_test.go | 644 + vendor/github.com/aws/aws-sdk-go/aws/types.go | 118 + .../aws/aws-sdk-go/aws/types_test.go | 92 + vendor/github.com/aws/aws-sdk-go/aws/url.go | 12 + .../github.com/aws/aws-sdk-go/aws/url_1_7.go | 29 + .../github.com/aws/aws-sdk-go/aws/version.go | 8 + .../github.com/aws/aws-sdk-go/buildspec.yml | 21 + vendor/github.com/aws/aws-sdk-go/doc.go | 405 + .../internal/shareddefaults/shared_config.go | 40 + .../shared_config_other_test.go | 40 + .../shared_config_windows_test.go | 40 + .../aws/aws-sdk-go/private/README.md | 4 + .../private/protocol/idempotency.go | 75 + .../private/protocol/idempotency_test.go | 106 + .../private/protocol/json/jsonutil/build.go | 286 + .../protocol/json/jsonutil/build_test.go | 109 + .../protocol/json/jsonutil/unmarshal.go | 226 + .../protocol/jsonrpc/build_bench_test.go | 71 + .../private/protocol/jsonrpc/build_test.go | 2444 + .../private/protocol/jsonrpc/jsonrpc.go | 111 + .../protocol/jsonrpc/unmarshal_test.go | 1521 + .../aws-sdk-go/private/protocol/jsonvalue.go | 76 + .../private/protocol/jsonvalue_test.go | 93 + .../private/protocol/protocol_test.go | 203 + .../private/protocol/query/build.go | 36 + .../private/protocol/query/build_test.go | 4056 + .../protocol/query/queryutil/queryutil.go | 241 + .../private/protocol/query/unmarshal.go | 35 + .../private/protocol/query/unmarshal_error.go | 66 + .../private/protocol/query/unmarshal_test.go | 2991 + .../aws-sdk-go/private/protocol/rest/build.go | 291 + .../private/protocol/rest/build_test.go | 63 + .../private/protocol/rest/payload.go | 45 + .../private/protocol/rest/rest_test.go | 63 + .../private/protocol/rest/unmarshal.go | 221 + .../aws-sdk-go/private/protocol/unmarshal.go | 21 + .../private/protocol/unmarshal_test.go | 40 + .../private/protocol/xml/xmlutil/build.go | 296 + .../private/protocol/xml/xmlutil/unmarshal.go | 260 + .../protocol/xml/xmlutil/unmarshal_test.go | 142 + .../protocol/xml/xmlutil/xml_to_struct.go | 147 + .../aws/aws-sdk-go/service/dynamodb/api.go | 11629 +++ .../service/dynamodb/customizations.go | 109 + .../service/dynamodb/customizations_test.go | 153 + .../aws/aws-sdk-go/service/dynamodb/doc.go | 45 + .../aws-sdk-go/service/dynamodb/doc_custom.go | 27 + .../dynamodb/dynamodbattribute/converter.go | 443 + .../converter_examples_test.go | 80 + .../dynamodbattribute/converter_test.go | 498 + .../dynamodb/dynamodbattribute/decode.go | 761 + .../dynamodb/dynamodbattribute/decode_test.go | 598 + .../service/dynamodb/dynamodbattribute/doc.go | 95 + .../dynamodb/dynamodbattribute/encode.go | 641 + .../dynamodb/dynamodbattribute/encode_test.go | 271 + .../dynamodb/dynamodbattribute/field.go | 269 + .../dynamodb/dynamodbattribute/field_test.go | 116 + .../marshaler_examples_test.go | 104 + .../dynamodbattribute/marshaler_test.go | 573 + .../dynamodb/dynamodbattribute/shared_test.go | 405 + .../service/dynamodb/dynamodbattribute/tag.go | 68 + .../dynamodb/dynamodbattribute/tag_test.go | 47 + .../aws/aws-sdk-go/service/dynamodb/errors.go | 126 + .../service/dynamodb/examples_test.go | 677 + .../aws-sdk-go/service/dynamodb/service.go | 95 + .../aws-sdk-go/service/dynamodb/waiters.go | 107 + .../aws/aws-sdk-go/service/generate.go | 5 + .../aws/aws-sdk-go/service/sts/api.go | 2358 + .../aws-sdk-go/service/sts/customizations.go | 12 + .../service/sts/customizations_test.go | 45 + .../aws/aws-sdk-go/service/sts/doc.go | 72 + .../aws/aws-sdk-go/service/sts/errors.go | 73 + .../aws-sdk-go/service/sts/examples_test.go | 282 + .../aws/aws-sdk-go/service/sts/service.go | 93 + vendor/github.com/beevik/etree/.travis.yml | 16 + vendor/github.com/beevik/etree/CONTRIBUTORS | 8 + vendor/github.com/beevik/etree/LICENSE | 24 + vendor/github.com/beevik/etree/README.md | 203 + vendor/github.com/beevik/etree/etree.go | 943 + vendor/github.com/beevik/etree/etree_test.go | 426 + .../github.com/beevik/etree/example_test.go | 62 + vendor/github.com/beevik/etree/helpers.go | 188 + vendor/github.com/beevik/etree/path.go | 516 + vendor/github.com/beevik/etree/path_test.go | 173 + vendor/github.com/beorn7/perks/.gitignore | 2 + vendor/github.com/beorn7/perks/LICENSE | 20 + vendor/github.com/beorn7/perks/README.md | 31 + .../beorn7/perks/quantile/bench_test.go | 63 + .../beorn7/perks/quantile/example_test.go | 121 + .../beorn7/perks/quantile/exampledata.txt | 2388 + .../beorn7/perks/quantile/stream.go | 292 + .../beorn7/perks/quantile/stream_test.go | 215 + vendor/github.com/boltdb/bolt/.gitignore | 4 + vendor/github.com/boltdb/bolt/LICENSE | 20 + vendor/github.com/boltdb/bolt/Makefile | 18 + vendor/github.com/boltdb/bolt/README.md | 916 + vendor/github.com/boltdb/bolt/appveyor.yml | 18 + vendor/github.com/boltdb/bolt/bolt_386.go | 10 + vendor/github.com/boltdb/bolt/bolt_amd64.go | 10 + vendor/github.com/boltdb/bolt/bolt_arm.go | 28 + vendor/github.com/boltdb/bolt/bolt_arm64.go | 12 + vendor/github.com/boltdb/bolt/bolt_linux.go | 10 + vendor/github.com/boltdb/bolt/bolt_openbsd.go | 27 + vendor/github.com/boltdb/bolt/bolt_ppc.go | 9 + vendor/github.com/boltdb/bolt/bolt_ppc64.go | 12 + vendor/github.com/boltdb/bolt/bolt_ppc64le.go | 12 + vendor/github.com/boltdb/bolt/bolt_s390x.go | 12 + vendor/github.com/boltdb/bolt/bolt_unix.go | 89 + .../boltdb/bolt/bolt_unix_solaris.go | 90 + vendor/github.com/boltdb/bolt/bolt_windows.go | 144 + .../github.com/boltdb/bolt/boltsync_unix.go | 8 + vendor/github.com/boltdb/bolt/bucket.go | 777 + vendor/github.com/boltdb/bolt/bucket_test.go | 1909 + vendor/github.com/boltdb/bolt/cursor.go | 400 + vendor/github.com/boltdb/bolt/cursor_test.go | 817 + vendor/github.com/boltdb/bolt/db.go | 1039 + vendor/github.com/boltdb/bolt/db_test.go | 1545 + vendor/github.com/boltdb/bolt/doc.go | 44 + vendor/github.com/boltdb/bolt/errors.go | 71 + vendor/github.com/boltdb/bolt/freelist.go | 252 + .../github.com/boltdb/bolt/freelist_test.go | 158 + vendor/github.com/boltdb/bolt/node.go | 604 + vendor/github.com/boltdb/bolt/node_test.go | 156 + vendor/github.com/boltdb/bolt/page.go | 197 + vendor/github.com/boltdb/bolt/page_test.go | 72 + vendor/github.com/boltdb/bolt/quick_test.go | 87 + .../github.com/boltdb/bolt/simulation_test.go | 329 + vendor/github.com/boltdb/bolt/tx.go | 684 + vendor/github.com/boltdb/bolt/tx_test.go | 716 + .../github.com/boombuler/barcode/.gitignore | 1 + vendor/github.com/boombuler/barcode/LICENSE | 21 + vendor/github.com/boombuler/barcode/README.md | 53 + .../github.com/boombuler/barcode/barcode.go | 42 + .../boombuler/barcode/qr/alphanumeric.go | 66 + .../boombuler/barcode/qr/alphanumeric_test.go | 44 + .../boombuler/barcode/qr/automatic.go | 23 + .../boombuler/barcode/qr/automatic_test.go | 30 + .../github.com/boombuler/barcode/qr/blocks.go | 59 + .../boombuler/barcode/qr/blocks_test.go | 36 + .../boombuler/barcode/qr/encoder.go | 416 + .../boombuler/barcode/qr/encoder_test.go | 134 + .../boombuler/barcode/qr/errorcorrection.go | 29 + .../barcode/qr/errorcorrection_test.go | 60 + .../boombuler/barcode/qr/numeric.go | 56 + .../boombuler/barcode/qr/numeric_test.go | 26 + .../github.com/boombuler/barcode/qr/qrcode.go | 166 + .../boombuler/barcode/qr/qrcode_test.go | 126 + .../boombuler/barcode/qr/unicode.go | 27 + .../boombuler/barcode/qr/unicode_test.go | 18 + .../boombuler/barcode/qr/versioninfo.go | 310 + .../boombuler/barcode/qr/versioninfo_test.go | 157 + .../boombuler/barcode/scaledbarcode.go | 134 + .../boombuler/barcode/utils/base1dcode.go | 57 + .../boombuler/barcode/utils/bitlist.go | 119 + .../boombuler/barcode/utils/galoisfield.go | 65 + .../barcode/utils/galoisfield_test.go | 59 + .../boombuler/barcode/utils/gfpoly.go | 103 + .../boombuler/barcode/utils/reedsolomon.go | 44 + .../boombuler/barcode/utils/runeint.go | 19 + .../boombuler/barcode/utils/runeint_test.go | 24 + vendor/github.com/cenkalti/backoff/.gitignore | 22 + .../github.com/cenkalti/backoff/.travis.yml | 9 + vendor/github.com/cenkalti/backoff/LICENSE | 20 + vendor/github.com/cenkalti/backoff/README.md | 30 + vendor/github.com/cenkalti/backoff/backoff.go | 66 + .../cenkalti/backoff/backoff_test.go | 27 + vendor/github.com/cenkalti/backoff/context.go | 60 + .../cenkalti/backoff/context_test.go | 26 + .../cenkalti/backoff/example_test.go | 73 + .../cenkalti/backoff/exponential.go | 156 + .../cenkalti/backoff/exponential_test.go | 108 + vendor/github.com/cenkalti/backoff/retry.go | 78 + .../github.com/cenkalti/backoff/retry_test.go | 99 + vendor/github.com/cenkalti/backoff/ticker.go | 81 + .../cenkalti/backoff/ticker_test.go | 94 + vendor/github.com/cenkalti/backoff/tries.go | 35 + .../github.com/cenkalti/backoff/tries_test.go | 55 + .../codahale/hdrhistogram/.travis.yml | 5 + .../github.com/codahale/hdrhistogram/LICENSE | 21 + .../codahale/hdrhistogram/README.md | 15 + .../github.com/codahale/hdrhistogram/hdr.go | 564 + .../codahale/hdrhistogram/hdr_test.go | 388 + .../codahale/hdrhistogram/window.go | 45 + .../codahale/hdrhistogram/window_test.go | 64 + vendor/github.com/coreos/etcd/.dockerignore | 1 + vendor/github.com/coreos/etcd/.gitignore | 16 + vendor/github.com/coreos/etcd/.godir | 1 + vendor/github.com/coreos/etcd/.header | 13 + vendor/github.com/coreos/etcd/.semaphore.sh | 16 + vendor/github.com/coreos/etcd/.travis.yml | 88 + vendor/github.com/coreos/etcd/CONTRIBUTING.md | 62 + vendor/github.com/coreos/etcd/DCO | 36 + vendor/github.com/coreos/etcd/Dockerfile | 6 + .../github.com/coreos/etcd/Dockerfile-release | 17 + .../coreos/etcd/Dockerfile-release.arm64 | 11 + .../coreos/etcd/Dockerfile-release.ppc64le | 11 + vendor/github.com/coreos/etcd/Dockerfile-test | 57 + vendor/github.com/coreos/etcd/LICENSE | 202 + vendor/github.com/coreos/etcd/MAINTAINERS | 8 + vendor/github.com/coreos/etcd/NEWS | 106 + vendor/github.com/coreos/etcd/NOTICE | 5 + vendor/github.com/coreos/etcd/Procfile | 6 + vendor/github.com/coreos/etcd/README.md | 135 + vendor/github.com/coreos/etcd/ROADMAP.md | 23 + vendor/github.com/coreos/etcd/V2Procfile | 5 + .../coreos/etcd/bill-of-materials.json | 388 + .../etcd/bill-of-materials.override.json | 26 + vendor/github.com/coreos/etcd/build | 64 + vendor/github.com/coreos/etcd/build.bat | 1 + vendor/github.com/coreos/etcd/build.ps1 | 81 + .../github.com/coreos/etcd/client/README.md | 117 + .../coreos/etcd/client/auth_role.go | 237 + .../coreos/etcd/client/auth_user.go | 320 + .../coreos/etcd/client/cancelreq.go | 18 + .../github.com/coreos/etcd/client/client.go | 704 + .../coreos/etcd/client/client_test.go | 1074 + .../coreos/etcd/client/cluster_error.go | 37 + vendor/github.com/coreos/etcd/client/curl.go | 70 + .../github.com/coreos/etcd/client/discover.go | 40 + vendor/github.com/coreos/etcd/client/doc.go | 73 + .../coreos/etcd/client/fake_transport_test.go | 40 + .../coreos/etcd/client/keys.generated.go | 1087 + vendor/github.com/coreos/etcd/client/keys.go | 682 + .../coreos/etcd/client/keys_bench_test.go | 87 + .../coreos/etcd/client/keys_test.go | 1429 + .../github.com/coreos/etcd/client/members.go | 304 + .../coreos/etcd/client/members_test.go | 599 + vendor/github.com/coreos/etcd/client/util.go | 53 + vendor/github.com/coreos/etcd/cover | 31 + .../coreos/etcd/etcd.conf.yml.sample | 141 + vendor/github.com/coreos/etcd/glide.lock | 176 + vendor/github.com/coreos/etcd/glide.yaml | 134 + vendor/github.com/coreos/etcd/main.go | 29 + vendor/github.com/coreos/etcd/main_test.go | 35 + vendor/github.com/coreos/etcd/pkg/README.md | 2 + .../coreos/etcd/pkg/pathutil/path.go | 31 + .../coreos/etcd/pkg/pathutil/path_test.go | 38 + vendor/github.com/coreos/etcd/pkg/srv/srv.go | 140 + .../coreos/etcd/pkg/srv/srv_test.go | 200 + .../github.com/coreos/etcd/pkg/tlsutil/doc.go | 16 + .../coreos/etcd/pkg/tlsutil/tlsutil.go | 72 + .../coreos/etcd/pkg/transport/doc.go | 17 + .../etcd/pkg/transport/keepalive_listener.go | 94 + .../pkg/transport/keepalive_listener_test.go | 90 + .../coreos/etcd/pkg/transport/limit_listen.go | 80 + .../coreos/etcd/pkg/transport/listener.go | 260 + .../etcd/pkg/transport/listener_test.go | 282 + .../coreos/etcd/pkg/transport/listener_tls.go | 217 + .../coreos/etcd/pkg/transport/timeout_conn.go | 44 + .../etcd/pkg/transport/timeout_dialer.go | 36 + .../etcd/pkg/transport/timeout_dialer_test.go | 103 + .../etcd/pkg/transport/timeout_listener.go | 57 + .../pkg/transport/timeout_listener_test.go | 112 + .../etcd/pkg/transport/timeout_transport.go | 51 + .../pkg/transport/timeout_transport_test.go | 85 + .../coreos/etcd/pkg/transport/tls.go | 49 + .../coreos/etcd/pkg/transport/transport.go | 71 + .../etcd/pkg/transport/unix_listener.go | 40 + .../github.com/coreos/etcd/pkg/types/doc.go | 17 + vendor/github.com/coreos/etcd/pkg/types/id.go | 41 + .../coreos/etcd/pkg/types/id_test.go | 95 + .../github.com/coreos/etcd/pkg/types/set.go | 178 + .../coreos/etcd/pkg/types/set_test.go | 186 + .../github.com/coreos/etcd/pkg/types/slice.go | 22 + .../coreos/etcd/pkg/types/slice_test.go | 30 + .../github.com/coreos/etcd/pkg/types/urls.go | 82 + .../coreos/etcd/pkg/types/urls_test.go | 169 + .../coreos/etcd/pkg/types/urlsmap.go | 107 + .../coreos/etcd/pkg/types/urlsmap_test.go | 155 + vendor/github.com/coreos/etcd/test | 373 + .../github.com/coreos/etcd/version/version.go | 56 + vendor/github.com/coreos/go-oidc/.gitignore | 2 + vendor/github.com/coreos/go-oidc/.travis.yml | 16 + .../github.com/coreos/go-oidc/CONTRIBUTING.md | 71 + vendor/github.com/coreos/go-oidc/DCO | 36 + vendor/github.com/coreos/go-oidc/LICENSE | 202 + vendor/github.com/coreos/go-oidc/MAINTAINERS | 3 + vendor/github.com/coreos/go-oidc/NOTICE | 5 + vendor/github.com/coreos/go-oidc/README.md | 72 + vendor/github.com/coreos/go-oidc/gen.go | 150 + .../github.com/coreos/go-oidc/http/client.go | 7 + vendor/github.com/coreos/go-oidc/http/doc.go | 2 + vendor/github.com/coreos/go-oidc/http/http.go | 156 + .../coreos/go-oidc/http/http_test.go | 380 + vendor/github.com/coreos/go-oidc/http/url.go | 29 + .../coreos/go-oidc/http/url_test.go | 49 + vendor/github.com/coreos/go-oidc/jose.go | 20 + .../github.com/coreos/go-oidc/jose/claims.go | 126 + .../coreos/go-oidc/jose/claims_test.go | 328 + vendor/github.com/coreos/go-oidc/jose/doc.go | 2 + vendor/github.com/coreos/go-oidc/jose/jose.go | 112 + vendor/github.com/coreos/go-oidc/jose/jwk.go | 142 + .../coreos/go-oidc/jose/jwk_test.go | 64 + vendor/github.com/coreos/go-oidc/jose/jws.go | 51 + .../coreos/go-oidc/jose/jws_test.go | 74 + vendor/github.com/coreos/go-oidc/jose/jwt.go | 82 + .../coreos/go-oidc/jose/jwt_test.go | 94 + vendor/github.com/coreos/go-oidc/jose/sig.go | 24 + .../github.com/coreos/go-oidc/jose/sig_rsa.go | 67 + vendor/github.com/coreos/go-oidc/jose_test.go | 405 + vendor/github.com/coreos/go-oidc/jwks.go | 200 + vendor/github.com/coreos/go-oidc/jwks_test.go | 99 + vendor/github.com/coreos/go-oidc/key/doc.go | 2 + vendor/github.com/coreos/go-oidc/key/key.go | 153 + .../github.com/coreos/go-oidc/key/key_test.go | 103 + .../github.com/coreos/go-oidc/key/manager.go | 99 + .../coreos/go-oidc/key/manager_test.go | 225 + vendor/github.com/coreos/go-oidc/key/repo.go | 55 + .../github.com/coreos/go-oidc/key/rotate.go | 159 + .../coreos/go-oidc/key/rotate_test.go | 311 + vendor/github.com/coreos/go-oidc/key/sync.go | 91 + .../coreos/go-oidc/key/sync_test.go | 214 + .../github.com/coreos/go-oidc/oauth2/doc.go | 2 + .../github.com/coreos/go-oidc/oauth2/error.go | 29 + .../coreos/go-oidc/oauth2/oauth2.go | 416 + .../coreos/go-oidc/oauth2/oauth2_test.go | 518 + vendor/github.com/coreos/go-oidc/oidc.go | 299 + .../github.com/coreos/go-oidc/oidc/client.go | 846 + .../coreos/go-oidc/oidc/client_race_test.go | 81 + .../coreos/go-oidc/oidc/client_test.go | 654 + vendor/github.com/coreos/go-oidc/oidc/doc.go | 2 + .../coreos/go-oidc/oidc/identity.go | 44 + .../coreos/go-oidc/oidc/identity_test.go | 113 + .../coreos/go-oidc/oidc/interface.go | 3 + vendor/github.com/coreos/go-oidc/oidc/key.go | 67 + .../coreos/go-oidc/oidc/provider.go | 690 + .../coreos/go-oidc/oidc/provider_test.go | 940 + .../coreos/go-oidc/oidc/transport.go | 88 + .../coreos/go-oidc/oidc/transport_test.go | 176 + vendor/github.com/coreos/go-oidc/oidc/util.go | 109 + .../coreos/go-oidc/oidc/util_test.go | 110 + .../coreos/go-oidc/oidc/verification.go | 190 + .../coreos/go-oidc/oidc/verification_test.go | 380 + vendor/github.com/coreos/go-oidc/oidc_test.go | 21 + vendor/github.com/coreos/go-oidc/test | 15 + vendor/github.com/coreos/go-oidc/verify.go | 263 + .../github.com/coreos/go-oidc/verify_test.go | 265 + .../github.com/coreos/go-semver/.travis.yml | 8 + vendor/github.com/coreos/go-semver/LICENSE | 202 + vendor/github.com/coreos/go-semver/README.md | 28 + vendor/github.com/coreos/go-semver/example.go | 20 + .../coreos/go-semver/semver/semver.go | 268 + .../coreos/go-semver/semver/semver_test.go | 370 + .../coreos/go-semver/semver/sort.go | 38 + vendor/github.com/coreos/pkg/.gitignore | 27 + vendor/github.com/coreos/pkg/.travis.yml | 8 + vendor/github.com/coreos/pkg/CONTRIBUTING.md | 71 + vendor/github.com/coreos/pkg/DCO | 36 + vendor/github.com/coreos/pkg/LICENSE | 202 + vendor/github.com/coreos/pkg/MAINTAINERS | 1 + vendor/github.com/coreos/pkg/NOTICE | 5 + vendor/github.com/coreos/pkg/README.md | 4 + vendor/github.com/coreos/pkg/build | 3 + vendor/github.com/coreos/pkg/health/README.md | 11 + vendor/github.com/coreos/pkg/health/health.go | 127 + .../coreos/pkg/health/health_test.go | 198 + .../github.com/coreos/pkg/httputil/README.md | 13 + .../github.com/coreos/pkg/httputil/cookie.go | 21 + .../coreos/pkg/httputil/cookie_test.go | 51 + vendor/github.com/coreos/pkg/httputil/json.go | 27 + .../coreos/pkg/httputil/json_test.go | 56 + vendor/github.com/coreos/pkg/test | 56 + .../github.com/coreos/pkg/timeutil/backoff.go | 15 + .../coreos/pkg/timeutil/backoff_test.go | 52 + vendor/github.com/docker/docker/.DEREK.yml | 17 + vendor/github.com/docker/docker/.dockerignore | 7 + vendor/github.com/docker/docker/.gitignore | 22 + vendor/github.com/docker/docker/.mailmap | 422 + vendor/github.com/docker/docker/AUTHORS | 1909 + vendor/github.com/docker/docker/CHANGELOG.md | 3587 + .../github.com/docker/docker/CONTRIBUTING.md | 454 + vendor/github.com/docker/docker/Dockerfile | 196 + .../docker/docker/Dockerfile.aarch64 | 165 + .../github.com/docker/docker/Dockerfile.armhf | 153 + .../github.com/docker/docker/Dockerfile.e2e | 71 + .../docker/docker/Dockerfile.ppc64le | 149 + .../github.com/docker/docker/Dockerfile.s390x | 143 + .../docker/docker/Dockerfile.simple | 59 + .../docker/docker/Dockerfile.windows | 256 + vendor/github.com/docker/docker/LICENSE | 191 + vendor/github.com/docker/docker/MAINTAINERS | 467 + vendor/github.com/docker/docker/Makefile | 212 + vendor/github.com/docker/docker/NOTICE | 19 + vendor/github.com/docker/docker/README.md | 57 + vendor/github.com/docker/docker/ROADMAP.md | 68 + vendor/github.com/docker/docker/TESTING.md | 71 + vendor/github.com/docker/docker/VENDORING.md | 46 + vendor/github.com/docker/docker/pkg/README.md | 11 + .../docker/docker/pkg/term/ascii.go | 66 + .../docker/docker/pkg/term/ascii_test.go | 25 + .../docker/docker/pkg/term/proxy.go | 74 + .../docker/docker/pkg/term/proxy_test.go | 92 + .../github.com/docker/docker/pkg/term/tc.go | 20 + .../github.com/docker/docker/pkg/term/term.go | 124 + .../docker/docker/pkg/term/term_linux_test.go | 115 + .../docker/docker/pkg/term/term_windows.go | 230 + .../docker/docker/pkg/term/termios_bsd.go | 42 + .../docker/docker/pkg/term/termios_linux.go | 39 + .../docker/pkg/term/windows/ansi_reader.go | 263 + .../docker/pkg/term/windows/ansi_writer.go | 64 + .../docker/docker/pkg/term/windows/console.go | 35 + .../docker/docker/pkg/term/windows/windows.go | 33 + .../docker/pkg/term/windows/windows_test.go | 3 + .../docker/docker/pkg/term/winsize.go | 20 + vendor/github.com/docker/docker/poule.yml | 131 + vendor/github.com/docker/docker/vendor.conf | 154 + vendor/github.com/fatih/color/.travis.yml | 5 + vendor/github.com/fatih/color/LICENSE.md | 20 + vendor/github.com/fatih/color/README.md | 177 + vendor/github.com/fatih/color/color.go | 600 + vendor/github.com/fatih/color/color_test.go | 342 + vendor/github.com/fatih/color/doc.go | 133 + vendor/github.com/fatih/structs/.gitignore | 23 + vendor/github.com/fatih/structs/.travis.yml | 11 + vendor/github.com/fatih/structs/LICENSE | 21 + vendor/github.com/fatih/structs/README.md | 163 + vendor/github.com/fatih/structs/field.go | 141 + vendor/github.com/fatih/structs/field_test.go | 397 + vendor/github.com/fatih/structs/structs.go | 586 + .../fatih/structs/structs_example_test.go | 351 + .../github.com/fatih/structs/structs_test.go | 1453 + vendor/github.com/fatih/structs/tags.go | 32 + vendor/github.com/fatih/structs/tags_test.go | 46 + vendor/github.com/ghodss/yaml/.gitignore | 20 + vendor/github.com/ghodss/yaml/.travis.yml | 7 + vendor/github.com/ghodss/yaml/LICENSE | 50 + vendor/github.com/ghodss/yaml/README.md | 121 + vendor/github.com/ghodss/yaml/fields.go | 501 + vendor/github.com/ghodss/yaml/yaml.go | 277 + vendor/github.com/ghodss/yaml/yaml_test.go | 287 + vendor/github.com/go-ini/ini/.gitignore | 6 + vendor/github.com/go-ini/ini/.travis.yml | 15 + vendor/github.com/go-ini/ini/LICENSE | 191 + vendor/github.com/go-ini/ini/Makefile | 15 + vendor/github.com/go-ini/ini/README.md | 763 + vendor/github.com/go-ini/ini/README_ZH.md | 750 + vendor/github.com/go-ini/ini/bench_test.go | 118 + vendor/github.com/go-ini/ini/error.go | 32 + vendor/github.com/go-ini/ini/file.go | 398 + vendor/github.com/go-ini/ini/file_test.go | 355 + vendor/github.com/go-ini/ini/ini.go | 194 + .../go-ini/ini/ini_internal_test.go | 35 + vendor/github.com/go-ini/ini/ini_test.go | 336 + vendor/github.com/go-ini/ini/key.go | 751 + vendor/github.com/go-ini/ini/key_test.go | 523 + vendor/github.com/go-ini/ini/parser.go | 401 + vendor/github.com/go-ini/ini/parser_test.go | 77 + vendor/github.com/go-ini/ini/section.go | 257 + vendor/github.com/go-ini/ini/section_test.go | 313 + vendor/github.com/go-ini/ini/struct.go | 512 + vendor/github.com/go-ini/ini/struct_test.go | 387 + vendor/github.com/gokyle/hotp/LICENSE | 13 + vendor/github.com/gokyle/hotp/README.md | 192 + vendor/github.com/gokyle/hotp/doc.go | 27 + vendor/github.com/gokyle/hotp/hotp.go | 316 + vendor/github.com/gokyle/hotp/hotp_test.go | 452 + vendor/github.com/gokyle/hotp/rfc4226.txt | 2075 + vendor/github.com/golang/protobuf/.gitignore | 16 + vendor/github.com/golang/protobuf/.travis.yml | 18 + vendor/github.com/golang/protobuf/AUTHORS | 3 + .../github.com/golang/protobuf/CONTRIBUTORS | 3 + vendor/github.com/golang/protobuf/LICENSE | 31 + .../github.com/golang/protobuf/Make.protobuf | 40 + vendor/github.com/golang/protobuf/Makefile | 55 + vendor/github.com/golang/protobuf/README.md | 244 + .../github.com/golang/protobuf/proto/Makefile | 43 + .../golang/protobuf/proto/all_test.go | 2278 + .../golang/protobuf/proto/any_test.go | 300 + .../github.com/golang/protobuf/proto/clone.go | 229 + .../golang/protobuf/proto/clone_test.go | 300 + .../golang/protobuf/proto/decode.go | 970 + .../golang/protobuf/proto/decode_test.go | 258 + .../golang/protobuf/proto/encode.go | 1362 + .../golang/protobuf/proto/encode_test.go | 85 + .../github.com/golang/protobuf/proto/equal.go | 300 + .../golang/protobuf/proto/equal_test.go | 224 + .../golang/protobuf/proto/extensions.go | 587 + .../golang/protobuf/proto/extensions_test.go | 536 + .../github.com/golang/protobuf/proto/lib.go | 897 + .../golang/protobuf/proto/map_test.go | 46 + .../golang/protobuf/proto/message_set.go | 311 + .../golang/protobuf/proto/message_set_test.go | 66 + .../golang/protobuf/proto/pointer_reflect.go | 484 + .../golang/protobuf/proto/pointer_unsafe.go | 270 + .../golang/protobuf/proto/properties.go | 872 + .../golang/protobuf/proto/proto3_test.go | 135 + .../golang/protobuf/proto/size2_test.go | 63 + .../golang/protobuf/proto/size_test.go | 164 + .../github.com/golang/protobuf/proto/text.go | 854 + .../golang/protobuf/proto/text_parser.go | 895 + .../golang/protobuf/proto/text_parser_test.go | 673 + .../golang/protobuf/proto/text_test.go | 474 + .../golang/protobuf/protoc-gen-go/Makefile | 33 + .../protoc-gen-go/descriptor/Makefile | 37 + .../protoc-gen-go/descriptor/descriptor.pb.go | 2215 + .../protoc-gen-go/descriptor/descriptor.proto | 849 + .../golang/protobuf/protoc-gen-go/doc.go | 51 + .../protobuf/protoc-gen-go/link_grpc.go | 34 + .../golang/protobuf/protoc-gen-go/main.go | 98 + .../github.com/golang/protobuf/ptypes/any.go | 139 + .../golang/protobuf/ptypes/any/any.pb.go | 178 + .../golang/protobuf/ptypes/any/any.proto | 149 + .../golang/protobuf/ptypes/any_test.go | 113 + .../github.com/golang/protobuf/ptypes/doc.go | 35 + .../golang/protobuf/ptypes/duration.go | 102 + .../protobuf/ptypes/duration/duration.pb.go | 144 + .../protobuf/ptypes/duration/duration.proto | 117 + .../golang/protobuf/ptypes/duration_test.go | 121 + .../golang/protobuf/ptypes/empty/empty.pb.go | 66 + .../golang/protobuf/ptypes/empty/empty.proto | 52 + .../golang/protobuf/ptypes/regen.sh | 43 + .../golang/protobuf/ptypes/timestamp.go | 134 + .../protobuf/ptypes/timestamp/timestamp.pb.go | 160 + .../protobuf/ptypes/timestamp/timestamp.proto | 133 + .../golang/protobuf/ptypes/timestamp_test.go | 153 + .../gravitational/configure/.gitignore | 25 + .../gravitational/configure/LICENSE | 201 + .../gravitational/configure/Makefile | 13 + .../gravitational/configure/README.md | 43 + .../gravitational/configure/cidr.go | 88 + .../gravitational/configure/cidr_test.go | 39 + .../github.com/gravitational/configure/cli.go | 277 + .../gravitational/configure/cli_test.go | 59 + .../configure/cstrings/domain.go | 51 + .../gravitational/configure/cstrings/split.go | 103 + .../configure/cstrings/split_test.go | 122 + .../gravitational/configure/cstrings/user.go | 35 + .../github.com/gravitational/configure/doc.go | 48 + .../github.com/gravitational/configure/env.go | 143 + .../gravitational/configure/env_test.go | 53 + .../configure/jsonschema/schema.go | 206 + .../configure/jsonschema/schema_test.go | 155 + .../github.com/gravitational/configure/kv.go | 107 + .../gravitational/configure/test_test.go | 24 + .../github.com/gravitational/configure/tpl.go | 87 + .../gravitational/configure/yaml.go | 63 + .../gravitational/configure/yaml_test.go | 65 + .../github.com/gravitational/form/.gitignore | 24 + vendor/github.com/gravitational/form/LICENSE | 201 + vendor/github.com/gravitational/form/Makefile | 13 + .../github.com/gravitational/form/README.md | 9 + vendor/github.com/gravitational/form/form.go | 283 + .../gravitational/form/form_test.go | 215 + .../gravitational/form/shippable.yaml | 19 + .../gravitational/kingpin/.travis.yml | 4 + .../github.com/gravitational/kingpin/COPYING | 19 + .../gravitational/kingpin/README.md | 576 + .../gravitational/kingpin/actions.go | 42 + .../github.com/gravitational/kingpin/app.go | 569 + .../gravitational/kingpin/app_test.go | 223 + .../github.com/gravitational/kingpin/args.go | 118 + .../gravitational/kingpin/args_test.go | 57 + .../github.com/gravitational/kingpin/cmd.go | 194 + .../gravitational/kingpin/cmd_test.go | 176 + .../github.com/gravitational/kingpin/doc.go | 68 + .../gravitational/kingpin/examples_test.go | 46 + .../github.com/gravitational/kingpin/flags.go | 300 + .../gravitational/kingpin/flags_test.go | 209 + .../gravitational/kingpin/global.go | 94 + .../gravitational/kingpin/guesswidth.go | 9 + .../gravitational/kingpin/guesswidth_unix.go | 38 + .../github.com/gravitational/kingpin/model.go | 225 + .../gravitational/kingpin/parser.go | 374 + .../gravitational/kingpin/parser_test.go | 42 + .../gravitational/kingpin/parsers.go | 212 + .../gravitational/kingpin/parsers_test.go | 98 + .../gravitational/kingpin/templates.go | 233 + .../github.com/gravitational/kingpin/usage.go | 229 + .../gravitational/kingpin/usage_test.go | 65 + .../gravitational/kingpin/values.go | 466 + .../gravitational/kingpin/values.json | 25 + .../gravitational/kingpin/values_generated.go | 821 + .../gravitational/kingpin/values_test.go | 89 + .../gravitational/roundtrip/.gitignore | 24 + .../gravitational/roundtrip/LICENSE | 201 + .../gravitational/roundtrip/Makefile | 13 + .../gravitational/roundtrip/README.md | 7 + .../gravitational/roundtrip/client.go | 609 + .../gravitational/roundtrip/client_test.go | 526 + .../gravitational/roundtrip/creds.go | 103 + .../gravitational/roundtrip/creds_test.go | 137 + .../gravitational/roundtrip/errors.go | 70 + .../gravitational/roundtrip/reply.go | 36 + .../gravitational/roundtrip/seeker.go | 190 + .../gravitational/roundtrip/tracer.go | 118 + .../gravitational/teleport/.gitattributes | 6 + .../gravitational/teleport/.gitignore | 49 + .../gravitational/teleport/.gitmodules | 3 + .../gravitational/teleport/CHANGELOG.md | 316 + .../gravitational/teleport/CONTRIBUTING.md | 22 + .../gravitational/teleport/Gopkg.lock | 397 + .../gravitational/teleport/Gopkg.toml | 134 + .../github.com/gravitational/teleport/LICENSE | 201 + .../gravitational/teleport/Makefile | 233 + .../gravitational/teleport/README.md | 145 + .../gravitational/teleport/constants.go | 216 + .../github.com/gravitational/teleport/doc.go | 26 + .../teleport/integration/helpers.go | 666 + .../teleport/integration/integration.go | 19 + .../teleport/integration/integration_test.go | 928 + .../gravitational/teleport/lib/auth/api.go | 63 + .../teleport/lib/auth/apiserver.go | 1780 + .../teleport/lib/auth/apiserver_test.go | 626 + .../gravitational/teleport/lib/auth/auth.go | 838 + .../teleport/lib/auth/auth_test.go | 527 + .../teleport/lib/auth/auth_with_roles.go | 939 + .../gravitational/teleport/lib/auth/clt.go | 1759 + .../gravitational/teleport/lib/auth/init.go | 632 + .../teleport/lib/auth/init_test.go | 211 + .../teleport/lib/auth/native/native.go | 258 + .../teleport/lib/auth/native/native_test.go | 198 + .../teleport/lib/auth/new_web_user.go | 335 + .../gravitational/teleport/lib/auth/oidc.go | 575 + .../teleport/lib/auth/password.go | 163 + .../teleport/lib/auth/password_test.go | 99 + .../teleport/lib/auth/permissions.go | 297 + .../teleport/lib/auth/register.go | 112 + .../gravitational/teleport/lib/auth/saml.go | 358 + .../teleport/lib/auth/ssh_to_http.go | 110 + .../teleport/lib/auth/test/suite.go | 143 + .../lib/auth/testauthority/testauthority.go | 246 + .../teleport/lib/auth/trustedcluster.go | 475 + .../gravitational/teleport/lib/auth/tun.go | 1120 + .../teleport/lib/auth/tun_test.go | 694 + .../teleport/lib/backend/backend.go | 129 + .../teleport/lib/backend/backend_test.go | 38 + .../teleport/lib/backend/boltbk/boltbk.go | 383 + .../lib/backend/boltbk/boltbk_test.go | 73 + .../teleport/lib/backend/boltbk/doc.go | 5 + .../teleport/lib/backend/codec.go | 53 + .../teleport/lib/backend/dir/doc.go | 27 + .../teleport/lib/backend/dir/impl.go | 320 + .../teleport/lib/backend/dir/impl_test.go | 216 + .../gravitational/teleport/lib/backend/doc.go | 23 + .../teleport/lib/backend/dynamo/README.md | 64 + .../teleport/lib/backend/dynamo/doc.go | 13 + .../teleport/lib/backend/dynamo/dynamo.go | 17 + .../teleport/lib/backend/dynamo/dynamodbbk.go | 644 + .../lib/backend/dynamo/dynamodbbk_test.go | 113 + .../teleport/lib/backend/etcdbk/etcd.go | 275 + .../teleport/lib/backend/etcdbk/etcd_test.go | 116 + .../gravitational/teleport/lib/client/api.go | 1419 + .../teleport/lib/client/api_test.go | 159 + .../teleport/lib/client/bench.go | 230 + .../teleport/lib/client/client.go | 493 + .../teleport/lib/client/client_test.go | 111 + .../teleport/lib/client/hotp_mock.go | 87 + .../teleport/lib/client/https_client.go | 79 + .../teleport/lib/client/identity.go | 108 + .../teleport/lib/client/interfaces.go | 127 + .../teleport/lib/client/keyagent.go | 363 + .../teleport/lib/client/keyagent_test.go | 321 + .../teleport/lib/client/keystore.go | 337 + .../teleport/lib/client/keystore_test.go | 223 + .../teleport/lib/client/player.go | 217 + .../teleport/lib/client/profile.go | 160 + .../teleport/lib/client/profile_test.go | 72 + .../teleport/lib/client/session.go | 480 + .../teleport/lib/client/testdata_test.go | 69 + .../teleport/lib/client/weblogin.go | 479 + .../teleport/lib/defaults/defaults.go | 287 + .../teleport/lib/defaults/defaults_test.go | 49 + .../gravitational/teleport/lib/events/api.go | 205 + .../teleport/lib/events/api_test.go | 34 + .../teleport/lib/events/auditlog.go | 674 + .../teleport/lib/events/auditlog_test.go | 156 + .../teleport/lib/events/discard.go | 39 + .../gravitational/teleport/lib/events/mock.go | 91 + .../teleport/lib/events/slice.pb.go | 696 + .../teleport/lib/events/slice.proto | 25 + .../teleport/lib/httplib/csrf/csrf.go | 138 + .../teleport/lib/httplib/httpheaders.go | 88 + .../teleport/lib/httplib/httplib.go | 165 + .../teleport/lib/httplib/httplib_test.go | 76 + .../teleport/lib/limiter/connlimiter.go | 108 + .../teleport/lib/limiter/limiter.go | 82 + .../teleport/lib/limiter/limiter_test.go | 165 + .../teleport/lib/limiter/ratelimiter.go | 163 + .../teleport/lib/reversetunnel/agent.go | 415 + .../teleport/lib/reversetunnel/agentpool.go | 211 + .../teleport/lib/reversetunnel/api.go | 78 + .../teleport/lib/reversetunnel/localsite.go | 115 + .../teleport/lib/reversetunnel/remotesite.go | 265 + .../teleport/lib/reversetunnel/srv.go | 471 + .../teleport/lib/runtimeflags.go | 80 + .../gravitational/teleport/lib/service/cfg.go | 329 + .../teleport/lib/service/cfg_test.go | 77 + .../teleport/lib/service/service.go | 940 + .../teleport/lib/service/service_test.go | 48 + .../teleport/lib/service/supervisor.go | 256 + .../gravitational/teleport/lib/service/tpl.go | 70 + .../teleport/lib/services/authentication.go | 275 + .../teleport/lib/services/authority.go | 635 + .../teleport/lib/services/clustername.go | 219 + .../teleport/lib/services/configuration.go | 37 + .../teleport/lib/services/doc.go | 22 + .../teleport/lib/services/identity.go | 427 + .../teleport/lib/services/local/access.go | 129 + .../lib/services/local/configuration.go | 122 + .../lib/services/local/configuration_test.go | 83 + .../teleport/lib/services/local/doc.go | 20 + .../teleport/lib/services/local/presence.go | 346 + .../lib/services/local/presence_test.go | 119 + .../lib/services/local/provisioning.go | 98 + .../lib/services/local/services_test.go | 107 + .../teleport/lib/services/local/trust.go | 181 + .../teleport/lib/services/local/users.go | 827 + .../teleport/lib/services/map_test.go | 144 + .../teleport/lib/services/migrations_test.go | 309 + .../teleport/lib/services/namespace.go | 121 + .../teleport/lib/services/oidc.go | 677 + .../teleport/lib/services/oidc_test.go | 126 + .../teleport/lib/services/parser.go | 223 + .../teleport/lib/services/presence.go | 120 + .../teleport/lib/services/provisioning.go | 56 + .../teleport/lib/services/resource.go | 442 + .../teleport/lib/services/role.go | 1694 + .../teleport/lib/services/role_test.go | 708 + .../teleport/lib/services/saml.go | 842 + .../teleport/lib/services/saml_test.go | 57 + .../teleport/lib/services/server.go | 554 + .../teleport/lib/services/session.go | 443 + .../teleport/lib/services/statictokens.go | 250 + .../teleport/lib/services/trust.go | 102 + .../teleport/lib/services/trustedcluster.go | 519 + .../teleport/lib/services/tunnel.go | 304 + .../teleport/lib/services/user.go | 622 + .../teleport/lib/services/users_test.go | 52 + .../teleport/lib/session/session.go | 414 + .../teleport/lib/session/session_test.go | 207 + .../gravitational/teleport/lib/shell/shell.go | 87 + .../teleport/lib/shell/shell_test.go | 43 + .../gravitational/teleport/lib/srv/ctx.go | 211 + .../gravitational/teleport/lib/srv/exec.go | 422 + .../teleport/lib/srv/exec_test.go | 167 + .../gravitational/teleport/lib/srv/proxy.go | 374 + .../teleport/lib/srv/proxy_test.go | 98 + .../gravitational/teleport/lib/srv/sess.go | 964 + .../gravitational/teleport/lib/srv/sites.go | 74 + .../teleport/lib/srv/sshserver.go | 1210 + .../teleport/lib/srv/sshserver_test.go | 1008 + .../teleport/lib/srv/subsystem.go | 52 + .../gravitational/teleport/lib/srv/term.go | 176 + .../teleport/lib/sshutils/close.go | 36 + .../teleport/lib/sshutils/fingerprint.go | 31 + .../teleport/lib/sshutils/req.go | 90 + .../teleport/lib/sshutils/scp/scp.go | 496 + .../teleport/lib/sshutils/scp/scp_test.go | 281 + .../teleport/lib/sshutils/server.go | 464 + .../teleport/lib/sshutils/server_test.go | 137 + .../teleport/lib/sshutils/signer.go | 47 + .../teleport/lib/sshutils/tcpip.go | 38 + .../gravitational/teleport/lib/state/api.go | 31 + .../teleport/lib/state/cachingaccesspoint.go | 445 + .../lib/state/cachingaccesspoint_test.go | 227 + .../gravitational/teleport/lib/state/log.go | 418 + .../teleport/lib/state/log_test.go | 202 + .../teleport/lib/teleagent/agent.go | 115 + .../gravitational/teleport/lib/utils/addr.go | 335 + .../teleport/lib/utils/addr_test.go | 226 + .../teleport/lib/utils/broadcaster.go | 44 + .../gravitational/teleport/lib/utils/certs.go | 259 + .../teleport/lib/utils/certs_test.go | 45 + .../gravitational/teleport/lib/utils/cli.go | 216 + .../gravitational/teleport/lib/utils/conv.go | 62 + .../gravitational/teleport/lib/utils/copy.go | 76 + .../teleport/lib/utils/environment.go | 71 + .../teleport/lib/utils/environment_test.go | 66 + .../teleport/lib/utils/equals.go | 69 + .../teleport/lib/utils/fakeconn.go | 123 + .../gravitational/teleport/lib/utils/fs.go | 119 + .../teleport/lib/utils/jsontools.go | 51 + .../gravitational/teleport/lib/utils/node.go | 25 + .../gravitational/teleport/lib/utils/otp.go | 55 + .../teleport/lib/utils/parse/parse.go | 105 + .../teleport/lib/utils/parse/parse_test.go | 133 + .../teleport/lib/utils/proxy/proxy.go | 189 + .../teleport/lib/utils/proxy/proxy_test.go | 90 + .../gravitational/teleport/lib/utils/rand.go | 45 + .../teleport/lib/utils/roles_test.go | 70 + .../teleport/lib/utils/schema.go | 57 + .../teleport/lib/utils/signal.go | 20 + .../gravitational/teleport/lib/utils/srv.go | 40 + .../teleport/lib/utils/storage.go | 77 + .../gravitational/teleport/lib/utils/time.go | 46 + .../teleport/lib/utils/timeout.go | 66 + .../teleport/lib/utils/timeout_test.go | 99 + .../gravitational/teleport/lib/utils/tls.go | 158 + .../gravitational/teleport/lib/utils/utils.go | 241 + .../teleport/lib/utils/utils_test.go | 74 + .../teleport/lib/utils/websocketwriter.go | 123 + .../teleport/lib/web/apiserver.go | 1820 + .../teleport/lib/web/apiserver_test.go | 1443 + .../gravitational/teleport/lib/web/cookie.go | 77 + .../gravitational/teleport/lib/web/plugin.go | 45 + .../gravitational/teleport/lib/web/saml.go | 135 + .../teleport/lib/web/sessions.go | 721 + .../gravitational/teleport/lib/web/static.go | 206 + .../teleport/lib/web/static_test.go | 105 + .../gravitational/teleport/lib/web/stream.go | 169 + .../teleport/lib/web/terminal.go | 295 + .../teleport/lib/web/ui/server.go | 95 + .../teleport/lib/web/ui/usercontext.go | 115 + .../gravitational/teleport/mkdocs.yml | 22 + .../gravitational/teleport/roles.go | 164 + .../gravitational/teleport/version.go | 11 + .../gravitational/teleport/version.mk | 22 + .../github.com/gravitational/trace/.gitignore | 24 + vendor/github.com/gravitational/trace/LICENSE | 201 + .../github.com/gravitational/trace/README.md | 72 + .../github.com/gravitational/trace/errors.go | 448 + .../github.com/gravitational/trace/httplib.go | 129 + vendor/github.com/gravitational/trace/log.go | 240 + .../github.com/gravitational/trace/trace.go | 381 + .../gravitational/trace/trace_test.go | 471 + .../github.com/gravitational/trace/udphook.go | 112 + .../gravitational/trace/udphook_test.go | 46 + .../gravitational/ttlmap/.gitignore | 1 + .../gravitational/ttlmap/.travis.yml | 17 + .../github.com/gravitational/ttlmap/LICENSE | 202 + .../github.com/gravitational/ttlmap/Makefile | 21 + .../github.com/gravitational/ttlmap/README.md | 19 + .../github.com/gravitational/ttlmap/ttlmap.go | 254 + .../gravitational/ttlmap/ttlmap_test.go | 428 + .../grpc-ecosystem/grpc-gateway/.gitignore | 1 + .../grpc-ecosystem/grpc-gateway/.travis.yml | 34 + .../grpc-ecosystem/grpc-gateway/LICENSE.txt | 27 + .../grpc-ecosystem/grpc-gateway/Makefile | 143 + .../grpc-ecosystem/grpc-gateway/README.md | 224 + .../third_party/googleapis/LICENSE | 201 + .../googleapis/README.grcp-gateway | 22 + .../googleapis/google/api/annotations.pb.go | 61 + .../googleapis/google/api/annotations.proto | 29 + .../googleapis/google/api/http.pb.go | 360 + .../googleapis/google/api/http.proto | 127 + .../jmespath/go-jmespath/.gitignore | 4 + .../jmespath/go-jmespath/.travis.yml | 9 + .../github.com/jmespath/go-jmespath/LICENSE | 13 + .../github.com/jmespath/go-jmespath/Makefile | 44 + .../github.com/jmespath/go-jmespath/README.md | 7 + vendor/github.com/jmespath/go-jmespath/api.go | 49 + .../jmespath/go-jmespath/api_test.go | 32 + .../go-jmespath/astnodetype_string.go | 16 + .../jmespath/go-jmespath/compliance_test.go | 123 + .../jmespath/go-jmespath/functions.go | 842 + .../jmespath/go-jmespath/interpreter.go | 418 + .../jmespath/go-jmespath/interpreter_test.go | 221 + .../github.com/jmespath/go-jmespath/lexer.go | 420 + .../jmespath/go-jmespath/lexer_test.go | 161 + .../github.com/jmespath/go-jmespath/parser.go | 603 + .../jmespath/go-jmespath/parser_test.go | 136 + .../jmespath/go-jmespath/toktype_string.go | 16 + .../github.com/jmespath/go-jmespath/util.go | 185 + .../jmespath/go-jmespath/util_test.go | 73 + .../github.com/jonboulle/clockwork/.gitignore | 25 + .../jonboulle/clockwork/.travis.yml | 5 + vendor/github.com/jonboulle/clockwork/LICENSE | 201 + .../github.com/jonboulle/clockwork/README.md | 61 + .../jonboulle/clockwork/clockwork.go | 169 + .../jonboulle/clockwork/clockwork_test.go | 129 + .../jonboulle/clockwork/example_test.go | 49 + .../julienschmidt/httprouter/.travis.yml | 8 + .../julienschmidt/httprouter/LICENSE | 24 + .../julienschmidt/httprouter/README.md | 323 + .../julienschmidt/httprouter/path.go | 123 + .../julienschmidt/httprouter/path_test.go | 92 + .../julienschmidt/httprouter/router.go | 363 + .../julienschmidt/httprouter/router_test.go | 378 + .../julienschmidt/httprouter/tree.go | 555 + .../julienschmidt/httprouter/tree_test.go | 611 + vendor/github.com/kardianos/osext/LICENSE | 27 + vendor/github.com/kardianos/osext/README.md | 21 + vendor/github.com/kardianos/osext/osext.go | 33 + .../github.com/kardianos/osext/osext_go18.go | 9 + .../github.com/kardianos/osext/osext_plan9.go | 22 + .../kardianos/osext/osext_procfs.go | 36 + .../kardianos/osext/osext_sysctl.go | 126 + .../github.com/kardianos/osext/osext_test.go | 203 + .../kardianos/osext/osext_windows.go | 36 + vendor/github.com/kr/pty/.gitignore | 4 + vendor/github.com/kr/pty/License | 23 + vendor/github.com/kr/pty/README.md | 36 + vendor/github.com/kr/pty/doc.go | 16 + vendor/github.com/kr/pty/ioctl.go | 13 + vendor/github.com/kr/pty/ioctl_bsd.go | 39 + vendor/github.com/kr/pty/mktypes.bash | 19 + vendor/github.com/kr/pty/pty_darwin.go | 61 + vendor/github.com/kr/pty/pty_dragonfly.go | 76 + vendor/github.com/kr/pty/pty_freebsd.go | 73 + vendor/github.com/kr/pty/pty_linux.go | 46 + vendor/github.com/kr/pty/pty_unsupported.go | 11 + vendor/github.com/kr/pty/run.go | 34 + vendor/github.com/kr/pty/types.go | 10 + vendor/github.com/kr/pty/types_dragonfly.go | 17 + vendor/github.com/kr/pty/types_freebsd.go | 15 + vendor/github.com/kr/pty/util.go | 37 + vendor/github.com/kr/pty/ztypes_386.go | 9 + vendor/github.com/kr/pty/ztypes_amd64.go | 9 + vendor/github.com/kr/pty/ztypes_arm.go | 9 + vendor/github.com/kr/pty/ztypes_arm64.go | 11 + .../kr/pty/ztypes_dragonfly_amd64.go | 14 + .../github.com/kr/pty/ztypes_freebsd_386.go | 13 + .../github.com/kr/pty/ztypes_freebsd_amd64.go | 14 + .../github.com/kr/pty/ztypes_freebsd_arm.go | 13 + vendor/github.com/kr/pty/ztypes_mipsx.go | 12 + vendor/github.com/kr/pty/ztypes_ppc64.go | 11 + vendor/github.com/kr/pty/ztypes_ppc64le.go | 11 + vendor/github.com/kr/pty/ztypes_s390x.go | 11 + vendor/github.com/mailgun/holster/.gitignore | 31 + vendor/github.com/mailgun/holster/README.md | 399 + vendor/github.com/mailgun/holster/clock.go | 123 + .../github.com/mailgun/holster/clock_test.go | 134 + .../mailgun/holster/expire_cache.go | 194 + vendor/github.com/mailgun/holster/fanout.go | 93 + .../mailgun/holster/holster_test.go | 24 + .../github.com/mailgun/holster/lru_cache.go | 228 + .../mailgun/holster/lru_cache_test.go | 98 + vendor/github.com/mailgun/holster/misc.go | 73 + .../github.com/mailgun/holster/misc_test.go | 69 + .../mailgun/holster/priority_queue.go | 96 + .../mailgun/holster/priority_queue_test.go | 119 + vendor/github.com/mailgun/holster/random.go | 60 + .../github.com/mailgun/holster/set_default.go | 67 + .../mailgun/holster/set_default_test.go | 94 + vendor/github.com/mailgun/holster/ttlmap.go | 245 + .../github.com/mailgun/holster/ttlmap_test.go | 370 + .../github.com/mailgun/holster/waitgroup.go | 100 + .../mailgun/holster/waitgroup_test.go | 124 + vendor/github.com/mailgun/lemma/.gitignore | 24 + vendor/github.com/mailgun/lemma/HACKING.md | 22 + vendor/github.com/mailgun/lemma/LICENSE | 201 + vendor/github.com/mailgun/lemma/README.md | 18 + .../github.com/mailgun/lemma/random/README.md | 72 + .../github.com/mailgun/lemma/random/random.go | 98 + .../mailgun/lemma/random/random_test.go | 74 + .../github.com/mailgun/lemma/secret/README.md | 178 + .../mailgun/lemma/secret/constants.go | 4 + vendor/github.com/mailgun/lemma/secret/key.go | 62 + .../mailgun/lemma/secret/key_test.go | 94 + .../github.com/mailgun/lemma/secret/secret.go | 264 + .../mailgun/lemma/secret/secret_test.go | 66 + vendor/github.com/mailgun/metrics/.gitignore | 24 + vendor/github.com/mailgun/metrics/LICENSE | 201 + vendor/github.com/mailgun/metrics/LICENSE.md | 19 + vendor/github.com/mailgun/metrics/Makefile | 6 + vendor/github.com/mailgun/metrics/README.md | 17 + vendor/github.com/mailgun/metrics/client.go | 277 + .../github.com/mailgun/metrics/client_test.go | 224 + vendor/github.com/mailgun/metrics/metric.go | 79 + vendor/github.com/mailgun/metrics/nop.go | 61 + vendor/github.com/mailgun/metrics/sender.go | 123 + vendor/github.com/mailgun/minheap/.gitignore | 1 + vendor/github.com/mailgun/minheap/LICENSE | 202 + vendor/github.com/mailgun/minheap/Makefile | 21 + vendor/github.com/mailgun/minheap/README.md | 35 + vendor/github.com/mailgun/minheap/minheap.go | 75 + .../mailgun/minheap/minheap_test.go | 78 + vendor/github.com/mailgun/oxy/.gitignore | 26 + vendor/github.com/mailgun/oxy/LICENSE | 202 + vendor/github.com/mailgun/oxy/Makefile | 18 + vendor/github.com/mailgun/oxy/README.md | 109 + vendor/github.com/mailgun/oxy/forward/fwd.go | 170 + .../mailgun/oxy/forward/fwd_test.go | 304 + .../github.com/mailgun/oxy/forward/headers.go | 31 + .../github.com/mailgun/oxy/forward/rewrite.go | 43 + vendor/github.com/mailgun/oxy/utils/auth.go | 41 + .../github.com/mailgun/oxy/utils/auth_test.go | 62 + .../github.com/mailgun/oxy/utils/handler.go | 38 + .../mailgun/oxy/utils/handler_test.go | 34 + .../github.com/mailgun/oxy/utils/logging.go | 86 + .../github.com/mailgun/oxy/utils/netutils.go | 121 + .../mailgun/oxy/utils/netutils_test.go | 68 + vendor/github.com/mailgun/oxy/utils/source.go | 57 + vendor/github.com/mailgun/timetools/LICENSE | 202 + vendor/github.com/mailgun/timetools/README.md | 6 + .../github.com/mailgun/timetools/provider.go | 104 + .../mailgun/timetools/provider_test.go | 93 + .../mailgun/timetools/rfc2822time.go | 59 + vendor/github.com/mailgun/ttlmap/.gitignore | 1 + vendor/github.com/mailgun/ttlmap/.travis.yml | 10 + vendor/github.com/mailgun/ttlmap/LICENSE | 202 + vendor/github.com/mailgun/ttlmap/Makefile | 21 + vendor/github.com/mailgun/ttlmap/README.md | 26 + vendor/github.com/mailgun/ttlmap/ttlmap.go | 278 + .../github.com/mailgun/ttlmap/ttlmap_test.go | 353 + .../github.com/mattn/go-colorable/.travis.yml | 9 + vendor/github.com/mattn/go-colorable/LICENSE | 21 + .../github.com/mattn/go-colorable/README.md | 48 + .../mattn/go-colorable/colorable_appengine.go | 29 + .../mattn/go-colorable/colorable_others.go | 30 + .../mattn/go-colorable/colorable_test.go | 83 + .../mattn/go-colorable/colorable_windows.go | 884 + .../mattn/go-colorable/noncolorable.go | 55 + vendor/github.com/mattn/go-isatty/.travis.yml | 9 + vendor/github.com/mattn/go-isatty/LICENSE | 9 + vendor/github.com/mattn/go-isatty/README.md | 50 + vendor/github.com/mattn/go-isatty/doc.go | 2 + .../mattn/go-isatty/example_test.go | 18 + .../mattn/go-isatty/isatty_appengine.go | 15 + .../github.com/mattn/go-isatty/isatty_bsd.go | 18 + .../mattn/go-isatty/isatty_linux.go | 18 + .../mattn/go-isatty/isatty_linux_ppc64x.go | 19 + .../mattn/go-isatty/isatty_others.go | 10 + .../mattn/go-isatty/isatty_others_test.go | 19 + .../mattn/go-isatty/isatty_solaris.go | 16 + .../mattn/go-isatty/isatty_windows.go | 94 + .../mattn/go-isatty/isatty_windows_test.go | 35 + .../golang_protobuf_extensions/.travis.yml | 2 + .../golang_protobuf_extensions/LICENSE | 201 + .../golang_protobuf_extensions/NOTICE | 1 + .../golang_protobuf_extensions/README.md | 20 + .../pbutil/all_test.go | 177 + .../pbutil/decode.go | 75 + .../pbutil/decode_test.go | 99 + .../golang_protobuf_extensions/pbutil/doc.go | 16 + .../pbutil/encode.go | 46 + .../pbutil/encode_test.go | 67 + .../pbutil/fixtures_test.go | 103 + vendor/github.com/mdp/rsc/README.md | 2 + vendor/github.com/mdp/rsc/gf256/blog_test.go | 85 + vendor/github.com/mdp/rsc/gf256/gf256.go | 241 + vendor/github.com/mdp/rsc/gf256/gf256_test.go | 194 + vendor/github.com/mdp/rsc/qr/coding/gen.go | 149 + vendor/github.com/mdp/rsc/qr/coding/qr.go | 815 + .../github.com/mdp/rsc/qr/coding/qr_test.go | 133 + vendor/github.com/mdp/rsc/qr/png.go | 400 + vendor/github.com/mdp/rsc/qr/png_test.go | 73 + vendor/github.com/mdp/rsc/qr/qr.go | 116 + vendor/github.com/mdp/rsc/qr/x.png | Bin 0 -> 871 bytes vendor/github.com/moby/moby/.dockerignore | 4 + vendor/github.com/moby/moby/.gitignore | 33 + vendor/github.com/moby/moby/.mailmap | 275 + vendor/github.com/moby/moby/AUTHORS | 1652 + vendor/github.com/moby/moby/CHANGELOG.md | 3337 + vendor/github.com/moby/moby/CONTRIBUTING.md | 401 + vendor/github.com/moby/moby/Dockerfile | 246 + .../github.com/moby/moby/Dockerfile.aarch64 | 175 + vendor/github.com/moby/moby/Dockerfile.armhf | 182 + .../github.com/moby/moby/Dockerfile.ppc64le | 188 + vendor/github.com/moby/moby/Dockerfile.s390x | 190 + vendor/github.com/moby/moby/Dockerfile.simple | 73 + .../github.com/moby/moby/Dockerfile.solaris | 20 + .../github.com/moby/moby/Dockerfile.windows | 267 + vendor/github.com/moby/moby/LICENSE | 191 + vendor/github.com/moby/moby/MAINTAINERS | 376 + vendor/github.com/moby/moby/Makefile | 147 + vendor/github.com/moby/moby/NOTICE | 19 + vendor/github.com/moby/moby/README.md | 304 + vendor/github.com/moby/moby/ROADMAP.md | 118 + vendor/github.com/moby/moby/VENDORING.md | 45 + vendor/github.com/moby/moby/VERSION | 1 + vendor/github.com/moby/moby/pkg/README.md | 11 + vendor/github.com/moby/moby/pkg/term/ascii.go | 66 + .../moby/moby/pkg/term/ascii_test.go | 43 + .../moby/moby/pkg/term/tc_linux_cgo.go | 50 + .../github.com/moby/moby/pkg/term/tc_other.go | 20 + .../moby/moby/pkg/term/tc_solaris_cgo.go | 63 + vendor/github.com/moby/moby/pkg/term/term.go | 123 + .../moby/moby/pkg/term/term_solaris.go | 41 + .../moby/moby/pkg/term/term_unix.go | 29 + .../moby/moby/pkg/term/term_windows.go | 233 + .../moby/moby/pkg/term/termios_darwin.go | 69 + .../moby/moby/pkg/term/termios_freebsd.go | 69 + .../moby/moby/pkg/term/termios_linux.go | 47 + .../moby/moby/pkg/term/termios_openbsd.go | 69 + vendor/github.com/moby/moby/poule.yml | 88 + vendor/github.com/moby/moby/vendor.conf | 140 + vendor/github.com/pborman/uuid/.travis.yml | 9 + .../github.com/pborman/uuid/CONTRIBUTING.md | 10 + vendor/github.com/pborman/uuid/CONTRIBUTORS | 1 + vendor/github.com/pborman/uuid/LICENSE | 27 + vendor/github.com/pborman/uuid/README.md | 13 + vendor/github.com/pborman/uuid/dce.go | 84 + vendor/github.com/pborman/uuid/doc.go | 8 + vendor/github.com/pborman/uuid/hash.go | 53 + vendor/github.com/pborman/uuid/marshal.go | 83 + .../github.com/pborman/uuid/marshal_test.go | 124 + vendor/github.com/pborman/uuid/node.go | 117 + vendor/github.com/pborman/uuid/seq_test.go | 66 + vendor/github.com/pborman/uuid/sql.go | 66 + vendor/github.com/pborman/uuid/sql_test.go | 96 + vendor/github.com/pborman/uuid/time.go | 132 + vendor/github.com/pborman/uuid/util.go | 43 + vendor/github.com/pborman/uuid/uuid.go | 201 + vendor/github.com/pborman/uuid/uuid_test.go | 543 + vendor/github.com/pborman/uuid/version1.go | 41 + vendor/github.com/pborman/uuid/version4.go | 25 + vendor/github.com/pkg/errors/.gitignore | 24 + vendor/github.com/pkg/errors/.travis.yml | 11 + vendor/github.com/pkg/errors/LICENSE | 23 + vendor/github.com/pkg/errors/README.md | 52 + vendor/github.com/pkg/errors/appveyor.yml | 32 + vendor/github.com/pkg/errors/bench_test.go | 59 + vendor/github.com/pkg/errors/errors.go | 269 + vendor/github.com/pkg/errors/errors_test.go | 226 + vendor/github.com/pkg/errors/example_test.go | 205 + vendor/github.com/pkg/errors/format_test.go | 535 + vendor/github.com/pkg/errors/stack.go | 178 + vendor/github.com/pkg/errors/stack_test.go | 292 + vendor/github.com/pquerna/otp/.travis.yml | 6 + vendor/github.com/pquerna/otp/LICENSE | 202 + vendor/github.com/pquerna/otp/NOTICE | 5 + vendor/github.com/pquerna/otp/README.md | 60 + vendor/github.com/pquerna/otp/doc.go | 70 + vendor/github.com/pquerna/otp/hotp/hotp.go | 188 + .../github.com/pquerna/otp/hotp/hotp_test.go | 162 + vendor/github.com/pquerna/otp/otp.go | 202 + vendor/github.com/pquerna/otp/otp_test.go | 55 + vendor/github.com/pquerna/otp/totp/totp.go | 193 + .../github.com/pquerna/otp/totp/totp_test.go | 146 + .../prometheus/client_golang/.gitignore | 26 + .../prometheus/client_golang/.travis.yml | 9 + .../prometheus/client_golang/AUTHORS.md | 18 + .../prometheus/client_golang/CHANGELOG.md | 109 + .../prometheus/client_golang/CONTRIBUTING.md | 18 + .../prometheus/client_golang/LICENSE | 201 + .../prometheus/client_golang/NOTICE | 23 + .../prometheus/client_golang/README.md | 45 + .../prometheus/client_golang/VERSION | 1 + .../client_golang/prometheus/.gitignore | 1 + .../client_golang/prometheus/README.md | 1 + .../prometheus/benchmark_test.go | 183 + .../client_golang/prometheus/collector.go | 75 + .../client_golang/prometheus/counter.go | 172 + .../client_golang/prometheus/counter_test.go | 58 + .../client_golang/prometheus/desc.go | 205 + .../client_golang/prometheus/doc.go | 181 + .../prometheus/example_clustermanager_test.go | 118 + .../client_golang/prometheus/examples_test.go | 751 + .../prometheus/expvar_collector.go | 119 + .../prometheus/expvar_collector_test.go | 97 + .../client_golang/prometheus/fnv.go | 29 + .../client_golang/prometheus/gauge.go | 140 + .../client_golang/prometheus/gauge_test.go | 182 + .../client_golang/prometheus/go_collector.go | 263 + .../prometheus/go_collector_test.go | 123 + .../client_golang/prometheus/histogram.go | 444 + .../prometheus/histogram_test.go | 326 + .../client_golang/prometheus/http.go | 490 + .../client_golang/prometheus/http_test.go | 121 + .../client_golang/prometheus/metric.go | 166 + .../client_golang/prometheus/metric_test.go | 35 + .../prometheus/process_collector.go | 142 + .../prometheus/process_collector_test.go | 58 + .../client_golang/prometheus/registry.go | 806 + .../client_golang/prometheus/registry_test.go | 545 + .../client_golang/prometheus/summary.go | 534 + .../client_golang/prometheus/summary_test.go | 347 + .../client_golang/prometheus/untyped.go | 138 + .../client_golang/prometheus/value.go | 234 + .../client_golang/prometheus/vec.go | 404 + .../client_golang/prometheus/vec_test.go | 312 + .../prometheus/client_model/.gitignore | 1 + .../prometheus/client_model/CONTRIBUTING.md | 18 + .../prometheus/client_model/LICENSE | 201 + .../prometheus/client_model/MAINTAINERS.md | 1 + .../prometheus/client_model/Makefile | 62 + .../github.com/prometheus/client_model/NOTICE | 5 + .../prometheus/client_model/README.md | 26 + .../prometheus/client_model/go/metrics.pb.go | 364 + .../prometheus/client_model/metrics.proto | 81 + .../prometheus/client_model/pom.xml | 130 + .../prometheus/client_model/setup.py | 23 + .../github.com/prometheus/common/.travis.yml | 6 + .../prometheus/common/CONTRIBUTING.md | 18 + vendor/github.com/prometheus/common/LICENSE | 201 + .../prometheus/common/MAINTAINERS.md | 1 + vendor/github.com/prometheus/common/NOTICE | 5 + vendor/github.com/prometheus/common/README.md | 12 + .../prometheus/common/expfmt/bench_test.go | 167 + .../prometheus/common/expfmt/decode.go | 429 + .../prometheus/common/expfmt/decode_test.go | 435 + .../prometheus/common/expfmt/encode.go | 88 + .../prometheus/common/expfmt/expfmt.go | 38 + .../prometheus/common/expfmt/fuzz.go | 36 + .../prometheus/common/expfmt/text_create.go | 303 + .../common/expfmt/text_create_test.go | 443 + .../prometheus/common/expfmt/text_parse.go | 757 + .../common/expfmt/text_parse_test.go | 593 + .../bitbucket.org/ww/goautoneg/README.txt | 67 + .../bitbucket.org/ww/goautoneg/autoneg.go | 162 + .../ww/goautoneg/autoneg_test.go | 33 + .../prometheus/common/model/alert.go | 136 + .../prometheus/common/model/alert_test.go | 118 + .../prometheus/common/model/fingerprinting.go | 105 + .../github.com/prometheus/common/model/fnv.go | 42 + .../prometheus/common/model/labels.go | 210 + .../prometheus/common/model/labels_test.go | 140 + .../prometheus/common/model/labelset.go | 169 + .../prometheus/common/model/metric.go | 103 + .../prometheus/common/model/metric_test.go | 132 + .../prometheus/common/model/model.go | 16 + .../prometheus/common/model/signature.go | 144 + .../prometheus/common/model/signature_test.go | 314 + .../prometheus/common/model/silence.go | 106 + .../prometheus/common/model/silence_test.go | 228 + .../prometheus/common/model/time.go | 264 + .../prometheus/common/model/time_test.go | 132 + .../prometheus/common/model/value.go | 416 + .../prometheus/common/model/value_test.go | 468 + .../github.com/prometheus/procfs/.travis.yml | 5 + .../prometheus/procfs/CONTRIBUTING.md | 18 + vendor/github.com/prometheus/procfs/LICENSE | 201 + .../prometheus/procfs/MAINTAINERS.md | 1 + vendor/github.com/prometheus/procfs/Makefile | 18 + vendor/github.com/prometheus/procfs/NOTICE | 7 + vendor/github.com/prometheus/procfs/README.md | 11 + .../github.com/prometheus/procfs/buddyinfo.go | 95 + .../prometheus/procfs/buddyinfo_test.go | 64 + vendor/github.com/prometheus/procfs/doc.go | 45 + vendor/github.com/prometheus/procfs/fs.go | 46 + .../github.com/prometheus/procfs/fs_test.go | 26 + vendor/github.com/prometheus/procfs/ipvs.go | 246 + .../github.com/prometheus/procfs/ipvs_test.go | 237 + vendor/github.com/prometheus/procfs/mdstat.go | 138 + .../prometheus/procfs/mdstat_test.go | 31 + .../prometheus/procfs/mountstats.go | 556 + .../prometheus/procfs/mountstats_test.go | 273 + vendor/github.com/prometheus/procfs/proc.go | 224 + .../github.com/prometheus/procfs/proc_io.go | 55 + .../prometheus/procfs/proc_io_test.go | 33 + .../prometheus/procfs/proc_limits.go | 137 + .../prometheus/procfs/proc_limits_test.go | 31 + .../github.com/prometheus/procfs/proc_stat.go | 175 + .../prometheus/procfs/proc_stat_test.go | 110 + .../github.com/prometheus/procfs/proc_test.go | 160 + vendor/github.com/prometheus/procfs/stat.go | 219 + .../github.com/prometheus/procfs/stat_test.go | 61 + vendor/github.com/prometheus/procfs/ttar | 264 + vendor/github.com/prometheus/procfs/xfrm.go | 187 + .../github.com/prometheus/procfs/xfrm_test.go | 66 + .../github.com/prometheus/procfs/xfs/parse.go | 359 + .../prometheus/procfs/xfs/parse_test.go | 442 + .../github.com/prometheus/procfs/xfs/xfs.go | 163 + .../russellhaering/gosaml2/.travis.yml | 12 + .../github.com/russellhaering/gosaml2/LICENSE | 175 + .../russellhaering/gosaml2/README.md | 34 + .../russellhaering/gosaml2/attribute.go | 19 + .../russellhaering/gosaml2/authn_request.go | 16 + .../russellhaering/gosaml2/build_request.go | 164 + .../gosaml2/build_request_test.go | 117 + .../russellhaering/gosaml2/decode_response.go | 216 + .../gosaml2/decode_response_test.go | 106 + .../gosaml2/retrieve_assertion.go | 93 + .../github.com/russellhaering/gosaml2/saml.go | 92 + .../russellhaering/gosaml2/saml2_test.go | 70 + .../russellhaering/gosaml2/saml_test.go | 250 + .../russellhaering/gosaml2/test_constants.go | 376 + .../gosaml2/types/encrypted_assertion.go | 72 + .../gosaml2/types/encrypted_key.go | 109 + .../russellhaering/gosaml2/types/metadata.go | 39 + .../russellhaering/gosaml2/types/response.go | 118 + .../russellhaering/gosaml2/validate.go | 218 + .../russellhaering/gosaml2/xml_constants.go | 54 + .../russellhaering/goxmldsig/.travis.yml | 6 + .../russellhaering/goxmldsig/LICENSE | 175 + .../russellhaering/goxmldsig/README.md | 90 + .../russellhaering/goxmldsig/canonicalize.go | 128 + .../goxmldsig/canonicalize_test.go | 66 + .../russellhaering/goxmldsig/clock.go | 55 + .../goxmldsig/etreeutils/canonicalize.go | 98 + .../goxmldsig/etreeutils/namespace.go | 328 + .../goxmldsig/etreeutils/sort.go | 66 + .../goxmldsig/etreeutils/unmarshal.go | 43 + .../russellhaering/goxmldsig/keystore.go | 63 + .../russellhaering/goxmldsig/run_test.sh | 12 + .../russellhaering/goxmldsig/sign.go | 211 + .../russellhaering/goxmldsig/sign_test.go | 140 + .../russellhaering/goxmldsig/tls_keystore.go | 34 + .../goxmldsig/types/signature.go | 93 + .../russellhaering/goxmldsig/validate.go | 419 + .../russellhaering/goxmldsig/validate_test.go | 205 + .../russellhaering/goxmldsig/xml_constants.go | 78 + vendor/github.com/satori/go.uuid/.travis.yml | 15 + vendor/github.com/satori/go.uuid/LICENSE | 20 + vendor/github.com/satori/go.uuid/README.md | 65 + .../satori/go.uuid/benchmarks_test.go | 121 + vendor/github.com/satori/go.uuid/uuid.go | 488 + vendor/github.com/satori/go.uuid/uuid_test.go | 633 + vendor/github.com/sirupsen/logrus/.gitignore | 1 + vendor/github.com/sirupsen/logrus/.travis.yml | 15 + .../github.com/sirupsen/logrus/CHANGELOG.md | 118 + vendor/github.com/sirupsen/logrus/LICENSE | 21 + vendor/github.com/sirupsen/logrus/README.md | 509 + vendor/github.com/sirupsen/logrus/alt_exit.go | 64 + .../sirupsen/logrus/alt_exit_test.go | 83 + .../github.com/sirupsen/logrus/appveyor.yml | 14 + vendor/github.com/sirupsen/logrus/doc.go | 26 + vendor/github.com/sirupsen/logrus/entry.go | 279 + .../github.com/sirupsen/logrus/entry_test.go | 77 + .../sirupsen/logrus/example_basic_test.go | 69 + .../sirupsen/logrus/example_hook_test.go | 35 + vendor/github.com/sirupsen/logrus/exported.go | 193 + .../github.com/sirupsen/logrus/formatter.go | 45 + .../sirupsen/logrus/formatter_bench_test.go | 101 + .../github.com/sirupsen/logrus/hook_test.go | 144 + vendor/github.com/sirupsen/logrus/hooks.go | 34 + .../sirupsen/logrus/hooks/syslog/README.md | 39 + .../sirupsen/logrus/hooks/syslog/syslog.go | 55 + .../logrus/hooks/syslog/syslog_test.go | 27 + .../sirupsen/logrus/json_formatter.go | 79 + .../sirupsen/logrus/json_formatter_test.go | 199 + vendor/github.com/sirupsen/logrus/logger.go | 323 + .../sirupsen/logrus/logger_bench_test.go | 61 + vendor/github.com/sirupsen/logrus/logrus.go | 143 + .../github.com/sirupsen/logrus/logrus_test.go | 386 + .../sirupsen/logrus/terminal_bsd.go | 10 + .../logrus/terminal_check_appengine.go | 11 + .../logrus/terminal_check_notappengine.go | 19 + .../sirupsen/logrus/terminal_linux.go | 14 + .../sirupsen/logrus/text_formatter.go | 178 + .../sirupsen/logrus/text_formatter_test.go | 141 + vendor/github.com/sirupsen/logrus/writer.go | 62 + vendor/github.com/tstranex/u2f/.gitignore | 4 + vendor/github.com/tstranex/u2f/LICENSE | 21 + vendor/github.com/tstranex/u2f/README.md | 78 + vendor/github.com/tstranex/u2f/auth.go | 126 + vendor/github.com/tstranex/u2f/auth_test.go | 36 + vendor/github.com/tstranex/u2f/certs.go | 89 + vendor/github.com/tstranex/u2f/messages.go | 70 + vendor/github.com/tstranex/u2f/register.go | 179 + .../github.com/tstranex/u2f/register_test.go | 100 + vendor/github.com/tstranex/u2f/u2f_test.go | 64 + vendor/github.com/tstranex/u2f/util.go | 125 + vendor/github.com/tstranex/u2f/util_test.go | 40 + vendor/github.com/ugorji/go/LICENSE | 22 + vendor/github.com/ugorji/go/README.md | 20 + vendor/github.com/ugorji/go/codec/0doc.go | 199 + vendor/github.com/ugorji/go/codec/README.md | 148 + vendor/github.com/ugorji/go/codec/binc.go | 922 + vendor/github.com/ugorji/go/codec/cbor.go | 585 + .../github.com/ugorji/go/codec/cbor_test.go | 205 + .../github.com/ugorji/go/codec/codec_test.go | 1459 + .../ugorji/go/codec/codecgen_test.go | 24 + vendor/github.com/ugorji/go/codec/decode.go | 2019 + vendor/github.com/ugorji/go/codec/encode.go | 1419 + .../ugorji/go/codec/fast-path.generated.go | 39365 +++++++++ .../ugorji/go/codec/fast-path.go.tmpl | 540 + .../ugorji/go/codec/fast-path.not.go | 32 + .../ugorji/go/codec/gen-dec-array.go.tmpl | 104 + .../ugorji/go/codec/gen-dec-map.go.tmpl | 58 + .../ugorji/go/codec/gen-helper.generated.go | 233 + .../ugorji/go/codec/gen-helper.go.tmpl | 364 + .../ugorji/go/codec/gen.generated.go | 175 + vendor/github.com/ugorji/go/codec/gen.go | 1989 + vendor/github.com/ugorji/go/codec/helper.go | 1271 + .../ugorji/go/codec/helper_internal.go | 242 + .../ugorji/go/codec/helper_not_unsafe.go | 20 + .../github.com/ugorji/go/codec/helper_test.go | 242 + .../ugorji/go/codec/helper_unsafe.go | 45 + vendor/github.com/ugorji/go/codec/json.go | 1213 + vendor/github.com/ugorji/go/codec/msgpack.go | 845 + vendor/github.com/ugorji/go/codec/noop.go | 213 + vendor/github.com/ugorji/go/codec/prebuild.go | 3 + vendor/github.com/ugorji/go/codec/prebuild.sh | 199 + vendor/github.com/ugorji/go/codec/py_test.go | 30 + vendor/github.com/ugorji/go/codec/rpc.go | 180 + vendor/github.com/ugorji/go/codec/simple.go | 519 + .../ugorji/go/codec/test-cbor-goldens.json | 639 + vendor/github.com/ugorji/go/codec/test.py | 126 + vendor/github.com/ugorji/go/codec/tests.sh | 80 + vendor/github.com/ugorji/go/codec/time.go | 233 + .../github.com/ugorji/go/codec/values_test.go | 203 + vendor/github.com/ugorji/go/msgpack.org.md | 47 + vendor/github.com/vulcand/oxy/.gitignore | 29 + vendor/github.com/vulcand/oxy/.travis.yml | 21 + vendor/github.com/vulcand/oxy/Gopkg.lock | 111 + vendor/github.com/vulcand/oxy/Gopkg.toml | 51 + vendor/github.com/vulcand/oxy/LICENSE | 202 + vendor/github.com/vulcand/oxy/Makefile | 25 + vendor/github.com/vulcand/oxy/README.md | 112 + .../vulcand/oxy/connlimit/connlimit.go | 134 + .../vulcand/oxy/connlimit/connlimit_test.go | 113 + .../vulcand/oxy/ratelimit/bucket.go | 125 + .../vulcand/oxy/ratelimit/bucket_test.go | 300 + .../vulcand/oxy/ratelimit/bucketset.go | 108 + .../vulcand/oxy/ratelimit/bucketset_test.go | 185 + .../vulcand/oxy/ratelimit/tokenlimiter.go | 237 + .../oxy/ratelimit/tokenlimiter_test.go | 325 + vendor/github.com/vulcand/oxy/utils/auth.go | 41 + .../github.com/vulcand/oxy/utils/auth_test.go | 62 + .../github.com/vulcand/oxy/utils/dumpreq.go | 60 + .../vulcand/oxy/utils/dumpreq_test.go | 36 + .../github.com/vulcand/oxy/utils/handler.go | 38 + .../vulcand/oxy/utils/handler_test.go | 34 + .../github.com/vulcand/oxy/utils/netutils.go | 159 + .../vulcand/oxy/utils/netutils_test.go | 94 + vendor/github.com/vulcand/oxy/utils/source.go | 57 + .../github.com/vulcand/predicate/.gitignore | 24 + vendor/github.com/vulcand/predicate/LICENSE | 202 + vendor/github.com/vulcand/predicate/Makefile | 13 + vendor/github.com/vulcand/predicate/README.md | 53 + vendor/github.com/vulcand/predicate/lib.go | 150 + vendor/github.com/vulcand/predicate/parse.go | 256 + .../vulcand/predicate/parse_test.go | 477 + .../github.com/vulcand/predicate/predicate.go | 84 + .../gojsonpointer/LICENSE-APACHE-2.0.txt | 202 + .../xeipuuv/gojsonpointer/README.md | 8 + .../xeipuuv/gojsonpointer/pointer.go | 190 + .../xeipuuv/gojsonpointer/pointer_test.go | 247 + .../gojsonreference/LICENSE-APACHE-2.0.txt | 202 + .../xeipuuv/gojsonreference/README.md | 10 + .../xeipuuv/gojsonreference/reference.go | 141 + .../xeipuuv/gojsonreference/reference_test.go | 378 + .../xeipuuv/gojsonschema/.gitignore | 1 + .../xeipuuv/gojsonschema/.travis.yml | 7 + .../gojsonschema/LICENSE-APACHE-2.0.txt | 202 + .../github.com/xeipuuv/gojsonschema/README.md | 294 + .../github.com/xeipuuv/gojsonschema/errors.go | 283 + .../xeipuuv/gojsonschema/format_checkers.go | 250 + .../gojsonschema/format_checkers_test.go | 23 + .../xeipuuv/gojsonschema/glide.yaml | 12 + .../xeipuuv/gojsonschema/internalLog.go | 37 + .../xeipuuv/gojsonschema/jsonContext.go | 72 + .../xeipuuv/gojsonschema/jsonLoader.go | 341 + .../xeipuuv/gojsonschema/locales.go | 286 + .../github.com/xeipuuv/gojsonschema/result.go | 172 + .../github.com/xeipuuv/gojsonschema/schema.go | 928 + .../xeipuuv/gojsonschema/schemaPool.go | 109 + .../gojsonschema/schemaReferencePool.go | 67 + .../xeipuuv/gojsonschema/schemaType.go | 83 + .../xeipuuv/gojsonschema/schema_test.go | 589 + .../xeipuuv/gojsonschema/subSchema.go | 227 + .../github.com/xeipuuv/gojsonschema/types.go | 58 + .../github.com/xeipuuv/gojsonschema/utils.go | 208 + .../xeipuuv/gojsonschema/utils_test.go | 64 + .../xeipuuv/gojsonschema/validation.go | 844 + vendor/golang.org/x/crypto/.gitattributes | 10 + vendor/golang.org/x/crypto/.gitignore | 2 + vendor/golang.org/x/crypto/AUTHORS | 3 + vendor/golang.org/x/crypto/CONTRIBUTING.md | 31 + vendor/golang.org/x/crypto/CONTRIBUTORS | 3 + vendor/golang.org/x/crypto/LICENSE | 27 + vendor/golang.org/x/crypto/PATENTS | 22 + vendor/golang.org/x/crypto/README | 3 + vendor/golang.org/x/crypto/bcrypt/base64.go | 35 + vendor/golang.org/x/crypto/bcrypt/bcrypt.go | 294 + .../golang.org/x/crypto/bcrypt/bcrypt_test.go | 226 + vendor/golang.org/x/crypto/blowfish/block.go | 159 + .../x/crypto/blowfish/blowfish_test.go | 274 + vendor/golang.org/x/crypto/blowfish/cipher.go | 91 + vendor/golang.org/x/crypto/blowfish/const.go | 199 + vendor/golang.org/x/crypto/codereview.cfg | 1 + .../x/crypto/curve25519/const_amd64.h | 8 + .../x/crypto/curve25519/const_amd64.s | 20 + .../x/crypto/curve25519/cswap_amd64.s | 88 + .../x/crypto/curve25519/curve25519.go | 841 + .../x/crypto/curve25519/curve25519_test.go | 29 + vendor/golang.org/x/crypto/curve25519/doc.go | 23 + .../x/crypto/curve25519/freeze_amd64.s | 73 + .../x/crypto/curve25519/ladderstep_amd64.s | 1377 + .../x/crypto/curve25519/mont25519_amd64.go | 240 + .../x/crypto/curve25519/mul_amd64.s | 169 + .../x/crypto/curve25519/square_amd64.s | 132 + vendor/golang.org/x/crypto/ed25519/ed25519.go | 181 + .../x/crypto/ed25519/ed25519_test.go | 183 + .../ed25519/internal/edwards25519/const.go | 1422 + .../internal/edwards25519/edwards25519.go | 1771 + .../x/crypto/nacl/secretbox/example_test.go | 53 + .../x/crypto/nacl/secretbox/secretbox.go | 149 + .../x/crypto/nacl/secretbox/secretbox_test.go | 91 + .../golang.org/x/crypto/poly1305/poly1305.go | 32 + .../x/crypto/poly1305/poly1305_test.go | 159 + .../golang.org/x/crypto/poly1305/sum_amd64.go | 22 + .../golang.org/x/crypto/poly1305/sum_amd64.s | 125 + .../golang.org/x/crypto/poly1305/sum_arm.go | 22 + vendor/golang.org/x/crypto/poly1305/sum_arm.s | 427 + .../golang.org/x/crypto/poly1305/sum_ref.go | 141 + .../x/crypto/salsa20/salsa/hsalsa20.go | 144 + .../x/crypto/salsa20/salsa/salsa2020_amd64.s | 889 + .../x/crypto/salsa20/salsa/salsa208.go | 199 + .../x/crypto/salsa20/salsa/salsa20_amd64.go | 23 + .../x/crypto/salsa20/salsa/salsa20_ref.go | 234 + .../x/crypto/salsa20/salsa/salsa_test.go | 35 + vendor/golang.org/x/crypto/salsa20/salsa20.go | 54 + .../x/crypto/salsa20/salsa20_test.go | 139 + .../golang.org/x/crypto/ssh/agent/client.go | 659 + .../x/crypto/ssh/agent/client_test.go | 343 + .../x/crypto/ssh/agent/example_test.go | 40 + .../golang.org/x/crypto/ssh/agent/forward.go | 103 + .../golang.org/x/crypto/ssh/agent/keyring.go | 215 + .../x/crypto/ssh/agent/keyring_test.go | 76 + .../golang.org/x/crypto/ssh/agent/server.go | 451 + .../x/crypto/ssh/agent/server_test.go | 207 + .../x/crypto/ssh/agent/testdata_test.go | 64 + .../golang.org/x/crypto/ssh/benchmark_test.go | 122 + vendor/golang.org/x/crypto/ssh/buffer.go | 98 + vendor/golang.org/x/crypto/ssh/buffer_test.go | 87 + vendor/golang.org/x/crypto/ssh/certs.go | 503 + vendor/golang.org/x/crypto/ssh/certs_test.go | 216 + vendor/golang.org/x/crypto/ssh/channel.go | 633 + vendor/golang.org/x/crypto/ssh/cipher.go | 627 + vendor/golang.org/x/crypto/ssh/cipher_test.go | 129 + vendor/golang.org/x/crypto/ssh/client.go | 211 + vendor/golang.org/x/crypto/ssh/client_auth.go | 475 + .../x/crypto/ssh/client_auth_test.go | 471 + vendor/golang.org/x/crypto/ssh/client_test.go | 39 + vendor/golang.org/x/crypto/ssh/common.go | 371 + vendor/golang.org/x/crypto/ssh/connection.go | 143 + vendor/golang.org/x/crypto/ssh/doc.go | 18 + .../golang.org/x/crypto/ssh/example_test.go | 262 + vendor/golang.org/x/crypto/ssh/handshake.go | 625 + .../golang.org/x/crypto/ssh/handshake_test.go | 527 + vendor/golang.org/x/crypto/ssh/kex.go | 540 + vendor/golang.org/x/crypto/ssh/kex_test.go | 50 + vendor/golang.org/x/crypto/ssh/keys.go | 905 + vendor/golang.org/x/crypto/ssh/keys_test.go | 474 + vendor/golang.org/x/crypto/ssh/mac.go | 61 + .../golang.org/x/crypto/ssh/mempipe_test.go | 110 + vendor/golang.org/x/crypto/ssh/messages.go | 758 + .../golang.org/x/crypto/ssh/messages_test.go | 288 + vendor/golang.org/x/crypto/ssh/mux.go | 330 + vendor/golang.org/x/crypto/ssh/mux_test.go | 505 + vendor/golang.org/x/crypto/ssh/server.go | 491 + vendor/golang.org/x/crypto/ssh/session.go | 627 + .../golang.org/x/crypto/ssh/session_test.go | 770 + vendor/golang.org/x/crypto/ssh/tcpip.go | 407 + vendor/golang.org/x/crypto/ssh/tcpip_test.go | 20 + .../x/crypto/ssh/terminal/terminal.go | 951 + .../x/crypto/ssh/terminal/terminal_test.go | 350 + .../golang.org/x/crypto/ssh/terminal/util.go | 119 + .../x/crypto/ssh/terminal/util_bsd.go | 12 + .../x/crypto/ssh/terminal/util_linux.go | 11 + .../x/crypto/ssh/terminal/util_plan9.go | 58 + .../x/crypto/ssh/terminal/util_solaris.go | 73 + .../x/crypto/ssh/terminal/util_windows.go | 155 + .../golang.org/x/crypto/ssh/testdata_test.go | 63 + vendor/golang.org/x/crypto/ssh/transport.go | 375 + .../golang.org/x/crypto/ssh/transport_test.go | 109 + vendor/golang.org/x/net/.gitattributes | 10 + vendor/golang.org/x/net/.gitignore | 2 + vendor/golang.org/x/net/AUTHORS | 3 + vendor/golang.org/x/net/CONTRIBUTING.md | 31 + vendor/golang.org/x/net/CONTRIBUTORS | 3 + vendor/golang.org/x/net/LICENSE | 27 + vendor/golang.org/x/net/PATENTS | 22 + vendor/golang.org/x/net/README.md | 16 + vendor/golang.org/x/net/codereview.cfg | 1 + vendor/golang.org/x/net/context/context.go | 56 + .../golang.org/x/net/context/context_test.go | 583 + vendor/golang.org/x/net/context/go17.go | 72 + vendor/golang.org/x/net/context/go19.go | 20 + vendor/golang.org/x/net/context/pre_go17.go | 300 + vendor/golang.org/x/net/context/pre_go19.go | 109 + .../x/net/context/withtimeout_test.go | 31 + vendor/golang.org/x/net/http2/.gitignore | 2 + vendor/golang.org/x/net/http2/Dockerfile | 51 + vendor/golang.org/x/net/http2/Makefile | 3 + vendor/golang.org/x/net/http2/README | 20 + vendor/golang.org/x/net/http2/ciphers.go | 641 + vendor/golang.org/x/net/http2/ciphers_test.go | 309 + .../x/net/http2/client_conn_pool.go | 256 + .../x/net/http2/configure_transport.go | 80 + vendor/golang.org/x/net/http2/databuffer.go | 146 + .../golang.org/x/net/http2/databuffer_test.go | 157 + vendor/golang.org/x/net/http2/errors.go | 133 + vendor/golang.org/x/net/http2/errors_test.go | 24 + vendor/golang.org/x/net/http2/flow.go | 50 + vendor/golang.org/x/net/http2/flow_test.go | 53 + vendor/golang.org/x/net/http2/frame.go | 1579 + vendor/golang.org/x/net/http2/frame_test.go | 1191 + vendor/golang.org/x/net/http2/go16.go | 16 + vendor/golang.org/x/net/http2/go17.go | 106 + vendor/golang.org/x/net/http2/go17_not18.go | 36 + vendor/golang.org/x/net/http2/go18.go | 56 + vendor/golang.org/x/net/http2/go18_test.go | 79 + vendor/golang.org/x/net/http2/go19.go | 16 + vendor/golang.org/x/net/http2/go19_test.go | 59 + vendor/golang.org/x/net/http2/gotrack.go | 170 + vendor/golang.org/x/net/http2/gotrack_test.go | 33 + vendor/golang.org/x/net/http2/headermap.go | 78 + vendor/golang.org/x/net/http2/hpack/encode.go | 240 + .../x/net/http2/hpack/encode_test.go | 386 + vendor/golang.org/x/net/http2/hpack/hpack.go | 490 + .../x/net/http2/hpack/hpack_test.go | 722 + .../golang.org/x/net/http2/hpack/huffman.go | 212 + vendor/golang.org/x/net/http2/hpack/tables.go | 479 + .../x/net/http2/hpack/tables_test.go | 214 + vendor/golang.org/x/net/http2/http2.go | 391 + vendor/golang.org/x/net/http2/http2_test.go | 199 + vendor/golang.org/x/net/http2/not_go16.go | 21 + vendor/golang.org/x/net/http2/not_go17.go | 87 + vendor/golang.org/x/net/http2/not_go18.go | 29 + vendor/golang.org/x/net/http2/not_go19.go | 16 + vendor/golang.org/x/net/http2/pipe.go | 163 + vendor/golang.org/x/net/http2/pipe_test.go | 130 + vendor/golang.org/x/net/http2/server.go | 2888 + .../x/net/http2/server_push_test.go | 521 + vendor/golang.org/x/net/http2/server_test.go | 3725 + vendor/golang.org/x/net/http2/transport.go | 2284 + .../golang.org/x/net/http2/transport_test.go | 3847 + vendor/golang.org/x/net/http2/write.go | 365 + vendor/golang.org/x/net/http2/writesched.go | 242 + .../x/net/http2/writesched_priority.go | 452 + .../x/net/http2/writesched_priority_test.go | 541 + .../x/net/http2/writesched_random.go | 72 + .../x/net/http2/writesched_random_test.go | 44 + .../golang.org/x/net/http2/writesched_test.go | 125 + vendor/golang.org/x/net/http2/z_spec_test.go | 356 + vendor/golang.org/x/net/idna/example_test.go | 70 + vendor/golang.org/x/net/idna/idna.go | 732 + vendor/golang.org/x/net/idna/idna_test.go | 108 + vendor/golang.org/x/net/idna/punycode.go | 203 + vendor/golang.org/x/net/idna/punycode_test.go | 198 + vendor/golang.org/x/net/idna/tables.go | 4557 + vendor/golang.org/x/net/idna/trie.go | 72 + vendor/golang.org/x/net/idna/trieval.go | 119 + .../x/net/internal/timeseries/timeseries.go | 525 + .../internal/timeseries/timeseries_test.go | 170 + .../golang.org/x/net/lex/httplex/httplex.go | 351 + .../x/net/lex/httplex/httplex_test.go | 119 + vendor/golang.org/x/net/trace/events.go | 532 + vendor/golang.org/x/net/trace/histogram.go | 365 + .../golang.org/x/net/trace/histogram_test.go | 325 + vendor/golang.org/x/net/trace/trace.go | 1082 + vendor/golang.org/x/net/trace/trace_go16.go | 21 + vendor/golang.org/x/net/trace/trace_go17.go | 21 + vendor/golang.org/x/net/trace/trace_test.go | 178 + vendor/golang.org/x/net/websocket/client.go | 106 + vendor/golang.org/x/net/websocket/dial.go | 24 + .../golang.org/x/net/websocket/dial_test.go | 43 + .../x/net/websocket/exampledial_test.go | 31 + .../x/net/websocket/examplehandler_test.go | 26 + vendor/golang.org/x/net/websocket/hybi.go | 583 + .../golang.org/x/net/websocket/hybi_test.go | 608 + vendor/golang.org/x/net/websocket/server.go | 113 + .../golang.org/x/net/websocket/websocket.go | 448 + .../x/net/websocket/websocket_test.go | 665 + vendor/golang.org/x/sys/.gitattributes | 10 + vendor/golang.org/x/sys/.gitignore | 2 + vendor/golang.org/x/sys/AUTHORS | 3 + vendor/golang.org/x/sys/CONTRIBUTING.md | 31 + vendor/golang.org/x/sys/CONTRIBUTORS | 3 + vendor/golang.org/x/sys/LICENSE | 27 + vendor/golang.org/x/sys/PATENTS | 22 + vendor/golang.org/x/sys/README.md | 18 + vendor/golang.org/x/sys/codereview.cfg | 1 + vendor/golang.org/x/sys/unix/.gitignore | 1 + vendor/golang.org/x/sys/unix/README.md | 173 + vendor/golang.org/x/sys/unix/asm_darwin_386.s | 29 + .../golang.org/x/sys/unix/asm_darwin_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_darwin_arm.s | 30 + .../golang.org/x/sys/unix/asm_darwin_arm64.s | 30 + .../x/sys/unix/asm_dragonfly_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_386.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_arm.s | 29 + vendor/golang.org/x/sys/unix/asm_linux_386.s | 35 + .../golang.org/x/sys/unix/asm_linux_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_linux_arm.s | 29 + .../golang.org/x/sys/unix/asm_linux_arm64.s | 24 + .../golang.org/x/sys/unix/asm_linux_mips64x.s | 28 + .../golang.org/x/sys/unix/asm_linux_mipsx.s | 31 + .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 28 + .../golang.org/x/sys/unix/asm_linux_s390x.s | 28 + vendor/golang.org/x/sys/unix/asm_netbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_netbsd_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_netbsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_solaris_amd64.s | 17 + .../golang.org/x/sys/unix/bluetooth_linux.go | 35 + vendor/golang.org/x/sys/unix/cap_freebsd.go | 195 + vendor/golang.org/x/sys/unix/constants.go | 13 + vendor/golang.org/x/sys/unix/creds_test.go | 152 + vendor/golang.org/x/sys/unix/dev_darwin.go | 24 + .../golang.org/x/sys/unix/dev_darwin_test.go | 51 + vendor/golang.org/x/sys/unix/dev_dragonfly.go | 30 + .../x/sys/unix/dev_dragonfly_test.go | 50 + vendor/golang.org/x/sys/unix/dev_freebsd.go | 30 + vendor/golang.org/x/sys/unix/dev_linux.go | 42 + .../golang.org/x/sys/unix/dev_linux_test.go | 53 + vendor/golang.org/x/sys/unix/dev_netbsd.go | 29 + .../golang.org/x/sys/unix/dev_netbsd_test.go | 50 + vendor/golang.org/x/sys/unix/dev_openbsd.go | 29 + .../golang.org/x/sys/unix/dev_openbsd_test.go | 54 + .../golang.org/x/sys/unix/dev_solaris_test.go | 51 + vendor/golang.org/x/sys/unix/dirent.go | 102 + vendor/golang.org/x/sys/unix/endian_big.go | 9 + vendor/golang.org/x/sys/unix/endian_little.go | 9 + vendor/golang.org/x/sys/unix/env_unix.go | 27 + vendor/golang.org/x/sys/unix/env_unset.go | 14 + .../x/sys/unix/errors_freebsd_386.go | 227 + .../x/sys/unix/errors_freebsd_amd64.go | 227 + .../x/sys/unix/errors_freebsd_arm.go | 226 + vendor/golang.org/x/sys/unix/export_test.go | 9 + vendor/golang.org/x/sys/unix/flock.go | 22 + .../x/sys/unix/flock_linux_32bit.go | 13 + vendor/golang.org/x/sys/unix/gccgo.go | 46 + vendor/golang.org/x/sys/unix/gccgo_c.c | 41 + .../x/sys/unix/gccgo_linux_amd64.go | 20 + vendor/golang.org/x/sys/unix/mkall.sh | 188 + vendor/golang.org/x/sys/unix/mkerrors.sh | 577 + vendor/golang.org/x/sys/unix/mkpost.go | 93 + vendor/golang.org/x/sys/unix/mksyscall.pl | 328 + .../x/sys/unix/mksyscall_solaris.pl | 289 + .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 264 + .../golang.org/x/sys/unix/mksysnum_darwin.pl | 39 + .../x/sys/unix/mksysnum_dragonfly.pl | 50 + .../golang.org/x/sys/unix/mksysnum_freebsd.pl | 50 + .../golang.org/x/sys/unix/mksysnum_netbsd.pl | 58 + .../golang.org/x/sys/unix/mksysnum_openbsd.pl | 50 + .../golang.org/x/sys/unix/mmap_unix_test.go | 35 + .../golang.org/x/sys/unix/openbsd_pledge.go | 38 + vendor/golang.org/x/sys/unix/openbsd_test.go | 113 + vendor/golang.org/x/sys/unix/pagesize_unix.go | 15 + vendor/golang.org/x/sys/unix/race.go | 30 + vendor/golang.org/x/sys/unix/race0.go | 25 + .../golang.org/x/sys/unix/sockcmsg_linux.go | 36 + vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 104 + vendor/golang.org/x/sys/unix/str.go | 26 + vendor/golang.org/x/sys/unix/syscall.go | 51 + vendor/golang.org/x/sys/unix/syscall_bsd.go | 653 + .../golang.org/x/sys/unix/syscall_bsd_test.go | 70 + .../golang.org/x/sys/unix/syscall_darwin.go | 612 + .../x/sys/unix/syscall_darwin_386.go | 68 + .../x/sys/unix/syscall_darwin_amd64.go | 68 + .../x/sys/unix/syscall_darwin_arm.go | 66 + .../x/sys/unix/syscall_darwin_arm64.go | 68 + .../x/sys/unix/syscall_dragonfly.go | 519 + .../x/sys/unix/syscall_dragonfly_amd64.go | 52 + .../golang.org/x/sys/unix/syscall_freebsd.go | 759 + .../x/sys/unix/syscall_freebsd_386.go | 52 + .../x/sys/unix/syscall_freebsd_amd64.go | 52 + .../x/sys/unix/syscall_freebsd_arm.go | 52 + .../x/sys/unix/syscall_freebsd_test.go | 297 + vendor/golang.org/x/sys/unix/syscall_linux.go | 1491 + .../x/sys/unix/syscall_linux_386.go | 391 + .../x/sys/unix/syscall_linux_amd64.go | 144 + .../x/sys/unix/syscall_linux_amd64_gc.go | 13 + .../x/sys/unix/syscall_linux_arm.go | 255 + .../x/sys/unix/syscall_linux_arm64.go | 186 + .../x/sys/unix/syscall_linux_mips64x.go | 206 + .../x/sys/unix/syscall_linux_mipsx.go | 231 + .../x/sys/unix/syscall_linux_ppc64x.go | 127 + .../x/sys/unix/syscall_linux_s390x.go | 320 + .../x/sys/unix/syscall_linux_sparc64.go | 143 + .../x/sys/unix/syscall_linux_test.go | 257 + .../golang.org/x/sys/unix/syscall_netbsd.go | 559 + .../x/sys/unix/syscall_netbsd_386.go | 33 + .../x/sys/unix/syscall_netbsd_amd64.go | 33 + .../x/sys/unix/syscall_netbsd_arm.go | 33 + .../golang.org/x/sys/unix/syscall_no_getwd.go | 11 + .../golang.org/x/sys/unix/syscall_openbsd.go | 359 + .../x/sys/unix/syscall_openbsd_386.go | 33 + .../x/sys/unix/syscall_openbsd_amd64.go | 33 + .../x/sys/unix/syscall_openbsd_arm.go | 33 + .../golang.org/x/sys/unix/syscall_solaris.go | 728 + .../x/sys/unix/syscall_solaris_amd64.go | 28 + .../x/sys/unix/syscall_solaris_test.go | 34 + vendor/golang.org/x/sys/unix/syscall_test.go | 60 + vendor/golang.org/x/sys/unix/syscall_unix.go | 293 + .../golang.org/x/sys/unix/syscall_unix_gc.go | 15 + .../x/sys/unix/syscall_unix_test.go | 398 + vendor/golang.org/x/sys/unix/timestruct.go | 62 + vendor/golang.org/x/sys/unix/types_darwin.go | 277 + .../golang.org/x/sys/unix/types_dragonfly.go | 274 + vendor/golang.org/x/sys/unix/types_freebsd.go | 396 + vendor/golang.org/x/sys/unix/types_netbsd.go | 264 + vendor/golang.org/x/sys/unix/types_openbsd.go | 276 + vendor/golang.org/x/sys/unix/types_solaris.go | 283 + .../x/sys/unix/zerrors_darwin_386.go | 1769 + .../x/sys/unix/zerrors_darwin_amd64.go | 1769 + .../x/sys/unix/zerrors_darwin_arm.go | 1769 + .../x/sys/unix/zerrors_darwin_arm64.go | 1769 + .../x/sys/unix/zerrors_dragonfly_amd64.go | 1575 + .../x/sys/unix/zerrors_freebsd_386.go | 1756 + .../x/sys/unix/zerrors_freebsd_amd64.go | 1757 + .../x/sys/unix/zerrors_freebsd_arm.go | 1765 + .../x/sys/unix/zerrors_linux_386.go | 2245 + .../x/sys/unix/zerrors_linux_amd64.go | 2246 + .../x/sys/unix/zerrors_linux_arm.go | 2250 + .../x/sys/unix/zerrors_linux_arm64.go | 2236 + .../x/sys/unix/zerrors_linux_mips.go | 2255 + .../x/sys/unix/zerrors_linux_mips64.go | 2255 + .../x/sys/unix/zerrors_linux_mips64le.go | 2255 + .../x/sys/unix/zerrors_linux_mipsle.go | 2255 + .../x/sys/unix/zerrors_linux_ppc64.go | 2308 + .../x/sys/unix/zerrors_linux_ppc64le.go | 2308 + .../x/sys/unix/zerrors_linux_s390x.go | 2307 + .../x/sys/unix/zerrors_linux_sparc64.go | 2142 + .../x/sys/unix/zerrors_netbsd_386.go | 1719 + .../x/sys/unix/zerrors_netbsd_amd64.go | 1709 + .../x/sys/unix/zerrors_netbsd_arm.go | 1698 + .../x/sys/unix/zerrors_openbsd_386.go | 1591 + .../x/sys/unix/zerrors_openbsd_amd64.go | 1590 + .../x/sys/unix/zerrors_openbsd_arm.go | 1593 + .../x/sys/unix/zerrors_solaris_amd64.go | 1489 + .../golang.org/x/sys/unix/zptrace386_linux.go | 80 + .../golang.org/x/sys/unix/zptracearm_linux.go | 41 + .../x/sys/unix/zptracemips_linux.go | 50 + .../x/sys/unix/zptracemipsle_linux.go | 50 + .../x/sys/unix/zsyscall_darwin_386.go | 1620 + .../x/sys/unix/zsyscall_darwin_amd64.go | 1620 + .../x/sys/unix/zsyscall_darwin_arm.go | 1620 + .../x/sys/unix/zsyscall_darwin_arm64.go | 1620 + .../x/sys/unix/zsyscall_dragonfly_amd64.go | 1461 + .../x/sys/unix/zsyscall_freebsd_386.go | 1905 + .../x/sys/unix/zsyscall_freebsd_amd64.go | 1905 + .../x/sys/unix/zsyscall_freebsd_arm.go | 1905 + .../x/sys/unix/zsyscall_linux_386.go | 1979 + .../x/sys/unix/zsyscall_linux_amd64.go | 2172 + .../x/sys/unix/zsyscall_linux_arm.go | 2081 + .../x/sys/unix/zsyscall_linux_arm64.go | 2029 + .../x/sys/unix/zsyscall_linux_mips.go | 2137 + .../x/sys/unix/zsyscall_linux_mips64.go | 2120 + .../x/sys/unix/zsyscall_linux_mips64le.go | 2120 + .../x/sys/unix/zsyscall_linux_mipsle.go | 2137 + .../x/sys/unix/zsyscall_linux_ppc64.go | 2183 + .../x/sys/unix/zsyscall_linux_ppc64le.go | 2183 + .../x/sys/unix/zsyscall_linux_s390x.go | 1963 + .../x/sys/unix/zsyscall_linux_sparc64.go | 1833 + .../x/sys/unix/zsyscall_netbsd_386.go | 1367 + .../x/sys/unix/zsyscall_netbsd_amd64.go | 1367 + .../x/sys/unix/zsyscall_netbsd_arm.go | 1367 + .../x/sys/unix/zsyscall_openbsd_386.go | 1425 + .../x/sys/unix/zsyscall_openbsd_amd64.go | 1425 + .../x/sys/unix/zsyscall_openbsd_arm.go | 1425 + .../x/sys/unix/zsyscall_solaris_amd64.go | 1642 + .../x/sys/unix/zsysctl_openbsd_386.go | 270 + .../x/sys/unix/zsysctl_openbsd_amd64.go | 270 + .../x/sys/unix/zsysctl_openbsd_arm.go | 270 + .../x/sys/unix/zsysnum_darwin_386.go | 436 + .../x/sys/unix/zsysnum_darwin_amd64.go | 436 + .../x/sys/unix/zsysnum_darwin_arm.go | 436 + .../x/sys/unix/zsysnum_darwin_arm64.go | 436 + .../x/sys/unix/zsysnum_dragonfly_amd64.go | 315 + .../x/sys/unix/zsysnum_freebsd_386.go | 353 + .../x/sys/unix/zsysnum_freebsd_amd64.go | 353 + .../x/sys/unix/zsysnum_freebsd_arm.go | 353 + .../x/sys/unix/zsysnum_linux_386.go | 390 + .../x/sys/unix/zsysnum_linux_amd64.go | 342 + .../x/sys/unix/zsysnum_linux_arm.go | 362 + .../x/sys/unix/zsysnum_linux_arm64.go | 286 + .../x/sys/unix/zsysnum_linux_mips.go | 375 + .../x/sys/unix/zsysnum_linux_mips64.go | 335 + .../x/sys/unix/zsysnum_linux_mips64le.go | 335 + .../x/sys/unix/zsysnum_linux_mipsle.go | 375 + .../x/sys/unix/zsysnum_linux_ppc64.go | 370 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 370 + .../x/sys/unix/zsysnum_linux_s390x.go | 333 + .../x/sys/unix/zsysnum_linux_sparc64.go | 348 + .../x/sys/unix/zsysnum_netbsd_386.go | 274 + .../x/sys/unix/zsysnum_netbsd_amd64.go | 274 + .../x/sys/unix/zsysnum_netbsd_arm.go | 274 + .../x/sys/unix/zsysnum_openbsd_386.go | 207 + .../x/sys/unix/zsysnum_openbsd_amd64.go | 207 + .../x/sys/unix/zsysnum_openbsd_arm.go | 213 + .../x/sys/unix/zsysnum_solaris_amd64.go | 13 + .../x/sys/unix/ztypes_darwin_386.go | 489 + .../x/sys/unix/ztypes_darwin_amd64.go | 499 + .../x/sys/unix/ztypes_darwin_arm.go | 490 + .../x/sys/unix/ztypes_darwin_arm64.go | 499 + .../x/sys/unix/ztypes_dragonfly_amd64.go | 482 + .../x/sys/unix/ztypes_freebsd_386.go | 549 + .../x/sys/unix/ztypes_freebsd_amd64.go | 552 + .../x/sys/unix/ztypes_freebsd_arm.go | 552 + .../golang.org/x/sys/unix/ztypes_linux_386.go | 794 + .../x/sys/unix/ztypes_linux_amd64.go | 812 + .../golang.org/x/sys/unix/ztypes_linux_arm.go | 783 + .../x/sys/unix/ztypes_linux_arm64.go | 791 + .../x/sys/unix/ztypes_linux_mips.go | 788 + .../x/sys/unix/ztypes_linux_mips64.go | 793 + .../x/sys/unix/ztypes_linux_mips64le.go | 793 + .../x/sys/unix/ztypes_linux_mipsle.go | 788 + .../x/sys/unix/ztypes_linux_ppc64.go | 801 + .../x/sys/unix/ztypes_linux_ppc64le.go | 801 + .../x/sys/unix/ztypes_linux_s390x.go | 818 + .../x/sys/unix/ztypes_linux_sparc64.go | 664 + .../x/sys/unix/ztypes_netbsd_386.go | 435 + .../x/sys/unix/ztypes_netbsd_amd64.go | 442 + .../x/sys/unix/ztypes_netbsd_arm.go | 440 + .../x/sys/unix/ztypes_openbsd_386.go | 480 + .../x/sys/unix/ztypes_openbsd_amd64.go | 487 + .../x/sys/unix/ztypes_openbsd_arm.go | 473 + .../x/sys/unix/ztypes_solaris_amd64.go | 459 + vendor/golang.org/x/text/.gitattributes | 10 + vendor/golang.org/x/text/.gitignore | 6 + vendor/golang.org/x/text/AUTHORS | 3 + vendor/golang.org/x/text/CONTRIBUTING.md | 31 + vendor/golang.org/x/text/CONTRIBUTORS | 3 + vendor/golang.org/x/text/LICENSE | 27 + vendor/golang.org/x/text/PATENTS | 22 + vendor/golang.org/x/text/README.md | 91 + vendor/golang.org/x/text/codereview.cfg | 1 + .../x/text/collate/build/builder.go | 702 + .../x/text/collate/build/builder_test.go | 290 + .../x/text/collate/build/colelem.go | 294 + .../x/text/collate/build/colelem_test.go | 215 + .../x/text/collate/build/contract.go | 309 + .../x/text/collate/build/contract_test.go | 266 + .../golang.org/x/text/collate/build/order.go | 393 + .../x/text/collate/build/order_test.go | 229 + .../golang.org/x/text/collate/build/table.go | 81 + .../golang.org/x/text/collate/build/trie.go | 290 + .../x/text/collate/build/trie_test.go | 107 + vendor/golang.org/x/text/collate/collate.go | 403 + .../golang.org/x/text/collate/collate_test.go | 482 + .../golang.org/x/text/collate/export_test.go | 51 + vendor/golang.org/x/text/collate/index.go | 32 + .../golang.org/x/text/collate/maketables.go | 553 + vendor/golang.org/x/text/collate/option.go | 239 + .../golang.org/x/text/collate/option_test.go | 209 + vendor/golang.org/x/text/collate/reg_test.go | 230 + vendor/golang.org/x/text/collate/sort.go | 81 + vendor/golang.org/x/text/collate/sort_test.go | 55 + .../golang.org/x/text/collate/table_test.go | 291 + vendor/golang.org/x/text/collate/tables.go | 73789 ++++++++++++++++ vendor/golang.org/x/text/doc.go | 13 + vendor/golang.org/x/text/encoding/encoding.go | 335 + .../x/text/encoding/encoding_test.go | 290 + .../x/text/encoding/example_test.go | 42 + .../text/encoding/internal/identifier/gen.go | 137 + .../internal/identifier/identifier.go | 81 + .../text/encoding/internal/identifier/mib.go | 1621 + .../x/text/encoding/internal/internal.go | 75 + .../x/text/encoding/unicode/override.go | 82 + .../x/text/encoding/unicode/unicode.go | 434 + .../x/text/encoding/unicode/unicode_test.go | 499 + vendor/golang.org/x/text/gen.go | 318 + .../x/text/internal/colltab/collate_test.go | 121 + .../x/text/internal/colltab/collelem.go | 371 + .../x/text/internal/colltab/collelem_test.go | 183 + .../x/text/internal/colltab/colltab.go | 105 + .../x/text/internal/colltab/colltab_test.go | 64 + .../x/text/internal/colltab/contract.go | 145 + .../x/text/internal/colltab/contract_test.go | 131 + .../x/text/internal/colltab/iter.go | 178 + .../x/text/internal/colltab/iter_test.go | 63 + .../x/text/internal/colltab/numeric.go | 236 + .../x/text/internal/colltab/numeric_test.go | 159 + .../x/text/internal/colltab/table.go | 275 + .../x/text/internal/colltab/trie.go | 159 + .../x/text/internal/colltab/trie_test.go | 106 + .../x/text/internal/colltab/weighter.go | 31 + .../x/text/internal/colltab/weighter_test.go | 42 + vendor/golang.org/x/text/internal/gen.go | 52 + vendor/golang.org/x/text/internal/gen/code.go | 351 + vendor/golang.org/x/text/internal/gen/gen.go | 281 + vendor/golang.org/x/text/internal/gen_test.go | 38 + vendor/golang.org/x/text/internal/internal.go | 51 + .../x/text/internal/internal_test.go | 38 + vendor/golang.org/x/text/internal/match.go | 67 + .../golang.org/x/text/internal/match_test.go | 56 + vendor/golang.org/x/text/internal/tables.go | 117 + vendor/golang.org/x/text/internal/tag/tag.go | 100 + .../x/text/internal/tag/tag_test.go | 67 + .../x/text/internal/triegen/compact.go | 58 + .../x/text/internal/triegen/data_test.go | 875 + .../internal/triegen/example_compact_test.go | 71 + .../x/text/internal/triegen/example_test.go | 148 + .../x/text/internal/triegen/gen_test.go | 68 + .../x/text/internal/triegen/print.go | 251 + .../x/text/internal/triegen/triegen.go | 494 + .../x/text/internal/ucd/example_test.go | 81 + vendor/golang.org/x/text/internal/ucd/ucd.go | 371 + .../x/text/internal/ucd/ucd_test.go | 105 + .../internal/utf8internal/utf8internal.go | 87 + vendor/golang.org/x/text/language/Makefile | 16 + vendor/golang.org/x/text/language/common.go | 16 + vendor/golang.org/x/text/language/coverage.go | 197 + .../x/text/language/coverage_test.go | 154 + vendor/golang.org/x/text/language/doc.go | 102 + .../x/text/language/examples_test.go | 413 + vendor/golang.org/x/text/language/gen.go | 1706 + .../golang.org/x/text/language/gen_common.go | 20 + .../golang.org/x/text/language/gen_index.go | 162 + vendor/golang.org/x/text/language/go1_1.go | 38 + vendor/golang.org/x/text/language/go1_2.go | 11 + .../x/text/language/httpexample_test.go | 48 + vendor/golang.org/x/text/language/index.go | 769 + vendor/golang.org/x/text/language/language.go | 907 + .../x/text/language/language_test.go | 911 + vendor/golang.org/x/text/language/lookup.go | 396 + .../golang.org/x/text/language/lookup_test.go | 457 + vendor/golang.org/x/text/language/match.go | 933 + .../golang.org/x/text/language/match_test.go | 505 + vendor/golang.org/x/text/language/parse.go | 859 + .../golang.org/x/text/language/parse_test.go | 517 + vendor/golang.org/x/text/language/tables.go | 3675 + vendor/golang.org/x/text/language/tags.go | 143 + vendor/golang.org/x/text/runes/cond.go | 187 + vendor/golang.org/x/text/runes/cond_test.go | 282 + .../golang.org/x/text/runes/example_test.go | 60 + vendor/golang.org/x/text/runes/runes.go | 355 + vendor/golang.org/x/text/runes/runes_test.go | 664 + .../x/text/secure/bidirule/bench_test.go | 54 + .../x/text/secure/bidirule/bidirule.go | 340 + .../x/text/secure/bidirule/bidirule_test.go | 851 + vendor/golang.org/x/text/secure/doc.go | 6 + .../x/text/transform/examples_test.go | 37 + .../golang.org/x/text/transform/transform.go | 705 + .../x/text/transform/transform_test.go | 1317 + vendor/golang.org/x/text/unicode/bidi/bidi.go | 198 + .../golang.org/x/text/unicode/bidi/bracket.go | 335 + vendor/golang.org/x/text/unicode/bidi/core.go | 1058 + .../x/text/unicode/bidi/core_test.go | 224 + vendor/golang.org/x/text/unicode/bidi/gen.go | 133 + .../x/text/unicode/bidi/gen_ranges.go | 57 + .../x/text/unicode/bidi/gen_trieval.go | 64 + vendor/golang.org/x/text/unicode/bidi/prop.go | 206 + .../x/text/unicode/bidi/ranges_test.go | 53 + .../golang.org/x/text/unicode/bidi/tables.go | 1813 + .../x/text/unicode/bidi/tables_test.go | 82 + .../golang.org/x/text/unicode/bidi/trieval.go | 60 + vendor/golang.org/x/text/unicode/cldr/base.go | 105 + vendor/golang.org/x/text/unicode/cldr/cldr.go | 130 + .../x/text/unicode/cldr/cldr_test.go | 27 + .../golang.org/x/text/unicode/cldr/collate.go | 359 + .../x/text/unicode/cldr/collate_test.go | 275 + .../x/text/unicode/cldr/data_test.go | 186 + .../golang.org/x/text/unicode/cldr/decode.go | 171 + .../x/text/unicode/cldr/examples_test.go | 21 + .../golang.org/x/text/unicode/cldr/makexml.go | 400 + .../golang.org/x/text/unicode/cldr/resolve.go | 602 + .../x/text/unicode/cldr/resolve_test.go | 368 + .../golang.org/x/text/unicode/cldr/slice.go | 144 + .../x/text/unicode/cldr/slice_test.go | 175 + vendor/golang.org/x/text/unicode/cldr/xml.go | 1487 + vendor/golang.org/x/text/unicode/doc.go | 8 + .../x/text/unicode/norm/composition.go | 508 + .../x/text/unicode/norm/composition_test.go | 130 + .../x/text/unicode/norm/example_iter_test.go | 82 + .../x/text/unicode/norm/example_test.go | 27 + .../x/text/unicode/norm/forminfo.go | 259 + .../x/text/unicode/norm/forminfo_test.go | 54 + .../golang.org/x/text/unicode/norm/input.go | 109 + vendor/golang.org/x/text/unicode/norm/iter.go | 457 + .../x/text/unicode/norm/iter_test.go | 98 + .../x/text/unicode/norm/maketables.go | 976 + .../x/text/unicode/norm/normalize.go | 609 + .../x/text/unicode/norm/normalize_test.go | 1287 + .../x/text/unicode/norm/readwriter.go | 125 + .../x/text/unicode/norm/readwriter_test.go | 56 + .../golang.org/x/text/unicode/norm/tables.go | 7651 ++ .../x/text/unicode/norm/transform.go | 88 + .../x/text/unicode/norm/transform_test.go | 101 + vendor/golang.org/x/text/unicode/norm/trie.go | 54 + .../golang.org/x/text/unicode/norm/triegen.go | 117 + .../x/text/unicode/norm/ucd_test.go | 275 + .../x/text/unicode/rangetable/gen.go | 115 + .../x/text/unicode/rangetable/merge.go | 260 + .../x/text/unicode/rangetable/merge_test.go | 184 + .../x/text/unicode/rangetable/rangetable.go | 70 + .../unicode/rangetable/rangetable_test.go | 55 + .../x/text/unicode/rangetable/tables.go | 6376 ++ vendor/google.golang.org/genproto/.travis.yml | 12 + .../genproto/CONTRIBUTING.md | 27 + vendor/google.golang.org/genproto/LICENSE | 202 + vendor/google.golang.org/genproto/README.md | 28 + .../googleapis/rpc/status/status.pb.go | 143 + vendor/google.golang.org/genproto/regen.go | 123 + vendor/google.golang.org/genproto/regen.sh | 77 + vendor/google.golang.org/grpc/.please-update | 0 vendor/google.golang.org/grpc/.travis.yml | 23 + vendor/google.golang.org/grpc/AUTHORS | 1 + vendor/google.golang.org/grpc/CONTRIBUTING.md | 32 + vendor/google.golang.org/grpc/LICENSE | 202 + vendor/google.golang.org/grpc/Makefile | 45 + vendor/google.golang.org/grpc/README.md | 46 + vendor/google.golang.org/grpc/backoff.go | 96 + vendor/google.golang.org/grpc/backoff_test.go | 29 + vendor/google.golang.org/grpc/balancer.go | 408 + .../grpc/balancer/balancer.go | 203 + .../grpc/balancer/roundrobin/roundrobin.go | 241 + .../balancer/roundrobin/roundrobin_test.go | 477 + .../grpc/balancer_conn_wrappers.go | 268 + .../grpc/balancer_switching_test.go | 133 + .../google.golang.org/grpc/balancer_test.go | 802 + .../grpc/balancer_v1_wrapper.go | 374 + vendor/google.golang.org/grpc/call.go | 344 + vendor/google.golang.org/grpc/call_test.go | 292 + vendor/google.golang.org/grpc/clientconn.go | 1172 + .../google.golang.org/grpc/clientconn_test.go | 359 + vendor/google.golang.org/grpc/codec.go | 102 + .../grpc/codec_benchmark_test.go | 99 + vendor/google.golang.org/grpc/codec_test.go | 128 + vendor/google.golang.org/grpc/codegen.sh | 17 + .../grpc/codes/code_string.go | 16 + vendor/google.golang.org/grpc/codes/codes.go | 144 + .../grpc/connectivity/connectivity.go | 72 + .../grpc/credentials/credentials.go | 219 + .../grpc/credentials/credentials_test.go | 206 + .../grpc/credentials/credentials_util_go17.go | 60 + .../grpc/credentials/credentials_util_go18.go | 38 + .../credentials/credentials_util_pre_go17.go | 57 + vendor/google.golang.org/grpc/doc.go | 24 + .../grpc/encoding/encoding.go | 61 + vendor/google.golang.org/grpc/go16.go | 98 + vendor/google.golang.org/grpc/go17.go | 99 + vendor/google.golang.org/grpc/grpclb.go | 704 + .../grpclb/grpc_lb_v1/messages/messages.pb.go | 615 + .../grpclb/grpc_lb_v1/messages/messages.proto | 155 + .../grpc/grpclb/grpclb_test.go | 902 + .../google.golang.org/grpc/grpclog/grpclog.go | 123 + .../google.golang.org/grpc/grpclog/logger.go | 83 + .../grpc/grpclog/loggerv2.go | 195 + .../grpc/grpclog/loggerv2_test.go | 62 + vendor/google.golang.org/grpc/interceptor.go | 75 + .../grpc/internal/internal.go | 27 + .../grpc/keepalive/keepalive.go | 65 + .../grpc/metadata/metadata.go | 137 + .../grpc/metadata/metadata_test.go | 71 + .../grpc/naming/dns_resolver.go | 290 + .../grpc/naming/dns_resolver_test.go | 315 + vendor/google.golang.org/grpc/naming/go17.go | 34 + .../grpc/naming/go17_test.go | 42 + vendor/google.golang.org/grpc/naming/go18.go | 28 + .../grpc/naming/go18_test.go | 41 + .../google.golang.org/grpc/naming/naming.go | 59 + vendor/google.golang.org/grpc/peer/peer.go | 51 + .../google.golang.org/grpc/picker_wrapper.go | 141 + .../grpc/picker_wrapper_test.go | 160 + vendor/google.golang.org/grpc/pickfirst.go | 105 + .../google.golang.org/grpc/pickfirst_test.go | 352 + vendor/google.golang.org/grpc/proxy.go | 130 + vendor/google.golang.org/grpc/proxy_test.go | 182 + .../grpc/resolver/dns/dns_resolver.go | 377 + .../grpc/resolver/dns/dns_resolver_test.go | 894 + .../grpc/resolver/dns/go17.go | 35 + .../grpc/resolver/dns/go17_test.go | 50 + .../grpc/resolver/dns/go18.go | 29 + .../grpc/resolver/dns/go18_test.go | 49 + .../grpc/resolver/passthrough/passthrough.go | 57 + .../grpc/resolver/resolver.go | 143 + .../grpc/resolver_conn_wrapper.go | 144 + .../grpc/resolver_conn_wrapper_test.go | 79 + vendor/google.golang.org/grpc/rpc_util.go | 515 + .../google.golang.org/grpc/rpc_util_test.go | 237 + vendor/google.golang.org/grpc/server.go | 1282 + vendor/google.golang.org/grpc/server_test.go | 124 + .../google.golang.org/grpc/service_config.go | 199 + .../grpc/service_config_test.go | 323 + .../google.golang.org/grpc/stats/handlers.go | 64 + vendor/google.golang.org/grpc/stats/stats.go | 294 + .../grpc/stats/stats_test.go | 1266 + .../google.golang.org/grpc/status/status.go | 168 + .../grpc/status/status_test.go | 261 + vendor/google.golang.org/grpc/stream.go | 714 + vendor/google.golang.org/grpc/tap/tap.go | 51 + vendor/google.golang.org/grpc/trace.go | 113 + .../grpc/transport/bdp_estimator.go | 140 + .../grpc/transport/control.go | 333 + .../google.golang.org/grpc/transport/go16.go | 45 + .../google.golang.org/grpc/transport/go17.go | 46 + .../grpc/transport/handler_server.go | 413 + .../grpc/transport/handler_server_test.go | 481 + .../grpc/transport/http2_client.go | 1371 + .../grpc/transport/http2_server.go | 1202 + .../grpc/transport/http_util.go | 489 + .../grpc/transport/http_util_test.go | 175 + .../google.golang.org/grpc/transport/log.go | 50 + .../grpc/transport/transport.go | 749 + .../grpc/transport/transport_test.go | 2264 + vendor/google.golang.org/grpc/vet.sh | 85 + vendor/gopkg.in/mgo.v2/.travis.yml | 45 + vendor/gopkg.in/mgo.v2/LICENSE | 25 + vendor/gopkg.in/mgo.v2/Makefile | 5 + vendor/gopkg.in/mgo.v2/README.md | 4 + vendor/gopkg.in/mgo.v2/auth.go | 467 + vendor/gopkg.in/mgo.v2/auth_test.go | 1180 + vendor/gopkg.in/mgo.v2/bson/LICENSE | 25 + vendor/gopkg.in/mgo.v2/bson/bson.go | 738 + vendor/gopkg.in/mgo.v2/bson/bson_test.go | 1832 + vendor/gopkg.in/mgo.v2/bson/decimal.go | 310 + vendor/gopkg.in/mgo.v2/bson/decimal_test.go | 4109 + vendor/gopkg.in/mgo.v2/bson/decode.go | 849 + vendor/gopkg.in/mgo.v2/bson/encode.go | 514 + vendor/gopkg.in/mgo.v2/bson/json.go | 380 + vendor/gopkg.in/mgo.v2/bson/json_test.go | 184 + vendor/gopkg.in/mgo.v2/bson/specdata_test.go | 241 + vendor/gopkg.in/mgo.v2/bulk.go | 351 + vendor/gopkg.in/mgo.v2/bulk_test.go | 504 + vendor/gopkg.in/mgo.v2/cluster.go | 682 + vendor/gopkg.in/mgo.v2/cluster_test.go | 2090 + vendor/gopkg.in/mgo.v2/doc.go | 31 + vendor/gopkg.in/mgo.v2/export_test.go | 33 + vendor/gopkg.in/mgo.v2/gridfs.go | 761 + vendor/gopkg.in/mgo.v2/gridfs_test.go | 708 + vendor/gopkg.in/mgo.v2/internal/json/LICENSE | 27 + .../mgo.v2/internal/json/bench_test.go | 223 + .../gopkg.in/mgo.v2/internal/json/decode.go | 1685 + .../mgo.v2/internal/json/decode_test.go | 1512 + .../gopkg.in/mgo.v2/internal/json/encode.go | 1256 + .../mgo.v2/internal/json/encode_test.go | 613 + .../mgo.v2/internal/json/example_test.go | 252 + .../mgo.v2/internal/json/extension.go | 95 + .../mgo.v2/internal/json/extension_test.go | 218 + vendor/gopkg.in/mgo.v2/internal/json/fold.go | 143 + .../mgo.v2/internal/json/fold_test.go | 116 + .../gopkg.in/mgo.v2/internal/json/indent.go | 141 + .../mgo.v2/internal/json/number_test.go | 133 + .../gopkg.in/mgo.v2/internal/json/scanner.go | 697 + .../mgo.v2/internal/json/scanner_test.go | 316 + .../gopkg.in/mgo.v2/internal/json/stream.go | 510 + .../mgo.v2/internal/json/stream_test.go | 418 + .../mgo.v2/internal/json/tagkey_test.go | 115 + vendor/gopkg.in/mgo.v2/internal/json/tags.go | 44 + .../mgo.v2/internal/json/tags_test.go | 28 + vendor/gopkg.in/mgo.v2/log.go | 133 + vendor/gopkg.in/mgo.v2/queue.go | 91 + vendor/gopkg.in/mgo.v2/queue_test.go | 101 + vendor/gopkg.in/mgo.v2/raceoff.go | 5 + vendor/gopkg.in/mgo.v2/raceon.go | 5 + vendor/gopkg.in/mgo.v2/saslimpl.go | 11 + vendor/gopkg.in/mgo.v2/saslstub.go | 11 + vendor/gopkg.in/mgo.v2/server.go | 463 + vendor/gopkg.in/mgo.v2/session.go | 4825 + vendor/gopkg.in/mgo.v2/session_test.go | 4236 + vendor/gopkg.in/mgo.v2/socket.go | 707 + vendor/gopkg.in/mgo.v2/stats.go | 147 + vendor/gopkg.in/mgo.v2/suite_test.go | 262 + vendor/gopkg.in/mgo.v2/syscall_test.go | 15 + .../gopkg.in/mgo.v2/syscall_windows_test.go | 11 + vendor/gopkg.in/yaml.v2/.travis.yml | 9 + vendor/gopkg.in/yaml.v2/LICENSE | 201 + vendor/gopkg.in/yaml.v2/LICENSE.libyaml | 31 + vendor/gopkg.in/yaml.v2/README.md | 133 + vendor/gopkg.in/yaml.v2/apic.go | 742 + vendor/gopkg.in/yaml.v2/decode.go | 685 + vendor/gopkg.in/yaml.v2/decode_test.go | 1032 + vendor/gopkg.in/yaml.v2/emitterc.go | 1684 + vendor/gopkg.in/yaml.v2/encode.go | 306 + vendor/gopkg.in/yaml.v2/encode_test.go | 501 + .../gopkg.in/yaml.v2/example_embedded_test.go | 41 + vendor/gopkg.in/yaml.v2/parserc.go | 1095 + vendor/gopkg.in/yaml.v2/readerc.go | 394 + vendor/gopkg.in/yaml.v2/resolve.go | 208 + vendor/gopkg.in/yaml.v2/scannerc.go | 2711 + vendor/gopkg.in/yaml.v2/sorter.go | 104 + vendor/gopkg.in/yaml.v2/suite_test.go | 12 + vendor/gopkg.in/yaml.v2/writerc.go | 89 + vendor/gopkg.in/yaml.v2/yaml.go | 357 + vendor/gopkg.in/yaml.v2/yamlh.go | 716 + vendor/gopkg.in/yaml.v2/yamlprivateh.go | 173 + 2416 files changed, 793675 insertions(+) create mode 100644 vendor/github.com/Azure/go-ansiterm/LICENSE create mode 100644 vendor/github.com/Azure/go-ansiterm/README.md create mode 100644 vendor/github.com/Azure/go-ansiterm/constants.go create mode 100644 vendor/github.com/Azure/go-ansiterm/context.go create mode 100644 vendor/github.com/Azure/go-ansiterm/csi_entry_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/csi_param_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/escape_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/event_handler.go create mode 100644 vendor/github.com/Azure/go-ansiterm/ground_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/osc_string_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser_actions.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser_test.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser_test_helpers_test.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser_test_utilities_test.go create mode 100644 vendor/github.com/Azure/go-ansiterm/states.go create mode 100644 vendor/github.com/Azure/go-ansiterm/test_event_handler_test.go create mode 100644 vendor/github.com/Azure/go-ansiterm/utilities.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/ansi.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/api.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/utilities.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go create mode 100644 vendor/github.com/alecthomas/template/LICENSE create mode 100644 vendor/github.com/alecthomas/template/README.md create mode 100644 vendor/github.com/alecthomas/template/doc.go create mode 100644 vendor/github.com/alecthomas/template/example_test.go create mode 100644 vendor/github.com/alecthomas/template/examplefiles_test.go create mode 100644 vendor/github.com/alecthomas/template/examplefunc_test.go create mode 100644 vendor/github.com/alecthomas/template/exec.go create mode 100644 vendor/github.com/alecthomas/template/exec_test.go create mode 100644 vendor/github.com/alecthomas/template/funcs.go create mode 100644 vendor/github.com/alecthomas/template/helper.go create mode 100644 vendor/github.com/alecthomas/template/multi_test.go create mode 100644 vendor/github.com/alecthomas/template/parse/lex.go create mode 100644 vendor/github.com/alecthomas/template/parse/lex_test.go create mode 100644 vendor/github.com/alecthomas/template/parse/node.go create mode 100644 vendor/github.com/alecthomas/template/parse/parse.go create mode 100644 vendor/github.com/alecthomas/template/parse/parse_test.go create mode 100644 vendor/github.com/alecthomas/template/template.go create mode 100644 vendor/github.com/alecthomas/units/COPYING create mode 100644 vendor/github.com/alecthomas/units/README.md create mode 100644 vendor/github.com/alecthomas/units/bytes.go create mode 100644 vendor/github.com/alecthomas/units/bytes_test.go create mode 100644 vendor/github.com/alecthomas/units/doc.go create mode 100644 vendor/github.com/alecthomas/units/si.go create mode 100644 vendor/github.com/alecthomas/units/util.go create mode 100644 vendor/github.com/aws/aws-sdk-go/.gitignore create mode 100644 vendor/github.com/aws/aws-sdk-go/.godoc_config create mode 100644 vendor/github.com/aws/aws-sdk-go/.travis.yml create mode 100644 vendor/github.com/aws/aws-sdk-go/CHANGELOG.md create mode 100644 vendor/github.com/aws/aws-sdk-go/CHANGELOG_PENDING.md create mode 100644 vendor/github.com/aws/aws-sdk-go/CONTRIBUTING.md create mode 100644 vendor/github.com/aws/aws-sdk-go/Gopkg.lock create mode 100644 vendor/github.com/aws/aws-sdk-go/Gopkg.toml create mode 100644 vendor/github.com/aws/aws-sdk-go/LICENSE.txt create mode 100644 vendor/github.com/aws/aws-sdk-go/Makefile create mode 100644 vendor/github.com/aws/aws-sdk-go/NOTICE.txt create mode 100644 vendor/github.com/aws/aws-sdk-go/README.md create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/client.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/client_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/logger.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/logger_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/config.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/config_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/context.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/context_1_6.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/context_1_7.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/context_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/convert_types.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_1_8_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/example_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/errors.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/logger.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/handlers_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/http_request_copy_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/http_request_retry_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_1_5_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_1_6_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_context_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_internal_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_resetbody_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/request_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/retryer_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_benchmark_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/validation.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/waiter_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/custom_ca_bundle_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/env_config_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/session.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/session_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/session/shared_config_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_1_5_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/options.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/types.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/types_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/url.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/url_1_7.go create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/version.go create mode 100644 vendor/github.com/aws/aws-sdk-go/buildspec.yml create mode 100644 vendor/github.com/aws/aws-sdk-go/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config.go create mode 100644 vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_other_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_windows_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/README.md create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_bench_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/unmarshal_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/protocol_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/rest_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/api.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc_custom.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_examples_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_examples_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/shared_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/errors.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/examples_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/service.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/dynamodb/waiters.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/generate.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/api.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/customizations_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/doc.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/errors.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/examples_test.go create mode 100644 vendor/github.com/aws/aws-sdk-go/service/sts/service.go create mode 100644 vendor/github.com/beevik/etree/.travis.yml create mode 100644 vendor/github.com/beevik/etree/CONTRIBUTORS create mode 100644 vendor/github.com/beevik/etree/LICENSE create mode 100644 vendor/github.com/beevik/etree/README.md create mode 100644 vendor/github.com/beevik/etree/etree.go create mode 100644 vendor/github.com/beevik/etree/etree_test.go create mode 100644 vendor/github.com/beevik/etree/example_test.go create mode 100644 vendor/github.com/beevik/etree/helpers.go create mode 100644 vendor/github.com/beevik/etree/path.go create mode 100644 vendor/github.com/beevik/etree/path_test.go create mode 100644 vendor/github.com/beorn7/perks/.gitignore create mode 100644 vendor/github.com/beorn7/perks/LICENSE create mode 100644 vendor/github.com/beorn7/perks/README.md create mode 100644 vendor/github.com/beorn7/perks/quantile/bench_test.go create mode 100644 vendor/github.com/beorn7/perks/quantile/example_test.go create mode 100644 vendor/github.com/beorn7/perks/quantile/exampledata.txt create mode 100644 vendor/github.com/beorn7/perks/quantile/stream.go create mode 100644 vendor/github.com/beorn7/perks/quantile/stream_test.go create mode 100644 vendor/github.com/boltdb/bolt/.gitignore create mode 100644 vendor/github.com/boltdb/bolt/LICENSE create mode 100644 vendor/github.com/boltdb/bolt/Makefile create mode 100644 vendor/github.com/boltdb/bolt/README.md create mode 100644 vendor/github.com/boltdb/bolt/appveyor.yml create mode 100644 vendor/github.com/boltdb/bolt/bolt_386.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_amd64.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_arm.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_arm64.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_linux.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_openbsd.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_ppc.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_ppc64.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_ppc64le.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_s390x.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_unix.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_unix_solaris.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_windows.go create mode 100644 vendor/github.com/boltdb/bolt/boltsync_unix.go create mode 100644 vendor/github.com/boltdb/bolt/bucket.go create mode 100644 vendor/github.com/boltdb/bolt/bucket_test.go create mode 100644 vendor/github.com/boltdb/bolt/cursor.go create mode 100644 vendor/github.com/boltdb/bolt/cursor_test.go create mode 100644 vendor/github.com/boltdb/bolt/db.go create mode 100644 vendor/github.com/boltdb/bolt/db_test.go create mode 100644 vendor/github.com/boltdb/bolt/doc.go create mode 100644 vendor/github.com/boltdb/bolt/errors.go create mode 100644 vendor/github.com/boltdb/bolt/freelist.go create mode 100644 vendor/github.com/boltdb/bolt/freelist_test.go create mode 100644 vendor/github.com/boltdb/bolt/node.go create mode 100644 vendor/github.com/boltdb/bolt/node_test.go create mode 100644 vendor/github.com/boltdb/bolt/page.go create mode 100644 vendor/github.com/boltdb/bolt/page_test.go create mode 100644 vendor/github.com/boltdb/bolt/quick_test.go create mode 100644 vendor/github.com/boltdb/bolt/simulation_test.go create mode 100644 vendor/github.com/boltdb/bolt/tx.go create mode 100644 vendor/github.com/boltdb/bolt/tx_test.go create mode 100644 vendor/github.com/boombuler/barcode/.gitignore create mode 100644 vendor/github.com/boombuler/barcode/LICENSE create mode 100644 vendor/github.com/boombuler/barcode/README.md create mode 100644 vendor/github.com/boombuler/barcode/barcode.go create mode 100644 vendor/github.com/boombuler/barcode/qr/alphanumeric.go create mode 100644 vendor/github.com/boombuler/barcode/qr/alphanumeric_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/automatic.go create mode 100644 vendor/github.com/boombuler/barcode/qr/automatic_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/blocks.go create mode 100644 vendor/github.com/boombuler/barcode/qr/blocks_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/encoder.go create mode 100644 vendor/github.com/boombuler/barcode/qr/encoder_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/errorcorrection.go create mode 100644 vendor/github.com/boombuler/barcode/qr/errorcorrection_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/numeric.go create mode 100644 vendor/github.com/boombuler/barcode/qr/numeric_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/qrcode.go create mode 100644 vendor/github.com/boombuler/barcode/qr/qrcode_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/unicode.go create mode 100644 vendor/github.com/boombuler/barcode/qr/unicode_test.go create mode 100644 vendor/github.com/boombuler/barcode/qr/versioninfo.go create mode 100644 vendor/github.com/boombuler/barcode/qr/versioninfo_test.go create mode 100644 vendor/github.com/boombuler/barcode/scaledbarcode.go create mode 100644 vendor/github.com/boombuler/barcode/utils/base1dcode.go create mode 100644 vendor/github.com/boombuler/barcode/utils/bitlist.go create mode 100644 vendor/github.com/boombuler/barcode/utils/galoisfield.go create mode 100644 vendor/github.com/boombuler/barcode/utils/galoisfield_test.go create mode 100644 vendor/github.com/boombuler/barcode/utils/gfpoly.go create mode 100644 vendor/github.com/boombuler/barcode/utils/reedsolomon.go create mode 100644 vendor/github.com/boombuler/barcode/utils/runeint.go create mode 100644 vendor/github.com/boombuler/barcode/utils/runeint_test.go create mode 100644 vendor/github.com/cenkalti/backoff/.gitignore create mode 100644 vendor/github.com/cenkalti/backoff/.travis.yml create mode 100644 vendor/github.com/cenkalti/backoff/LICENSE create mode 100644 vendor/github.com/cenkalti/backoff/README.md create mode 100644 vendor/github.com/cenkalti/backoff/backoff.go create mode 100644 vendor/github.com/cenkalti/backoff/backoff_test.go create mode 100644 vendor/github.com/cenkalti/backoff/context.go create mode 100644 vendor/github.com/cenkalti/backoff/context_test.go create mode 100644 vendor/github.com/cenkalti/backoff/example_test.go create mode 100644 vendor/github.com/cenkalti/backoff/exponential.go create mode 100644 vendor/github.com/cenkalti/backoff/exponential_test.go create mode 100644 vendor/github.com/cenkalti/backoff/retry.go create mode 100644 vendor/github.com/cenkalti/backoff/retry_test.go create mode 100644 vendor/github.com/cenkalti/backoff/ticker.go create mode 100644 vendor/github.com/cenkalti/backoff/ticker_test.go create mode 100644 vendor/github.com/cenkalti/backoff/tries.go create mode 100644 vendor/github.com/cenkalti/backoff/tries_test.go create mode 100644 vendor/github.com/codahale/hdrhistogram/.travis.yml create mode 100644 vendor/github.com/codahale/hdrhistogram/LICENSE create mode 100644 vendor/github.com/codahale/hdrhistogram/README.md create mode 100644 vendor/github.com/codahale/hdrhistogram/hdr.go create mode 100644 vendor/github.com/codahale/hdrhistogram/hdr_test.go create mode 100644 vendor/github.com/codahale/hdrhistogram/window.go create mode 100644 vendor/github.com/codahale/hdrhistogram/window_test.go create mode 100644 vendor/github.com/coreos/etcd/.dockerignore create mode 100644 vendor/github.com/coreos/etcd/.gitignore create mode 100644 vendor/github.com/coreos/etcd/.godir create mode 100644 vendor/github.com/coreos/etcd/.header create mode 100755 vendor/github.com/coreos/etcd/.semaphore.sh create mode 100644 vendor/github.com/coreos/etcd/.travis.yml create mode 100644 vendor/github.com/coreos/etcd/CONTRIBUTING.md create mode 100644 vendor/github.com/coreos/etcd/DCO create mode 100644 vendor/github.com/coreos/etcd/Dockerfile create mode 100644 vendor/github.com/coreos/etcd/Dockerfile-release create mode 100644 vendor/github.com/coreos/etcd/Dockerfile-release.arm64 create mode 100644 vendor/github.com/coreos/etcd/Dockerfile-release.ppc64le create mode 100644 vendor/github.com/coreos/etcd/Dockerfile-test create mode 100644 vendor/github.com/coreos/etcd/LICENSE create mode 100644 vendor/github.com/coreos/etcd/MAINTAINERS create mode 100644 vendor/github.com/coreos/etcd/NEWS create mode 100644 vendor/github.com/coreos/etcd/NOTICE create mode 100644 vendor/github.com/coreos/etcd/Procfile create mode 100644 vendor/github.com/coreos/etcd/README.md create mode 100644 vendor/github.com/coreos/etcd/ROADMAP.md create mode 100644 vendor/github.com/coreos/etcd/V2Procfile create mode 100644 vendor/github.com/coreos/etcd/bill-of-materials.json create mode 100644 vendor/github.com/coreos/etcd/bill-of-materials.override.json create mode 100755 vendor/github.com/coreos/etcd/build create mode 100755 vendor/github.com/coreos/etcd/build.bat create mode 100644 vendor/github.com/coreos/etcd/build.ps1 create mode 100644 vendor/github.com/coreos/etcd/client/README.md create mode 100644 vendor/github.com/coreos/etcd/client/auth_role.go create mode 100644 vendor/github.com/coreos/etcd/client/auth_user.go create mode 100644 vendor/github.com/coreos/etcd/client/cancelreq.go create mode 100644 vendor/github.com/coreos/etcd/client/client.go create mode 100644 vendor/github.com/coreos/etcd/client/client_test.go create mode 100644 vendor/github.com/coreos/etcd/client/cluster_error.go create mode 100644 vendor/github.com/coreos/etcd/client/curl.go create mode 100644 vendor/github.com/coreos/etcd/client/discover.go create mode 100644 vendor/github.com/coreos/etcd/client/doc.go create mode 100644 vendor/github.com/coreos/etcd/client/fake_transport_test.go create mode 100644 vendor/github.com/coreos/etcd/client/keys.generated.go create mode 100644 vendor/github.com/coreos/etcd/client/keys.go create mode 100644 vendor/github.com/coreos/etcd/client/keys_bench_test.go create mode 100644 vendor/github.com/coreos/etcd/client/keys_test.go create mode 100644 vendor/github.com/coreos/etcd/client/members.go create mode 100644 vendor/github.com/coreos/etcd/client/members_test.go create mode 100644 vendor/github.com/coreos/etcd/client/util.go create mode 100755 vendor/github.com/coreos/etcd/cover create mode 100644 vendor/github.com/coreos/etcd/etcd.conf.yml.sample create mode 100644 vendor/github.com/coreos/etcd/glide.lock create mode 100644 vendor/github.com/coreos/etcd/glide.yaml create mode 100644 vendor/github.com/coreos/etcd/main.go create mode 100644 vendor/github.com/coreos/etcd/main_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/README.md create mode 100644 vendor/github.com/coreos/etcd/pkg/pathutil/path.go create mode 100644 vendor/github.com/coreos/etcd/pkg/pathutil/path_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/srv/srv.go create mode 100644 vendor/github.com/coreos/etcd/pkg/srv/srv_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/tlsutil/doc.go create mode 100644 vendor/github.com/coreos/etcd/pkg/tlsutil/tlsutil.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/doc.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/keepalive_listener.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/keepalive_listener_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/limit_listen.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/listener.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/listener_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/listener_tls.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/timeout_conn.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/timeout_dialer.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/timeout_dialer_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/timeout_listener.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/timeout_listener_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/timeout_transport.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/timeout_transport_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/tls.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/transport.go create mode 100644 vendor/github.com/coreos/etcd/pkg/transport/unix_listener.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/doc.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/id.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/id_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/set.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/set_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/slice.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/slice_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/urls.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/urls_test.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/urlsmap.go create mode 100644 vendor/github.com/coreos/etcd/pkg/types/urlsmap_test.go create mode 100755 vendor/github.com/coreos/etcd/test create mode 100644 vendor/github.com/coreos/etcd/version/version.go create mode 100644 vendor/github.com/coreos/go-oidc/.gitignore create mode 100644 vendor/github.com/coreos/go-oidc/.travis.yml create mode 100644 vendor/github.com/coreos/go-oidc/CONTRIBUTING.md create mode 100644 vendor/github.com/coreos/go-oidc/DCO create mode 100644 vendor/github.com/coreos/go-oidc/LICENSE create mode 100644 vendor/github.com/coreos/go-oidc/MAINTAINERS create mode 100644 vendor/github.com/coreos/go-oidc/NOTICE create mode 100644 vendor/github.com/coreos/go-oidc/README.md create mode 100644 vendor/github.com/coreos/go-oidc/gen.go create mode 100644 vendor/github.com/coreos/go-oidc/http/client.go create mode 100644 vendor/github.com/coreos/go-oidc/http/doc.go create mode 100644 vendor/github.com/coreos/go-oidc/http/http.go create mode 100644 vendor/github.com/coreos/go-oidc/http/http_test.go create mode 100644 vendor/github.com/coreos/go-oidc/http/url.go create mode 100644 vendor/github.com/coreos/go-oidc/http/url_test.go create mode 100644 vendor/github.com/coreos/go-oidc/jose.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/claims.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/claims_test.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/doc.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/jose.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/jwk.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/jwk_test.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/jws.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/jws_test.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/jwt.go create mode 100644 vendor/github.com/coreos/go-oidc/jose/jwt_test.go create mode 100755 vendor/github.com/coreos/go-oidc/jose/sig.go create mode 100755 vendor/github.com/coreos/go-oidc/jose/sig_rsa.go create mode 100644 vendor/github.com/coreos/go-oidc/jose_test.go create mode 100644 vendor/github.com/coreos/go-oidc/jwks.go create mode 100644 vendor/github.com/coreos/go-oidc/jwks_test.go create mode 100644 vendor/github.com/coreos/go-oidc/key/doc.go create mode 100644 vendor/github.com/coreos/go-oidc/key/key.go create mode 100644 vendor/github.com/coreos/go-oidc/key/key_test.go create mode 100644 vendor/github.com/coreos/go-oidc/key/manager.go create mode 100644 vendor/github.com/coreos/go-oidc/key/manager_test.go create mode 100644 vendor/github.com/coreos/go-oidc/key/repo.go create mode 100644 vendor/github.com/coreos/go-oidc/key/rotate.go create mode 100644 vendor/github.com/coreos/go-oidc/key/rotate_test.go create mode 100644 vendor/github.com/coreos/go-oidc/key/sync.go create mode 100644 vendor/github.com/coreos/go-oidc/key/sync_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oauth2/doc.go create mode 100644 vendor/github.com/coreos/go-oidc/oauth2/error.go create mode 100644 vendor/github.com/coreos/go-oidc/oauth2/oauth2.go create mode 100644 vendor/github.com/coreos/go-oidc/oauth2/oauth2_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/client.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/client_race_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/client_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/doc.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/identity.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/identity_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/interface.go create mode 100755 vendor/github.com/coreos/go-oidc/oidc/key.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/provider.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/provider_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/transport.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/transport_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/util.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/util_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/verification.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc/verification_test.go create mode 100644 vendor/github.com/coreos/go-oidc/oidc_test.go create mode 100755 vendor/github.com/coreos/go-oidc/test create mode 100644 vendor/github.com/coreos/go-oidc/verify.go create mode 100644 vendor/github.com/coreos/go-oidc/verify_test.go create mode 100644 vendor/github.com/coreos/go-semver/.travis.yml create mode 100644 vendor/github.com/coreos/go-semver/LICENSE create mode 100644 vendor/github.com/coreos/go-semver/README.md create mode 100644 vendor/github.com/coreos/go-semver/example.go create mode 100644 vendor/github.com/coreos/go-semver/semver/semver.go create mode 100644 vendor/github.com/coreos/go-semver/semver/semver_test.go create mode 100644 vendor/github.com/coreos/go-semver/semver/sort.go create mode 100644 vendor/github.com/coreos/pkg/.gitignore create mode 100644 vendor/github.com/coreos/pkg/.travis.yml create mode 100644 vendor/github.com/coreos/pkg/CONTRIBUTING.md create mode 100644 vendor/github.com/coreos/pkg/DCO create mode 100644 vendor/github.com/coreos/pkg/LICENSE create mode 100644 vendor/github.com/coreos/pkg/MAINTAINERS create mode 100644 vendor/github.com/coreos/pkg/NOTICE create mode 100644 vendor/github.com/coreos/pkg/README.md create mode 100755 vendor/github.com/coreos/pkg/build create mode 100644 vendor/github.com/coreos/pkg/health/README.md create mode 100644 vendor/github.com/coreos/pkg/health/health.go create mode 100644 vendor/github.com/coreos/pkg/health/health_test.go create mode 100644 vendor/github.com/coreos/pkg/httputil/README.md create mode 100644 vendor/github.com/coreos/pkg/httputil/cookie.go create mode 100644 vendor/github.com/coreos/pkg/httputil/cookie_test.go create mode 100644 vendor/github.com/coreos/pkg/httputil/json.go create mode 100644 vendor/github.com/coreos/pkg/httputil/json_test.go create mode 100755 vendor/github.com/coreos/pkg/test create mode 100644 vendor/github.com/coreos/pkg/timeutil/backoff.go create mode 100644 vendor/github.com/coreos/pkg/timeutil/backoff_test.go create mode 100644 vendor/github.com/docker/docker/.DEREK.yml create mode 100644 vendor/github.com/docker/docker/.dockerignore create mode 100644 vendor/github.com/docker/docker/.gitignore create mode 100644 vendor/github.com/docker/docker/.mailmap create mode 100644 vendor/github.com/docker/docker/AUTHORS create mode 100644 vendor/github.com/docker/docker/CHANGELOG.md create mode 100644 vendor/github.com/docker/docker/CONTRIBUTING.md create mode 100644 vendor/github.com/docker/docker/Dockerfile create mode 100644 vendor/github.com/docker/docker/Dockerfile.aarch64 create mode 100644 vendor/github.com/docker/docker/Dockerfile.armhf create mode 100644 vendor/github.com/docker/docker/Dockerfile.e2e create mode 100644 vendor/github.com/docker/docker/Dockerfile.ppc64le create mode 100644 vendor/github.com/docker/docker/Dockerfile.s390x create mode 100644 vendor/github.com/docker/docker/Dockerfile.simple create mode 100644 vendor/github.com/docker/docker/Dockerfile.windows create mode 100644 vendor/github.com/docker/docker/LICENSE create mode 100644 vendor/github.com/docker/docker/MAINTAINERS create mode 100644 vendor/github.com/docker/docker/Makefile create mode 100644 vendor/github.com/docker/docker/NOTICE create mode 100644 vendor/github.com/docker/docker/README.md create mode 100644 vendor/github.com/docker/docker/ROADMAP.md create mode 100644 vendor/github.com/docker/docker/TESTING.md create mode 100644 vendor/github.com/docker/docker/VENDORING.md create mode 100644 vendor/github.com/docker/docker/pkg/README.md create mode 100644 vendor/github.com/docker/docker/pkg/term/ascii.go create mode 100644 vendor/github.com/docker/docker/pkg/term/ascii_test.go create mode 100644 vendor/github.com/docker/docker/pkg/term/proxy.go create mode 100644 vendor/github.com/docker/docker/pkg/term/proxy_test.go create mode 100644 vendor/github.com/docker/docker/pkg/term/tc.go create mode 100644 vendor/github.com/docker/docker/pkg/term/term.go create mode 100644 vendor/github.com/docker/docker/pkg/term/term_linux_test.go create mode 100644 vendor/github.com/docker/docker/pkg/term/term_windows.go create mode 100644 vendor/github.com/docker/docker/pkg/term/termios_bsd.go create mode 100644 vendor/github.com/docker/docker/pkg/term/termios_linux.go create mode 100644 vendor/github.com/docker/docker/pkg/term/windows/ansi_reader.go create mode 100644 vendor/github.com/docker/docker/pkg/term/windows/ansi_writer.go create mode 100644 vendor/github.com/docker/docker/pkg/term/windows/console.go create mode 100644 vendor/github.com/docker/docker/pkg/term/windows/windows.go create mode 100644 vendor/github.com/docker/docker/pkg/term/windows/windows_test.go create mode 100644 vendor/github.com/docker/docker/pkg/term/winsize.go create mode 100644 vendor/github.com/docker/docker/poule.yml create mode 100644 vendor/github.com/docker/docker/vendor.conf create mode 100644 vendor/github.com/fatih/color/.travis.yml create mode 100644 vendor/github.com/fatih/color/LICENSE.md create mode 100644 vendor/github.com/fatih/color/README.md create mode 100644 vendor/github.com/fatih/color/color.go create mode 100644 vendor/github.com/fatih/color/color_test.go create mode 100644 vendor/github.com/fatih/color/doc.go create mode 100644 vendor/github.com/fatih/structs/.gitignore create mode 100644 vendor/github.com/fatih/structs/.travis.yml create mode 100644 vendor/github.com/fatih/structs/LICENSE create mode 100644 vendor/github.com/fatih/structs/README.md create mode 100644 vendor/github.com/fatih/structs/field.go create mode 100644 vendor/github.com/fatih/structs/field_test.go create mode 100644 vendor/github.com/fatih/structs/structs.go create mode 100644 vendor/github.com/fatih/structs/structs_example_test.go create mode 100644 vendor/github.com/fatih/structs/structs_test.go create mode 100644 vendor/github.com/fatih/structs/tags.go create mode 100644 vendor/github.com/fatih/structs/tags_test.go create mode 100644 vendor/github.com/ghodss/yaml/.gitignore create mode 100644 vendor/github.com/ghodss/yaml/.travis.yml create mode 100644 vendor/github.com/ghodss/yaml/LICENSE create mode 100644 vendor/github.com/ghodss/yaml/README.md create mode 100644 vendor/github.com/ghodss/yaml/fields.go create mode 100644 vendor/github.com/ghodss/yaml/yaml.go create mode 100644 vendor/github.com/ghodss/yaml/yaml_test.go create mode 100644 vendor/github.com/go-ini/ini/.gitignore create mode 100644 vendor/github.com/go-ini/ini/.travis.yml create mode 100644 vendor/github.com/go-ini/ini/LICENSE create mode 100644 vendor/github.com/go-ini/ini/Makefile create mode 100644 vendor/github.com/go-ini/ini/README.md create mode 100644 vendor/github.com/go-ini/ini/README_ZH.md create mode 100644 vendor/github.com/go-ini/ini/bench_test.go create mode 100644 vendor/github.com/go-ini/ini/error.go create mode 100644 vendor/github.com/go-ini/ini/file.go create mode 100644 vendor/github.com/go-ini/ini/file_test.go create mode 100644 vendor/github.com/go-ini/ini/ini.go create mode 100644 vendor/github.com/go-ini/ini/ini_internal_test.go create mode 100644 vendor/github.com/go-ini/ini/ini_test.go create mode 100644 vendor/github.com/go-ini/ini/key.go create mode 100644 vendor/github.com/go-ini/ini/key_test.go create mode 100644 vendor/github.com/go-ini/ini/parser.go create mode 100644 vendor/github.com/go-ini/ini/parser_test.go create mode 100644 vendor/github.com/go-ini/ini/section.go create mode 100644 vendor/github.com/go-ini/ini/section_test.go create mode 100644 vendor/github.com/go-ini/ini/struct.go create mode 100644 vendor/github.com/go-ini/ini/struct_test.go create mode 100644 vendor/github.com/gokyle/hotp/LICENSE create mode 100644 vendor/github.com/gokyle/hotp/README.md create mode 100644 vendor/github.com/gokyle/hotp/doc.go create mode 100644 vendor/github.com/gokyle/hotp/hotp.go create mode 100644 vendor/github.com/gokyle/hotp/hotp_test.go create mode 100644 vendor/github.com/gokyle/hotp/rfc4226.txt create mode 100644 vendor/github.com/golang/protobuf/.gitignore create mode 100644 vendor/github.com/golang/protobuf/.travis.yml create mode 100644 vendor/github.com/golang/protobuf/AUTHORS create mode 100644 vendor/github.com/golang/protobuf/CONTRIBUTORS create mode 100644 vendor/github.com/golang/protobuf/LICENSE create mode 100644 vendor/github.com/golang/protobuf/Make.protobuf create mode 100644 vendor/github.com/golang/protobuf/Makefile create mode 100644 vendor/github.com/golang/protobuf/README.md create mode 100644 vendor/github.com/golang/protobuf/proto/Makefile create mode 100644 vendor/github.com/golang/protobuf/proto/all_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/any_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/clone.go create mode 100644 vendor/github.com/golang/protobuf/proto/clone_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/decode.go create mode 100644 vendor/github.com/golang/protobuf/proto/decode_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/encode.go create mode 100644 vendor/github.com/golang/protobuf/proto/encode_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/equal.go create mode 100644 vendor/github.com/golang/protobuf/proto/equal_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/extensions.go create mode 100644 vendor/github.com/golang/protobuf/proto/extensions_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/lib.go create mode 100644 vendor/github.com/golang/protobuf/proto/map_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/message_set.go create mode 100644 vendor/github.com/golang/protobuf/proto/message_set_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/pointer_reflect.go create mode 100644 vendor/github.com/golang/protobuf/proto/pointer_unsafe.go create mode 100644 vendor/github.com/golang/protobuf/proto/properties.go create mode 100644 vendor/github.com/golang/protobuf/proto/proto3_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/size2_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/size_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/text.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_parser.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_parser_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_test.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/Makefile create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/doc.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/main.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/any.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/any/any.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/any/any.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/any_test.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/doc.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration_test.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/empty/empty.proto create mode 100755 vendor/github.com/golang/protobuf/ptypes/regen.sh create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp_test.go create mode 100644 vendor/github.com/gravitational/configure/.gitignore create mode 100644 vendor/github.com/gravitational/configure/LICENSE create mode 100644 vendor/github.com/gravitational/configure/Makefile create mode 100644 vendor/github.com/gravitational/configure/README.md create mode 100644 vendor/github.com/gravitational/configure/cidr.go create mode 100644 vendor/github.com/gravitational/configure/cidr_test.go create mode 100644 vendor/github.com/gravitational/configure/cli.go create mode 100644 vendor/github.com/gravitational/configure/cli_test.go create mode 100644 vendor/github.com/gravitational/configure/cstrings/domain.go create mode 100644 vendor/github.com/gravitational/configure/cstrings/split.go create mode 100644 vendor/github.com/gravitational/configure/cstrings/split_test.go create mode 100644 vendor/github.com/gravitational/configure/cstrings/user.go create mode 100644 vendor/github.com/gravitational/configure/doc.go create mode 100644 vendor/github.com/gravitational/configure/env.go create mode 100644 vendor/github.com/gravitational/configure/env_test.go create mode 100644 vendor/github.com/gravitational/configure/jsonschema/schema.go create mode 100644 vendor/github.com/gravitational/configure/jsonschema/schema_test.go create mode 100644 vendor/github.com/gravitational/configure/kv.go create mode 100644 vendor/github.com/gravitational/configure/test_test.go create mode 100644 vendor/github.com/gravitational/configure/tpl.go create mode 100644 vendor/github.com/gravitational/configure/yaml.go create mode 100644 vendor/github.com/gravitational/configure/yaml_test.go create mode 100644 vendor/github.com/gravitational/form/.gitignore create mode 100644 vendor/github.com/gravitational/form/LICENSE create mode 100644 vendor/github.com/gravitational/form/Makefile create mode 100644 vendor/github.com/gravitational/form/README.md create mode 100644 vendor/github.com/gravitational/form/form.go create mode 100644 vendor/github.com/gravitational/form/form_test.go create mode 100644 vendor/github.com/gravitational/form/shippable.yaml create mode 100644 vendor/github.com/gravitational/kingpin/.travis.yml create mode 100644 vendor/github.com/gravitational/kingpin/COPYING create mode 100644 vendor/github.com/gravitational/kingpin/README.md create mode 100644 vendor/github.com/gravitational/kingpin/actions.go create mode 100644 vendor/github.com/gravitational/kingpin/app.go create mode 100644 vendor/github.com/gravitational/kingpin/app_test.go create mode 100644 vendor/github.com/gravitational/kingpin/args.go create mode 100644 vendor/github.com/gravitational/kingpin/args_test.go create mode 100644 vendor/github.com/gravitational/kingpin/cmd.go create mode 100644 vendor/github.com/gravitational/kingpin/cmd_test.go create mode 100644 vendor/github.com/gravitational/kingpin/doc.go create mode 100644 vendor/github.com/gravitational/kingpin/examples_test.go create mode 100644 vendor/github.com/gravitational/kingpin/flags.go create mode 100644 vendor/github.com/gravitational/kingpin/flags_test.go create mode 100644 vendor/github.com/gravitational/kingpin/global.go create mode 100644 vendor/github.com/gravitational/kingpin/guesswidth.go create mode 100644 vendor/github.com/gravitational/kingpin/guesswidth_unix.go create mode 100644 vendor/github.com/gravitational/kingpin/model.go create mode 100644 vendor/github.com/gravitational/kingpin/parser.go create mode 100644 vendor/github.com/gravitational/kingpin/parser_test.go create mode 100644 vendor/github.com/gravitational/kingpin/parsers.go create mode 100644 vendor/github.com/gravitational/kingpin/parsers_test.go create mode 100644 vendor/github.com/gravitational/kingpin/templates.go create mode 100644 vendor/github.com/gravitational/kingpin/usage.go create mode 100644 vendor/github.com/gravitational/kingpin/usage_test.go create mode 100644 vendor/github.com/gravitational/kingpin/values.go create mode 100644 vendor/github.com/gravitational/kingpin/values.json create mode 100644 vendor/github.com/gravitational/kingpin/values_generated.go create mode 100644 vendor/github.com/gravitational/kingpin/values_test.go create mode 100644 vendor/github.com/gravitational/roundtrip/.gitignore create mode 100644 vendor/github.com/gravitational/roundtrip/LICENSE create mode 100644 vendor/github.com/gravitational/roundtrip/Makefile create mode 100644 vendor/github.com/gravitational/roundtrip/README.md create mode 100644 vendor/github.com/gravitational/roundtrip/client.go create mode 100644 vendor/github.com/gravitational/roundtrip/client_test.go create mode 100644 vendor/github.com/gravitational/roundtrip/creds.go create mode 100644 vendor/github.com/gravitational/roundtrip/creds_test.go create mode 100644 vendor/github.com/gravitational/roundtrip/errors.go create mode 100644 vendor/github.com/gravitational/roundtrip/reply.go create mode 100644 vendor/github.com/gravitational/roundtrip/seeker.go create mode 100644 vendor/github.com/gravitational/roundtrip/tracer.go create mode 100644 vendor/github.com/gravitational/teleport/.gitattributes create mode 100644 vendor/github.com/gravitational/teleport/.gitignore create mode 100644 vendor/github.com/gravitational/teleport/.gitmodules create mode 100644 vendor/github.com/gravitational/teleport/CHANGELOG.md create mode 100644 vendor/github.com/gravitational/teleport/CONTRIBUTING.md create mode 100644 vendor/github.com/gravitational/teleport/Gopkg.lock create mode 100644 vendor/github.com/gravitational/teleport/Gopkg.toml create mode 100644 vendor/github.com/gravitational/teleport/LICENSE create mode 100644 vendor/github.com/gravitational/teleport/Makefile create mode 100644 vendor/github.com/gravitational/teleport/README.md create mode 100644 vendor/github.com/gravitational/teleport/constants.go create mode 100644 vendor/github.com/gravitational/teleport/doc.go create mode 100644 vendor/github.com/gravitational/teleport/integration/helpers.go create mode 100644 vendor/github.com/gravitational/teleport/integration/integration.go create mode 100644 vendor/github.com/gravitational/teleport/integration/integration_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/api.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/apiserver.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/apiserver_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/auth.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/auth_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/auth_with_roles.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/clt.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/init.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/init_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/native/native.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/native/native_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/new_web_user.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/oidc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/password.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/password_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/permissions.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/register.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/saml.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/ssh_to_http.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/test/suite.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/testauthority/testauthority.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/trustedcluster.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/tun.go create mode 100644 vendor/github.com/gravitational/teleport/lib/auth/tun_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/backend.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/backend_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/boltbk/boltbk.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/boltbk/boltbk_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/boltbk/doc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/codec.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dir/doc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dir/impl.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dir/impl_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/doc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dynamo/README.md create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dynamo/doc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dynamo/dynamo.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dynamo/dynamodbbk.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/dynamo/dynamodbbk_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/etcdbk/etcd.go create mode 100644 vendor/github.com/gravitational/teleport/lib/backend/etcdbk/etcd_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/api.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/api_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/bench.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/client.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/client_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/hotp_mock.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/https_client.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/identity.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/interfaces.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/keyagent.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/keyagent_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/keystore.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/keystore_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/player.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/profile.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/profile_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/session.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/testdata_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/client/weblogin.go create mode 100644 vendor/github.com/gravitational/teleport/lib/defaults/defaults.go create mode 100644 vendor/github.com/gravitational/teleport/lib/defaults/defaults_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/api.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/api_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/auditlog.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/auditlog_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/discard.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/mock.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/slice.pb.go create mode 100644 vendor/github.com/gravitational/teleport/lib/events/slice.proto create mode 100644 vendor/github.com/gravitational/teleport/lib/httplib/csrf/csrf.go create mode 100644 vendor/github.com/gravitational/teleport/lib/httplib/httpheaders.go create mode 100644 vendor/github.com/gravitational/teleport/lib/httplib/httplib.go create mode 100644 vendor/github.com/gravitational/teleport/lib/httplib/httplib_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/limiter/connlimiter.go create mode 100644 vendor/github.com/gravitational/teleport/lib/limiter/limiter.go create mode 100644 vendor/github.com/gravitational/teleport/lib/limiter/limiter_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/limiter/ratelimiter.go create mode 100644 vendor/github.com/gravitational/teleport/lib/reversetunnel/agent.go create mode 100644 vendor/github.com/gravitational/teleport/lib/reversetunnel/agentpool.go create mode 100644 vendor/github.com/gravitational/teleport/lib/reversetunnel/api.go create mode 100644 vendor/github.com/gravitational/teleport/lib/reversetunnel/localsite.go create mode 100644 vendor/github.com/gravitational/teleport/lib/reversetunnel/remotesite.go create mode 100644 vendor/github.com/gravitational/teleport/lib/reversetunnel/srv.go create mode 100644 vendor/github.com/gravitational/teleport/lib/runtimeflags.go create mode 100644 vendor/github.com/gravitational/teleport/lib/service/cfg.go create mode 100644 vendor/github.com/gravitational/teleport/lib/service/cfg_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/service/service.go create mode 100644 vendor/github.com/gravitational/teleport/lib/service/service_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/service/supervisor.go create mode 100644 vendor/github.com/gravitational/teleport/lib/service/tpl.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/authentication.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/authority.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/clustername.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/configuration.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/doc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/identity.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/access.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/configuration.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/configuration_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/doc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/presence.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/presence_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/provisioning.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/services_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/trust.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/local/users.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/map_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/migrations_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/namespace.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/oidc.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/oidc_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/parser.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/presence.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/provisioning.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/resource.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/role.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/role_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/saml.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/saml_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/server.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/session.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/statictokens.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/trust.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/trustedcluster.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/tunnel.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/user.go create mode 100644 vendor/github.com/gravitational/teleport/lib/services/users_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/session/session.go create mode 100644 vendor/github.com/gravitational/teleport/lib/session/session_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/shell/shell.go create mode 100644 vendor/github.com/gravitational/teleport/lib/shell/shell_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/ctx.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/exec.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/exec_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/proxy.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/proxy_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/sess.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/sites.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/sshserver.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/sshserver_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/subsystem.go create mode 100644 vendor/github.com/gravitational/teleport/lib/srv/term.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/close.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/fingerprint.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/req.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/scp/scp.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/scp/scp_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/server.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/server_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/signer.go create mode 100644 vendor/github.com/gravitational/teleport/lib/sshutils/tcpip.go create mode 100644 vendor/github.com/gravitational/teleport/lib/state/api.go create mode 100644 vendor/github.com/gravitational/teleport/lib/state/cachingaccesspoint.go create mode 100644 vendor/github.com/gravitational/teleport/lib/state/cachingaccesspoint_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/state/log.go create mode 100644 vendor/github.com/gravitational/teleport/lib/state/log_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/teleagent/agent.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/addr.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/addr_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/broadcaster.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/certs.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/certs_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/cli.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/conv.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/copy.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/environment.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/environment_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/equals.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/fakeconn.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/fs.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/jsontools.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/node.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/otp.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/parse/parse.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/parse/parse_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/proxy/proxy.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/proxy/proxy_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/rand.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/roles_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/schema.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/signal.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/srv.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/storage.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/time.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/timeout.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/timeout_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/tls.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/utils.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/utils_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/utils/websocketwriter.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/apiserver.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/apiserver_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/cookie.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/plugin.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/saml.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/sessions.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/static.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/static_test.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/stream.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/terminal.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/ui/server.go create mode 100644 vendor/github.com/gravitational/teleport/lib/web/ui/usercontext.go create mode 100644 vendor/github.com/gravitational/teleport/mkdocs.yml create mode 100644 vendor/github.com/gravitational/teleport/roles.go create mode 100644 vendor/github.com/gravitational/teleport/version.go create mode 100644 vendor/github.com/gravitational/teleport/version.mk create mode 100644 vendor/github.com/gravitational/trace/.gitignore create mode 100644 vendor/github.com/gravitational/trace/LICENSE create mode 100644 vendor/github.com/gravitational/trace/README.md create mode 100644 vendor/github.com/gravitational/trace/errors.go create mode 100644 vendor/github.com/gravitational/trace/httplib.go create mode 100644 vendor/github.com/gravitational/trace/log.go create mode 100644 vendor/github.com/gravitational/trace/trace.go create mode 100644 vendor/github.com/gravitational/trace/trace_test.go create mode 100644 vendor/github.com/gravitational/trace/udphook.go create mode 100644 vendor/github.com/gravitational/trace/udphook_test.go create mode 100644 vendor/github.com/gravitational/ttlmap/.gitignore create mode 100644 vendor/github.com/gravitational/ttlmap/.travis.yml create mode 100644 vendor/github.com/gravitational/ttlmap/LICENSE create mode 100644 vendor/github.com/gravitational/ttlmap/Makefile create mode 100644 vendor/github.com/gravitational/ttlmap/README.md create mode 100644 vendor/github.com/gravitational/ttlmap/ttlmap.go create mode 100644 vendor/github.com/gravitational/ttlmap/ttlmap_test.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/.gitignore create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/.travis.yml create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/Makefile create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/README.md create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/LICENSE create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/README.grcp-gateway create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api/annotations.pb.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api/annotations.proto create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api/http.pb.go create mode 100644 vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api/http.proto create mode 100644 vendor/github.com/jmespath/go-jmespath/.gitignore create mode 100644 vendor/github.com/jmespath/go-jmespath/.travis.yml create mode 100644 vendor/github.com/jmespath/go-jmespath/LICENSE create mode 100644 vendor/github.com/jmespath/go-jmespath/Makefile create mode 100644 vendor/github.com/jmespath/go-jmespath/README.md create mode 100644 vendor/github.com/jmespath/go-jmespath/api.go create mode 100644 vendor/github.com/jmespath/go-jmespath/api_test.go create mode 100644 vendor/github.com/jmespath/go-jmespath/astnodetype_string.go create mode 100644 vendor/github.com/jmespath/go-jmespath/compliance_test.go create mode 100644 vendor/github.com/jmespath/go-jmespath/functions.go create mode 100644 vendor/github.com/jmespath/go-jmespath/interpreter.go create mode 100644 vendor/github.com/jmespath/go-jmespath/interpreter_test.go create mode 100644 vendor/github.com/jmespath/go-jmespath/lexer.go create mode 100644 vendor/github.com/jmespath/go-jmespath/lexer_test.go create mode 100644 vendor/github.com/jmespath/go-jmespath/parser.go create mode 100644 vendor/github.com/jmespath/go-jmespath/parser_test.go create mode 100644 vendor/github.com/jmespath/go-jmespath/toktype_string.go create mode 100644 vendor/github.com/jmespath/go-jmespath/util.go create mode 100644 vendor/github.com/jmespath/go-jmespath/util_test.go create mode 100644 vendor/github.com/jonboulle/clockwork/.gitignore create mode 100644 vendor/github.com/jonboulle/clockwork/.travis.yml create mode 100644 vendor/github.com/jonboulle/clockwork/LICENSE create mode 100644 vendor/github.com/jonboulle/clockwork/README.md create mode 100644 vendor/github.com/jonboulle/clockwork/clockwork.go create mode 100644 vendor/github.com/jonboulle/clockwork/clockwork_test.go create mode 100644 vendor/github.com/jonboulle/clockwork/example_test.go create mode 100644 vendor/github.com/julienschmidt/httprouter/.travis.yml create mode 100644 vendor/github.com/julienschmidt/httprouter/LICENSE create mode 100644 vendor/github.com/julienschmidt/httprouter/README.md create mode 100644 vendor/github.com/julienschmidt/httprouter/path.go create mode 100644 vendor/github.com/julienschmidt/httprouter/path_test.go create mode 100644 vendor/github.com/julienschmidt/httprouter/router.go create mode 100644 vendor/github.com/julienschmidt/httprouter/router_test.go create mode 100644 vendor/github.com/julienschmidt/httprouter/tree.go create mode 100644 vendor/github.com/julienschmidt/httprouter/tree_test.go create mode 100644 vendor/github.com/kardianos/osext/LICENSE create mode 100644 vendor/github.com/kardianos/osext/README.md create mode 100644 vendor/github.com/kardianos/osext/osext.go create mode 100644 vendor/github.com/kardianos/osext/osext_go18.go create mode 100644 vendor/github.com/kardianos/osext/osext_plan9.go create mode 100644 vendor/github.com/kardianos/osext/osext_procfs.go create mode 100644 vendor/github.com/kardianos/osext/osext_sysctl.go create mode 100644 vendor/github.com/kardianos/osext/osext_test.go create mode 100644 vendor/github.com/kardianos/osext/osext_windows.go create mode 100644 vendor/github.com/kr/pty/.gitignore create mode 100644 vendor/github.com/kr/pty/License create mode 100644 vendor/github.com/kr/pty/README.md create mode 100644 vendor/github.com/kr/pty/doc.go create mode 100644 vendor/github.com/kr/pty/ioctl.go create mode 100644 vendor/github.com/kr/pty/ioctl_bsd.go create mode 100755 vendor/github.com/kr/pty/mktypes.bash create mode 100644 vendor/github.com/kr/pty/pty_darwin.go create mode 100644 vendor/github.com/kr/pty/pty_dragonfly.go create mode 100644 vendor/github.com/kr/pty/pty_freebsd.go create mode 100644 vendor/github.com/kr/pty/pty_linux.go create mode 100644 vendor/github.com/kr/pty/pty_unsupported.go create mode 100644 vendor/github.com/kr/pty/run.go create mode 100644 vendor/github.com/kr/pty/types.go create mode 100644 vendor/github.com/kr/pty/types_dragonfly.go create mode 100644 vendor/github.com/kr/pty/types_freebsd.go create mode 100644 vendor/github.com/kr/pty/util.go create mode 100644 vendor/github.com/kr/pty/ztypes_386.go create mode 100644 vendor/github.com/kr/pty/ztypes_amd64.go create mode 100644 vendor/github.com/kr/pty/ztypes_arm.go create mode 100644 vendor/github.com/kr/pty/ztypes_arm64.go create mode 100644 vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go create mode 100644 vendor/github.com/kr/pty/ztypes_freebsd_386.go create mode 100644 vendor/github.com/kr/pty/ztypes_freebsd_amd64.go create mode 100644 vendor/github.com/kr/pty/ztypes_freebsd_arm.go create mode 100644 vendor/github.com/kr/pty/ztypes_mipsx.go create mode 100644 vendor/github.com/kr/pty/ztypes_ppc64.go create mode 100644 vendor/github.com/kr/pty/ztypes_ppc64le.go create mode 100644 vendor/github.com/kr/pty/ztypes_s390x.go create mode 100644 vendor/github.com/mailgun/holster/.gitignore create mode 100644 vendor/github.com/mailgun/holster/README.md create mode 100644 vendor/github.com/mailgun/holster/clock.go create mode 100644 vendor/github.com/mailgun/holster/clock_test.go create mode 100644 vendor/github.com/mailgun/holster/expire_cache.go create mode 100644 vendor/github.com/mailgun/holster/fanout.go create mode 100644 vendor/github.com/mailgun/holster/holster_test.go create mode 100644 vendor/github.com/mailgun/holster/lru_cache.go create mode 100644 vendor/github.com/mailgun/holster/lru_cache_test.go create mode 100644 vendor/github.com/mailgun/holster/misc.go create mode 100644 vendor/github.com/mailgun/holster/misc_test.go create mode 100644 vendor/github.com/mailgun/holster/priority_queue.go create mode 100644 vendor/github.com/mailgun/holster/priority_queue_test.go create mode 100644 vendor/github.com/mailgun/holster/random.go create mode 100644 vendor/github.com/mailgun/holster/set_default.go create mode 100644 vendor/github.com/mailgun/holster/set_default_test.go create mode 100644 vendor/github.com/mailgun/holster/ttlmap.go create mode 100644 vendor/github.com/mailgun/holster/ttlmap_test.go create mode 100644 vendor/github.com/mailgun/holster/waitgroup.go create mode 100644 vendor/github.com/mailgun/holster/waitgroup_test.go create mode 100644 vendor/github.com/mailgun/lemma/.gitignore create mode 100644 vendor/github.com/mailgun/lemma/HACKING.md create mode 100644 vendor/github.com/mailgun/lemma/LICENSE create mode 100644 vendor/github.com/mailgun/lemma/README.md create mode 100644 vendor/github.com/mailgun/lemma/random/README.md create mode 100644 vendor/github.com/mailgun/lemma/random/random.go create mode 100644 vendor/github.com/mailgun/lemma/random/random_test.go create mode 100644 vendor/github.com/mailgun/lemma/secret/README.md create mode 100644 vendor/github.com/mailgun/lemma/secret/constants.go create mode 100644 vendor/github.com/mailgun/lemma/secret/key.go create mode 100644 vendor/github.com/mailgun/lemma/secret/key_test.go create mode 100644 vendor/github.com/mailgun/lemma/secret/secret.go create mode 100644 vendor/github.com/mailgun/lemma/secret/secret_test.go create mode 100644 vendor/github.com/mailgun/metrics/.gitignore create mode 100644 vendor/github.com/mailgun/metrics/LICENSE create mode 100644 vendor/github.com/mailgun/metrics/LICENSE.md create mode 100644 vendor/github.com/mailgun/metrics/Makefile create mode 100644 vendor/github.com/mailgun/metrics/README.md create mode 100644 vendor/github.com/mailgun/metrics/client.go create mode 100644 vendor/github.com/mailgun/metrics/client_test.go create mode 100644 vendor/github.com/mailgun/metrics/metric.go create mode 100644 vendor/github.com/mailgun/metrics/nop.go create mode 100644 vendor/github.com/mailgun/metrics/sender.go create mode 100644 vendor/github.com/mailgun/minheap/.gitignore create mode 100644 vendor/github.com/mailgun/minheap/LICENSE create mode 100644 vendor/github.com/mailgun/minheap/Makefile create mode 100644 vendor/github.com/mailgun/minheap/README.md create mode 100644 vendor/github.com/mailgun/minheap/minheap.go create mode 100644 vendor/github.com/mailgun/minheap/minheap_test.go create mode 100644 vendor/github.com/mailgun/oxy/.gitignore create mode 100644 vendor/github.com/mailgun/oxy/LICENSE create mode 100644 vendor/github.com/mailgun/oxy/Makefile create mode 100644 vendor/github.com/mailgun/oxy/README.md create mode 100644 vendor/github.com/mailgun/oxy/forward/fwd.go create mode 100644 vendor/github.com/mailgun/oxy/forward/fwd_test.go create mode 100644 vendor/github.com/mailgun/oxy/forward/headers.go create mode 100644 vendor/github.com/mailgun/oxy/forward/rewrite.go create mode 100644 vendor/github.com/mailgun/oxy/utils/auth.go create mode 100644 vendor/github.com/mailgun/oxy/utils/auth_test.go create mode 100644 vendor/github.com/mailgun/oxy/utils/handler.go create mode 100644 vendor/github.com/mailgun/oxy/utils/handler_test.go create mode 100644 vendor/github.com/mailgun/oxy/utils/logging.go create mode 100644 vendor/github.com/mailgun/oxy/utils/netutils.go create mode 100644 vendor/github.com/mailgun/oxy/utils/netutils_test.go create mode 100644 vendor/github.com/mailgun/oxy/utils/source.go create mode 100644 vendor/github.com/mailgun/timetools/LICENSE create mode 100644 vendor/github.com/mailgun/timetools/README.md create mode 100644 vendor/github.com/mailgun/timetools/provider.go create mode 100644 vendor/github.com/mailgun/timetools/provider_test.go create mode 100644 vendor/github.com/mailgun/timetools/rfc2822time.go create mode 100644 vendor/github.com/mailgun/ttlmap/.gitignore create mode 100644 vendor/github.com/mailgun/ttlmap/.travis.yml create mode 100644 vendor/github.com/mailgun/ttlmap/LICENSE create mode 100644 vendor/github.com/mailgun/ttlmap/Makefile create mode 100644 vendor/github.com/mailgun/ttlmap/README.md create mode 100644 vendor/github.com/mailgun/ttlmap/ttlmap.go create mode 100644 vendor/github.com/mailgun/ttlmap/ttlmap_test.go create mode 100644 vendor/github.com/mattn/go-colorable/.travis.yml create mode 100644 vendor/github.com/mattn/go-colorable/LICENSE create mode 100644 vendor/github.com/mattn/go-colorable/README.md create mode 100644 vendor/github.com/mattn/go-colorable/colorable_appengine.go create mode 100644 vendor/github.com/mattn/go-colorable/colorable_others.go create mode 100644 vendor/github.com/mattn/go-colorable/colorable_test.go create mode 100644 vendor/github.com/mattn/go-colorable/colorable_windows.go create mode 100644 vendor/github.com/mattn/go-colorable/noncolorable.go create mode 100644 vendor/github.com/mattn/go-isatty/.travis.yml create mode 100644 vendor/github.com/mattn/go-isatty/LICENSE create mode 100644 vendor/github.com/mattn/go-isatty/README.md create mode 100644 vendor/github.com/mattn/go-isatty/doc.go create mode 100644 vendor/github.com/mattn/go-isatty/example_test.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_appengine.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_bsd.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_linux.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_linux_ppc64x.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_others.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_others_test.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_solaris.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_windows.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_windows_test.go create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/.travis.yml create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/README.md create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode_test.go create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode_test.go create mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/fixtures_test.go create mode 100644 vendor/github.com/mdp/rsc/README.md create mode 100644 vendor/github.com/mdp/rsc/gf256/blog_test.go create mode 100644 vendor/github.com/mdp/rsc/gf256/gf256.go create mode 100644 vendor/github.com/mdp/rsc/gf256/gf256_test.go create mode 100644 vendor/github.com/mdp/rsc/qr/coding/gen.go create mode 100644 vendor/github.com/mdp/rsc/qr/coding/qr.go create mode 100644 vendor/github.com/mdp/rsc/qr/coding/qr_test.go create mode 100644 vendor/github.com/mdp/rsc/qr/png.go create mode 100644 vendor/github.com/mdp/rsc/qr/png_test.go create mode 100644 vendor/github.com/mdp/rsc/qr/qr.go create mode 100644 vendor/github.com/mdp/rsc/qr/x.png create mode 100644 vendor/github.com/moby/moby/.dockerignore create mode 100644 vendor/github.com/moby/moby/.gitignore create mode 100644 vendor/github.com/moby/moby/.mailmap create mode 100644 vendor/github.com/moby/moby/AUTHORS create mode 100644 vendor/github.com/moby/moby/CHANGELOG.md create mode 100644 vendor/github.com/moby/moby/CONTRIBUTING.md create mode 100644 vendor/github.com/moby/moby/Dockerfile create mode 100644 vendor/github.com/moby/moby/Dockerfile.aarch64 create mode 100644 vendor/github.com/moby/moby/Dockerfile.armhf create mode 100644 vendor/github.com/moby/moby/Dockerfile.ppc64le create mode 100644 vendor/github.com/moby/moby/Dockerfile.s390x create mode 100644 vendor/github.com/moby/moby/Dockerfile.simple create mode 100644 vendor/github.com/moby/moby/Dockerfile.solaris create mode 100644 vendor/github.com/moby/moby/Dockerfile.windows create mode 100644 vendor/github.com/moby/moby/LICENSE create mode 100644 vendor/github.com/moby/moby/MAINTAINERS create mode 100644 vendor/github.com/moby/moby/Makefile create mode 100644 vendor/github.com/moby/moby/NOTICE create mode 100644 vendor/github.com/moby/moby/README.md create mode 100644 vendor/github.com/moby/moby/ROADMAP.md create mode 100644 vendor/github.com/moby/moby/VENDORING.md create mode 100644 vendor/github.com/moby/moby/VERSION create mode 100644 vendor/github.com/moby/moby/pkg/README.md create mode 100644 vendor/github.com/moby/moby/pkg/term/ascii.go create mode 100644 vendor/github.com/moby/moby/pkg/term/ascii_test.go create mode 100644 vendor/github.com/moby/moby/pkg/term/tc_linux_cgo.go create mode 100644 vendor/github.com/moby/moby/pkg/term/tc_other.go create mode 100644 vendor/github.com/moby/moby/pkg/term/tc_solaris_cgo.go create mode 100644 vendor/github.com/moby/moby/pkg/term/term.go create mode 100644 vendor/github.com/moby/moby/pkg/term/term_solaris.go create mode 100644 vendor/github.com/moby/moby/pkg/term/term_unix.go create mode 100644 vendor/github.com/moby/moby/pkg/term/term_windows.go create mode 100644 vendor/github.com/moby/moby/pkg/term/termios_darwin.go create mode 100644 vendor/github.com/moby/moby/pkg/term/termios_freebsd.go create mode 100644 vendor/github.com/moby/moby/pkg/term/termios_linux.go create mode 100644 vendor/github.com/moby/moby/pkg/term/termios_openbsd.go create mode 100644 vendor/github.com/moby/moby/poule.yml create mode 100644 vendor/github.com/moby/moby/vendor.conf create mode 100644 vendor/github.com/pborman/uuid/.travis.yml create mode 100644 vendor/github.com/pborman/uuid/CONTRIBUTING.md create mode 100644 vendor/github.com/pborman/uuid/CONTRIBUTORS create mode 100644 vendor/github.com/pborman/uuid/LICENSE create mode 100644 vendor/github.com/pborman/uuid/README.md create mode 100644 vendor/github.com/pborman/uuid/dce.go create mode 100644 vendor/github.com/pborman/uuid/doc.go create mode 100644 vendor/github.com/pborman/uuid/hash.go create mode 100644 vendor/github.com/pborman/uuid/marshal.go create mode 100644 vendor/github.com/pborman/uuid/marshal_test.go create mode 100644 vendor/github.com/pborman/uuid/node.go create mode 100644 vendor/github.com/pborman/uuid/seq_test.go create mode 100644 vendor/github.com/pborman/uuid/sql.go create mode 100644 vendor/github.com/pborman/uuid/sql_test.go create mode 100644 vendor/github.com/pborman/uuid/time.go create mode 100644 vendor/github.com/pborman/uuid/util.go create mode 100644 vendor/github.com/pborman/uuid/uuid.go create mode 100644 vendor/github.com/pborman/uuid/uuid_test.go create mode 100644 vendor/github.com/pborman/uuid/version1.go create mode 100644 vendor/github.com/pborman/uuid/version4.go create mode 100644 vendor/github.com/pkg/errors/.gitignore create mode 100644 vendor/github.com/pkg/errors/.travis.yml create mode 100644 vendor/github.com/pkg/errors/LICENSE create mode 100644 vendor/github.com/pkg/errors/README.md create mode 100644 vendor/github.com/pkg/errors/appveyor.yml create mode 100644 vendor/github.com/pkg/errors/bench_test.go create mode 100644 vendor/github.com/pkg/errors/errors.go create mode 100644 vendor/github.com/pkg/errors/errors_test.go create mode 100644 vendor/github.com/pkg/errors/example_test.go create mode 100644 vendor/github.com/pkg/errors/format_test.go create mode 100644 vendor/github.com/pkg/errors/stack.go create mode 100644 vendor/github.com/pkg/errors/stack_test.go create mode 100644 vendor/github.com/pquerna/otp/.travis.yml create mode 100644 vendor/github.com/pquerna/otp/LICENSE create mode 100644 vendor/github.com/pquerna/otp/NOTICE create mode 100644 vendor/github.com/pquerna/otp/README.md create mode 100644 vendor/github.com/pquerna/otp/doc.go create mode 100644 vendor/github.com/pquerna/otp/hotp/hotp.go create mode 100644 vendor/github.com/pquerna/otp/hotp/hotp_test.go create mode 100644 vendor/github.com/pquerna/otp/otp.go create mode 100644 vendor/github.com/pquerna/otp/otp_test.go create mode 100644 vendor/github.com/pquerna/otp/totp/totp.go create mode 100644 vendor/github.com/pquerna/otp/totp/totp_test.go create mode 100644 vendor/github.com/prometheus/client_golang/.gitignore create mode 100644 vendor/github.com/prometheus/client_golang/.travis.yml create mode 100644 vendor/github.com/prometheus/client_golang/AUTHORS.md create mode 100644 vendor/github.com/prometheus/client_golang/CHANGELOG.md create mode 100644 vendor/github.com/prometheus/client_golang/CONTRIBUTING.md create mode 100644 vendor/github.com/prometheus/client_golang/LICENSE create mode 100644 vendor/github.com/prometheus/client_golang/NOTICE create mode 100644 vendor/github.com/prometheus/client_golang/README.md create mode 100644 vendor/github.com/prometheus/client_golang/VERSION create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/.gitignore create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/README.md create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/benchmark_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/collector.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/counter.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/counter_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/desc.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/doc.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/examples_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/expvar_collector_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/fnv.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/gauge.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/gauge_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/histogram.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/histogram_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/http.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/http_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/metric.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/metric_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/registry.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/registry_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/summary.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/summary_test.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/untyped.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/value.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/vec.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/vec_test.go create mode 100644 vendor/github.com/prometheus/client_model/.gitignore create mode 100644 vendor/github.com/prometheus/client_model/CONTRIBUTING.md create mode 100644 vendor/github.com/prometheus/client_model/LICENSE create mode 100644 vendor/github.com/prometheus/client_model/MAINTAINERS.md create mode 100644 vendor/github.com/prometheus/client_model/Makefile create mode 100644 vendor/github.com/prometheus/client_model/NOTICE create mode 100644 vendor/github.com/prometheus/client_model/README.md create mode 100644 vendor/github.com/prometheus/client_model/go/metrics.pb.go create mode 100644 vendor/github.com/prometheus/client_model/metrics.proto create mode 100644 vendor/github.com/prometheus/client_model/pom.xml create mode 100644 vendor/github.com/prometheus/client_model/setup.py create mode 100644 vendor/github.com/prometheus/common/.travis.yml create mode 100644 vendor/github.com/prometheus/common/CONTRIBUTING.md create mode 100644 vendor/github.com/prometheus/common/LICENSE create mode 100644 vendor/github.com/prometheus/common/MAINTAINERS.md create mode 100644 vendor/github.com/prometheus/common/NOTICE create mode 100644 vendor/github.com/prometheus/common/README.md create mode 100644 vendor/github.com/prometheus/common/expfmt/bench_test.go create mode 100644 vendor/github.com/prometheus/common/expfmt/decode.go create mode 100644 vendor/github.com/prometheus/common/expfmt/decode_test.go create mode 100644 vendor/github.com/prometheus/common/expfmt/encode.go create mode 100644 vendor/github.com/prometheus/common/expfmt/expfmt.go create mode 100644 vendor/github.com/prometheus/common/expfmt/fuzz.go create mode 100644 vendor/github.com/prometheus/common/expfmt/text_create.go create mode 100644 vendor/github.com/prometheus/common/expfmt/text_create_test.go create mode 100644 vendor/github.com/prometheus/common/expfmt/text_parse.go create mode 100644 vendor/github.com/prometheus/common/expfmt/text_parse_test.go create mode 100644 vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt create mode 100644 vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go create mode 100644 vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg_test.go create mode 100644 vendor/github.com/prometheus/common/model/alert.go create mode 100644 vendor/github.com/prometheus/common/model/alert_test.go create mode 100644 vendor/github.com/prometheus/common/model/fingerprinting.go create mode 100644 vendor/github.com/prometheus/common/model/fnv.go create mode 100644 vendor/github.com/prometheus/common/model/labels.go create mode 100644 vendor/github.com/prometheus/common/model/labels_test.go create mode 100644 vendor/github.com/prometheus/common/model/labelset.go create mode 100644 vendor/github.com/prometheus/common/model/metric.go create mode 100644 vendor/github.com/prometheus/common/model/metric_test.go create mode 100644 vendor/github.com/prometheus/common/model/model.go create mode 100644 vendor/github.com/prometheus/common/model/signature.go create mode 100644 vendor/github.com/prometheus/common/model/signature_test.go create mode 100644 vendor/github.com/prometheus/common/model/silence.go create mode 100644 vendor/github.com/prometheus/common/model/silence_test.go create mode 100644 vendor/github.com/prometheus/common/model/time.go create mode 100644 vendor/github.com/prometheus/common/model/time_test.go create mode 100644 vendor/github.com/prometheus/common/model/value.go create mode 100644 vendor/github.com/prometheus/common/model/value_test.go create mode 100644 vendor/github.com/prometheus/procfs/.travis.yml create mode 100644 vendor/github.com/prometheus/procfs/CONTRIBUTING.md create mode 100644 vendor/github.com/prometheus/procfs/LICENSE create mode 100644 vendor/github.com/prometheus/procfs/MAINTAINERS.md create mode 100644 vendor/github.com/prometheus/procfs/Makefile create mode 100644 vendor/github.com/prometheus/procfs/NOTICE create mode 100644 vendor/github.com/prometheus/procfs/README.md create mode 100644 vendor/github.com/prometheus/procfs/buddyinfo.go create mode 100644 vendor/github.com/prometheus/procfs/buddyinfo_test.go create mode 100644 vendor/github.com/prometheus/procfs/doc.go create mode 100644 vendor/github.com/prometheus/procfs/fs.go create mode 100644 vendor/github.com/prometheus/procfs/fs_test.go create mode 100644 vendor/github.com/prometheus/procfs/ipvs.go create mode 100644 vendor/github.com/prometheus/procfs/ipvs_test.go create mode 100644 vendor/github.com/prometheus/procfs/mdstat.go create mode 100644 vendor/github.com/prometheus/procfs/mdstat_test.go create mode 100644 vendor/github.com/prometheus/procfs/mountstats.go create mode 100644 vendor/github.com/prometheus/procfs/mountstats_test.go create mode 100644 vendor/github.com/prometheus/procfs/proc.go create mode 100644 vendor/github.com/prometheus/procfs/proc_io.go create mode 100644 vendor/github.com/prometheus/procfs/proc_io_test.go create mode 100644 vendor/github.com/prometheus/procfs/proc_limits.go create mode 100644 vendor/github.com/prometheus/procfs/proc_limits_test.go create mode 100644 vendor/github.com/prometheus/procfs/proc_stat.go create mode 100644 vendor/github.com/prometheus/procfs/proc_stat_test.go create mode 100644 vendor/github.com/prometheus/procfs/proc_test.go create mode 100644 vendor/github.com/prometheus/procfs/stat.go create mode 100644 vendor/github.com/prometheus/procfs/stat_test.go create mode 100755 vendor/github.com/prometheus/procfs/ttar create mode 100644 vendor/github.com/prometheus/procfs/xfrm.go create mode 100644 vendor/github.com/prometheus/procfs/xfrm_test.go create mode 100644 vendor/github.com/prometheus/procfs/xfs/parse.go create mode 100644 vendor/github.com/prometheus/procfs/xfs/parse_test.go create mode 100644 vendor/github.com/prometheus/procfs/xfs/xfs.go create mode 100644 vendor/github.com/russellhaering/gosaml2/.travis.yml create mode 100644 vendor/github.com/russellhaering/gosaml2/LICENSE create mode 100644 vendor/github.com/russellhaering/gosaml2/README.md create mode 100644 vendor/github.com/russellhaering/gosaml2/attribute.go create mode 100644 vendor/github.com/russellhaering/gosaml2/authn_request.go create mode 100644 vendor/github.com/russellhaering/gosaml2/build_request.go create mode 100644 vendor/github.com/russellhaering/gosaml2/build_request_test.go create mode 100644 vendor/github.com/russellhaering/gosaml2/decode_response.go create mode 100644 vendor/github.com/russellhaering/gosaml2/decode_response_test.go create mode 100644 vendor/github.com/russellhaering/gosaml2/retrieve_assertion.go create mode 100644 vendor/github.com/russellhaering/gosaml2/saml.go create mode 100644 vendor/github.com/russellhaering/gosaml2/saml2_test.go create mode 100644 vendor/github.com/russellhaering/gosaml2/saml_test.go create mode 100644 vendor/github.com/russellhaering/gosaml2/test_constants.go create mode 100644 vendor/github.com/russellhaering/gosaml2/types/encrypted_assertion.go create mode 100644 vendor/github.com/russellhaering/gosaml2/types/encrypted_key.go create mode 100644 vendor/github.com/russellhaering/gosaml2/types/metadata.go create mode 100644 vendor/github.com/russellhaering/gosaml2/types/response.go create mode 100644 vendor/github.com/russellhaering/gosaml2/validate.go create mode 100644 vendor/github.com/russellhaering/gosaml2/xml_constants.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/.travis.yml create mode 100644 vendor/github.com/russellhaering/goxmldsig/LICENSE create mode 100644 vendor/github.com/russellhaering/goxmldsig/README.md create mode 100644 vendor/github.com/russellhaering/goxmldsig/canonicalize.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/canonicalize_test.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/clock.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/etreeutils/canonicalize.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/etreeutils/namespace.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/etreeutils/sort.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/etreeutils/unmarshal.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/keystore.go create mode 100755 vendor/github.com/russellhaering/goxmldsig/run_test.sh create mode 100644 vendor/github.com/russellhaering/goxmldsig/sign.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/sign_test.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/tls_keystore.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/types/signature.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/validate.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/validate_test.go create mode 100644 vendor/github.com/russellhaering/goxmldsig/xml_constants.go create mode 100644 vendor/github.com/satori/go.uuid/.travis.yml create mode 100644 vendor/github.com/satori/go.uuid/LICENSE create mode 100644 vendor/github.com/satori/go.uuid/README.md create mode 100644 vendor/github.com/satori/go.uuid/benchmarks_test.go create mode 100644 vendor/github.com/satori/go.uuid/uuid.go create mode 100644 vendor/github.com/satori/go.uuid/uuid_test.go create mode 100644 vendor/github.com/sirupsen/logrus/.gitignore create mode 100644 vendor/github.com/sirupsen/logrus/.travis.yml create mode 100644 vendor/github.com/sirupsen/logrus/CHANGELOG.md create mode 100644 vendor/github.com/sirupsen/logrus/LICENSE create mode 100644 vendor/github.com/sirupsen/logrus/README.md create mode 100644 vendor/github.com/sirupsen/logrus/alt_exit.go create mode 100644 vendor/github.com/sirupsen/logrus/alt_exit_test.go create mode 100644 vendor/github.com/sirupsen/logrus/appveyor.yml create mode 100644 vendor/github.com/sirupsen/logrus/doc.go create mode 100644 vendor/github.com/sirupsen/logrus/entry.go create mode 100644 vendor/github.com/sirupsen/logrus/entry_test.go create mode 100644 vendor/github.com/sirupsen/logrus/example_basic_test.go create mode 100644 vendor/github.com/sirupsen/logrus/example_hook_test.go create mode 100644 vendor/github.com/sirupsen/logrus/exported.go create mode 100644 vendor/github.com/sirupsen/logrus/formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/formatter_bench_test.go create mode 100644 vendor/github.com/sirupsen/logrus/hook_test.go create mode 100644 vendor/github.com/sirupsen/logrus/hooks.go create mode 100644 vendor/github.com/sirupsen/logrus/hooks/syslog/README.md create mode 100644 vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go create mode 100644 vendor/github.com/sirupsen/logrus/hooks/syslog/syslog_test.go create mode 100644 vendor/github.com/sirupsen/logrus/json_formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/json_formatter_test.go create mode 100644 vendor/github.com/sirupsen/logrus/logger.go create mode 100644 vendor/github.com/sirupsen/logrus/logger_bench_test.go create mode 100644 vendor/github.com/sirupsen/logrus/logrus.go create mode 100644 vendor/github.com/sirupsen/logrus/logrus_test.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_bsd.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_appengine.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_linux.go create mode 100644 vendor/github.com/sirupsen/logrus/text_formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/text_formatter_test.go create mode 100644 vendor/github.com/sirupsen/logrus/writer.go create mode 100644 vendor/github.com/tstranex/u2f/.gitignore create mode 100644 vendor/github.com/tstranex/u2f/LICENSE create mode 100644 vendor/github.com/tstranex/u2f/README.md create mode 100644 vendor/github.com/tstranex/u2f/auth.go create mode 100644 vendor/github.com/tstranex/u2f/auth_test.go create mode 100644 vendor/github.com/tstranex/u2f/certs.go create mode 100644 vendor/github.com/tstranex/u2f/messages.go create mode 100644 vendor/github.com/tstranex/u2f/register.go create mode 100644 vendor/github.com/tstranex/u2f/register_test.go create mode 100644 vendor/github.com/tstranex/u2f/u2f_test.go create mode 100644 vendor/github.com/tstranex/u2f/util.go create mode 100644 vendor/github.com/tstranex/u2f/util_test.go create mode 100644 vendor/github.com/ugorji/go/LICENSE create mode 100644 vendor/github.com/ugorji/go/README.md create mode 100644 vendor/github.com/ugorji/go/codec/0doc.go create mode 100644 vendor/github.com/ugorji/go/codec/README.md create mode 100644 vendor/github.com/ugorji/go/codec/binc.go create mode 100644 vendor/github.com/ugorji/go/codec/cbor.go create mode 100644 vendor/github.com/ugorji/go/codec/cbor_test.go create mode 100644 vendor/github.com/ugorji/go/codec/codec_test.go create mode 100644 vendor/github.com/ugorji/go/codec/codecgen_test.go create mode 100644 vendor/github.com/ugorji/go/codec/decode.go create mode 100644 vendor/github.com/ugorji/go/codec/encode.go create mode 100644 vendor/github.com/ugorji/go/codec/fast-path.generated.go create mode 100644 vendor/github.com/ugorji/go/codec/fast-path.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/fast-path.not.go create mode 100644 vendor/github.com/ugorji/go/codec/gen-dec-array.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/gen-dec-map.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/gen-helper.generated.go create mode 100644 vendor/github.com/ugorji/go/codec/gen-helper.go.tmpl create mode 100644 vendor/github.com/ugorji/go/codec/gen.generated.go create mode 100644 vendor/github.com/ugorji/go/codec/gen.go create mode 100644 vendor/github.com/ugorji/go/codec/helper.go create mode 100644 vendor/github.com/ugorji/go/codec/helper_internal.go create mode 100644 vendor/github.com/ugorji/go/codec/helper_not_unsafe.go create mode 100644 vendor/github.com/ugorji/go/codec/helper_test.go create mode 100644 vendor/github.com/ugorji/go/codec/helper_unsafe.go create mode 100644 vendor/github.com/ugorji/go/codec/json.go create mode 100644 vendor/github.com/ugorji/go/codec/msgpack.go create mode 100644 vendor/github.com/ugorji/go/codec/noop.go create mode 100644 vendor/github.com/ugorji/go/codec/prebuild.go create mode 100755 vendor/github.com/ugorji/go/codec/prebuild.sh create mode 100644 vendor/github.com/ugorji/go/codec/py_test.go create mode 100644 vendor/github.com/ugorji/go/codec/rpc.go create mode 100644 vendor/github.com/ugorji/go/codec/simple.go create mode 100644 vendor/github.com/ugorji/go/codec/test-cbor-goldens.json create mode 100755 vendor/github.com/ugorji/go/codec/test.py create mode 100755 vendor/github.com/ugorji/go/codec/tests.sh create mode 100644 vendor/github.com/ugorji/go/codec/time.go create mode 100644 vendor/github.com/ugorji/go/codec/values_test.go create mode 100644 vendor/github.com/ugorji/go/msgpack.org.md create mode 100644 vendor/github.com/vulcand/oxy/.gitignore create mode 100644 vendor/github.com/vulcand/oxy/.travis.yml create mode 100644 vendor/github.com/vulcand/oxy/Gopkg.lock create mode 100644 vendor/github.com/vulcand/oxy/Gopkg.toml create mode 100644 vendor/github.com/vulcand/oxy/LICENSE create mode 100644 vendor/github.com/vulcand/oxy/Makefile create mode 100644 vendor/github.com/vulcand/oxy/README.md create mode 100644 vendor/github.com/vulcand/oxy/connlimit/connlimit.go create mode 100644 vendor/github.com/vulcand/oxy/connlimit/connlimit_test.go create mode 100644 vendor/github.com/vulcand/oxy/ratelimit/bucket.go create mode 100644 vendor/github.com/vulcand/oxy/ratelimit/bucket_test.go create mode 100644 vendor/github.com/vulcand/oxy/ratelimit/bucketset.go create mode 100644 vendor/github.com/vulcand/oxy/ratelimit/bucketset_test.go create mode 100644 vendor/github.com/vulcand/oxy/ratelimit/tokenlimiter.go create mode 100644 vendor/github.com/vulcand/oxy/ratelimit/tokenlimiter_test.go create mode 100644 vendor/github.com/vulcand/oxy/utils/auth.go create mode 100644 vendor/github.com/vulcand/oxy/utils/auth_test.go create mode 100644 vendor/github.com/vulcand/oxy/utils/dumpreq.go create mode 100644 vendor/github.com/vulcand/oxy/utils/dumpreq_test.go create mode 100644 vendor/github.com/vulcand/oxy/utils/handler.go create mode 100644 vendor/github.com/vulcand/oxy/utils/handler_test.go create mode 100644 vendor/github.com/vulcand/oxy/utils/netutils.go create mode 100644 vendor/github.com/vulcand/oxy/utils/netutils_test.go create mode 100644 vendor/github.com/vulcand/oxy/utils/source.go create mode 100644 vendor/github.com/vulcand/predicate/.gitignore create mode 100644 vendor/github.com/vulcand/predicate/LICENSE create mode 100644 vendor/github.com/vulcand/predicate/Makefile create mode 100644 vendor/github.com/vulcand/predicate/README.md create mode 100644 vendor/github.com/vulcand/predicate/lib.go create mode 100644 vendor/github.com/vulcand/predicate/parse.go create mode 100644 vendor/github.com/vulcand/predicate/parse_test.go create mode 100644 vendor/github.com/vulcand/predicate/predicate.go create mode 100644 vendor/github.com/xeipuuv/gojsonpointer/LICENSE-APACHE-2.0.txt create mode 100644 vendor/github.com/xeipuuv/gojsonpointer/README.md create mode 100644 vendor/github.com/xeipuuv/gojsonpointer/pointer.go create mode 100644 vendor/github.com/xeipuuv/gojsonpointer/pointer_test.go create mode 100644 vendor/github.com/xeipuuv/gojsonreference/LICENSE-APACHE-2.0.txt create mode 100644 vendor/github.com/xeipuuv/gojsonreference/README.md create mode 100644 vendor/github.com/xeipuuv/gojsonreference/reference.go create mode 100644 vendor/github.com/xeipuuv/gojsonreference/reference_test.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/.gitignore create mode 100644 vendor/github.com/xeipuuv/gojsonschema/.travis.yml create mode 100644 vendor/github.com/xeipuuv/gojsonschema/LICENSE-APACHE-2.0.txt create mode 100644 vendor/github.com/xeipuuv/gojsonschema/README.md create mode 100644 vendor/github.com/xeipuuv/gojsonschema/errors.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/format_checkers.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/format_checkers_test.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/glide.yaml create mode 100644 vendor/github.com/xeipuuv/gojsonschema/internalLog.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/jsonContext.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/locales.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/result.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/schema.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/schemaPool.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/schemaReferencePool.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/schemaType.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/schema_test.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/subSchema.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/types.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/utils.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/utils_test.go create mode 100644 vendor/github.com/xeipuuv/gojsonschema/validation.go create mode 100644 vendor/golang.org/x/crypto/.gitattributes create mode 100644 vendor/golang.org/x/crypto/.gitignore create mode 100644 vendor/golang.org/x/crypto/AUTHORS create mode 100644 vendor/golang.org/x/crypto/CONTRIBUTING.md create mode 100644 vendor/golang.org/x/crypto/CONTRIBUTORS create mode 100644 vendor/golang.org/x/crypto/LICENSE create mode 100644 vendor/golang.org/x/crypto/PATENTS create mode 100644 vendor/golang.org/x/crypto/README create mode 100644 vendor/golang.org/x/crypto/bcrypt/base64.go create mode 100644 vendor/golang.org/x/crypto/bcrypt/bcrypt.go create mode 100644 vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go create mode 100644 vendor/golang.org/x/crypto/blowfish/block.go create mode 100644 vendor/golang.org/x/crypto/blowfish/blowfish_test.go create mode 100644 vendor/golang.org/x/crypto/blowfish/cipher.go create mode 100644 vendor/golang.org/x/crypto/blowfish/const.go create mode 100644 vendor/golang.org/x/crypto/codereview.cfg create mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.h create mode 100644 vendor/golang.org/x/crypto/curve25519/const_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/cswap_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519.go create mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_test.go create mode 100644 vendor/golang.org/x/crypto/curve25519/doc.go create mode 100644 vendor/golang.org/x/crypto/curve25519/freeze_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go create mode 100644 vendor/golang.org/x/crypto/curve25519/mul_amd64.s create mode 100644 vendor/golang.org/x/crypto/curve25519/square_amd64.s create mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519.go create mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519_test.go create mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go create mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go create mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/example_test.go create mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go create mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go create mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305.go create mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305_test.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_amd64.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_amd64.s create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_arm.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_arm.s create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_ref.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa20.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa20_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/client.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/client_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/example_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/forward.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/keyring.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/keyring_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/server.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/server_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/agent/testdata_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/benchmark_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/buffer.go create mode 100644 vendor/golang.org/x/crypto/ssh/buffer_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/certs.go create mode 100644 vendor/golang.org/x/crypto/ssh/certs_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/channel.go create mode 100644 vendor/golang.org/x/crypto/ssh/cipher.go create mode 100644 vendor/golang.org/x/crypto/ssh/cipher_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/client.go create mode 100644 vendor/golang.org/x/crypto/ssh/client_auth.go create mode 100644 vendor/golang.org/x/crypto/ssh/client_auth_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/client_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/common.go create mode 100644 vendor/golang.org/x/crypto/ssh/connection.go create mode 100644 vendor/golang.org/x/crypto/ssh/doc.go create mode 100644 vendor/golang.org/x/crypto/ssh/example_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/handshake.go create mode 100644 vendor/golang.org/x/crypto/ssh/handshake_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/kex.go create mode 100644 vendor/golang.org/x/crypto/ssh/kex_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/keys.go create mode 100644 vendor/golang.org/x/crypto/ssh/keys_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/mac.go create mode 100644 vendor/golang.org/x/crypto/ssh/mempipe_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/messages.go create mode 100644 vendor/golang.org/x/crypto/ssh/messages_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/mux.go create mode 100644 vendor/golang.org/x/crypto/ssh/mux_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/server.go create mode 100644 vendor/golang.org/x/crypto/ssh/session.go create mode 100644 vendor/golang.org/x/crypto/ssh/session_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/tcpip.go create mode 100644 vendor/golang.org/x/crypto/ssh/tcpip_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/terminal.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_linux.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_windows.go create mode 100644 vendor/golang.org/x/crypto/ssh/testdata_test.go create mode 100644 vendor/golang.org/x/crypto/ssh/transport.go create mode 100644 vendor/golang.org/x/crypto/ssh/transport_test.go create mode 100644 vendor/golang.org/x/net/.gitattributes create mode 100644 vendor/golang.org/x/net/.gitignore create mode 100644 vendor/golang.org/x/net/AUTHORS create mode 100644 vendor/golang.org/x/net/CONTRIBUTING.md create mode 100644 vendor/golang.org/x/net/CONTRIBUTORS create mode 100644 vendor/golang.org/x/net/LICENSE create mode 100644 vendor/golang.org/x/net/PATENTS create mode 100644 vendor/golang.org/x/net/README.md create mode 100644 vendor/golang.org/x/net/codereview.cfg create mode 100644 vendor/golang.org/x/net/context/context.go create mode 100644 vendor/golang.org/x/net/context/context_test.go create mode 100644 vendor/golang.org/x/net/context/go17.go create mode 100644 vendor/golang.org/x/net/context/go19.go create mode 100644 vendor/golang.org/x/net/context/pre_go17.go create mode 100644 vendor/golang.org/x/net/context/pre_go19.go create mode 100644 vendor/golang.org/x/net/context/withtimeout_test.go create mode 100644 vendor/golang.org/x/net/http2/.gitignore create mode 100644 vendor/golang.org/x/net/http2/Dockerfile create mode 100644 vendor/golang.org/x/net/http2/Makefile create mode 100644 vendor/golang.org/x/net/http2/README create mode 100644 vendor/golang.org/x/net/http2/ciphers.go create mode 100644 vendor/golang.org/x/net/http2/ciphers_test.go create mode 100644 vendor/golang.org/x/net/http2/client_conn_pool.go create mode 100644 vendor/golang.org/x/net/http2/configure_transport.go create mode 100644 vendor/golang.org/x/net/http2/databuffer.go create mode 100644 vendor/golang.org/x/net/http2/databuffer_test.go create mode 100644 vendor/golang.org/x/net/http2/errors.go create mode 100644 vendor/golang.org/x/net/http2/errors_test.go create mode 100644 vendor/golang.org/x/net/http2/flow.go create mode 100644 vendor/golang.org/x/net/http2/flow_test.go create mode 100644 vendor/golang.org/x/net/http2/frame.go create mode 100644 vendor/golang.org/x/net/http2/frame_test.go create mode 100644 vendor/golang.org/x/net/http2/go16.go create mode 100644 vendor/golang.org/x/net/http2/go17.go create mode 100644 vendor/golang.org/x/net/http2/go17_not18.go create mode 100644 vendor/golang.org/x/net/http2/go18.go create mode 100644 vendor/golang.org/x/net/http2/go18_test.go create mode 100644 vendor/golang.org/x/net/http2/go19.go create mode 100644 vendor/golang.org/x/net/http2/go19_test.go create mode 100644 vendor/golang.org/x/net/http2/gotrack.go create mode 100644 vendor/golang.org/x/net/http2/gotrack_test.go create mode 100644 vendor/golang.org/x/net/http2/headermap.go create mode 100644 vendor/golang.org/x/net/http2/hpack/encode.go create mode 100644 vendor/golang.org/x/net/http2/hpack/encode_test.go create mode 100644 vendor/golang.org/x/net/http2/hpack/hpack.go create mode 100644 vendor/golang.org/x/net/http2/hpack/hpack_test.go create mode 100644 vendor/golang.org/x/net/http2/hpack/huffman.go create mode 100644 vendor/golang.org/x/net/http2/hpack/tables.go create mode 100644 vendor/golang.org/x/net/http2/hpack/tables_test.go create mode 100644 vendor/golang.org/x/net/http2/http2.go create mode 100644 vendor/golang.org/x/net/http2/http2_test.go create mode 100644 vendor/golang.org/x/net/http2/not_go16.go create mode 100644 vendor/golang.org/x/net/http2/not_go17.go create mode 100644 vendor/golang.org/x/net/http2/not_go18.go create mode 100644 vendor/golang.org/x/net/http2/not_go19.go create mode 100644 vendor/golang.org/x/net/http2/pipe.go create mode 100644 vendor/golang.org/x/net/http2/pipe_test.go create mode 100644 vendor/golang.org/x/net/http2/server.go create mode 100644 vendor/golang.org/x/net/http2/server_push_test.go create mode 100644 vendor/golang.org/x/net/http2/server_test.go create mode 100644 vendor/golang.org/x/net/http2/transport.go create mode 100644 vendor/golang.org/x/net/http2/transport_test.go create mode 100644 vendor/golang.org/x/net/http2/write.go create mode 100644 vendor/golang.org/x/net/http2/writesched.go create mode 100644 vendor/golang.org/x/net/http2/writesched_priority.go create mode 100644 vendor/golang.org/x/net/http2/writesched_priority_test.go create mode 100644 vendor/golang.org/x/net/http2/writesched_random.go create mode 100644 vendor/golang.org/x/net/http2/writesched_random_test.go create mode 100644 vendor/golang.org/x/net/http2/writesched_test.go create mode 100644 vendor/golang.org/x/net/http2/z_spec_test.go create mode 100644 vendor/golang.org/x/net/idna/example_test.go create mode 100644 vendor/golang.org/x/net/idna/idna.go create mode 100644 vendor/golang.org/x/net/idna/idna_test.go create mode 100644 vendor/golang.org/x/net/idna/punycode.go create mode 100644 vendor/golang.org/x/net/idna/punycode_test.go create mode 100644 vendor/golang.org/x/net/idna/tables.go create mode 100644 vendor/golang.org/x/net/idna/trie.go create mode 100644 vendor/golang.org/x/net/idna/trieval.go create mode 100644 vendor/golang.org/x/net/internal/timeseries/timeseries.go create mode 100644 vendor/golang.org/x/net/internal/timeseries/timeseries_test.go create mode 100644 vendor/golang.org/x/net/lex/httplex/httplex.go create mode 100644 vendor/golang.org/x/net/lex/httplex/httplex_test.go create mode 100644 vendor/golang.org/x/net/trace/events.go create mode 100644 vendor/golang.org/x/net/trace/histogram.go create mode 100644 vendor/golang.org/x/net/trace/histogram_test.go create mode 100644 vendor/golang.org/x/net/trace/trace.go create mode 100644 vendor/golang.org/x/net/trace/trace_go16.go create mode 100644 vendor/golang.org/x/net/trace/trace_go17.go create mode 100644 vendor/golang.org/x/net/trace/trace_test.go create mode 100644 vendor/golang.org/x/net/websocket/client.go create mode 100644 vendor/golang.org/x/net/websocket/dial.go create mode 100644 vendor/golang.org/x/net/websocket/dial_test.go create mode 100644 vendor/golang.org/x/net/websocket/exampledial_test.go create mode 100644 vendor/golang.org/x/net/websocket/examplehandler_test.go create mode 100644 vendor/golang.org/x/net/websocket/hybi.go create mode 100644 vendor/golang.org/x/net/websocket/hybi_test.go create mode 100644 vendor/golang.org/x/net/websocket/server.go create mode 100644 vendor/golang.org/x/net/websocket/websocket.go create mode 100644 vendor/golang.org/x/net/websocket/websocket_test.go create mode 100644 vendor/golang.org/x/sys/.gitattributes create mode 100644 vendor/golang.org/x/sys/.gitignore create mode 100644 vendor/golang.org/x/sys/AUTHORS create mode 100644 vendor/golang.org/x/sys/CONTRIBUTING.md create mode 100644 vendor/golang.org/x/sys/CONTRIBUTORS create mode 100644 vendor/golang.org/x/sys/LICENSE create mode 100644 vendor/golang.org/x/sys/PATENTS create mode 100644 vendor/golang.org/x/sys/README.md create mode 100644 vendor/golang.org/x/sys/codereview.cfg create mode 100644 vendor/golang.org/x/sys/unix/.gitignore create mode 100644 vendor/golang.org/x/sys/unix/README.md create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_mips64x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_mipsx.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_s390x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_solaris_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/bluetooth_linux.go create mode 100644 vendor/golang.org/x/sys/unix/cap_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/constants.go create mode 100644 vendor/golang.org/x/sys/unix/creds_test.go create mode 100644 vendor/golang.org/x/sys/unix/dev_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/dev_darwin_test.go create mode 100644 vendor/golang.org/x/sys/unix/dev_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/dev_dragonfly_test.go create mode 100644 vendor/golang.org/x/sys/unix/dev_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/dev_linux.go create mode 100644 vendor/golang.org/x/sys/unix/dev_linux_test.go create mode 100644 vendor/golang.org/x/sys/unix/dev_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/dev_netbsd_test.go create mode 100644 vendor/golang.org/x/sys/unix/dev_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/dev_openbsd_test.go create mode 100644 vendor/golang.org/x/sys/unix/dev_solaris_test.go create mode 100644 vendor/golang.org/x/sys/unix/dirent.go create mode 100644 vendor/golang.org/x/sys/unix/endian_big.go create mode 100644 vendor/golang.org/x/sys/unix/endian_little.go create mode 100644 vendor/golang.org/x/sys/unix/env_unix.go create mode 100644 vendor/golang.org/x/sys/unix/env_unset.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/export_test.go create mode 100644 vendor/golang.org/x/sys/unix/flock.go create mode 100644 vendor/golang.org/x/sys/unix/flock_linux_32bit.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo_c.c create mode 100644 vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go create mode 100755 vendor/golang.org/x/sys/unix/mkall.sh create mode 100755 vendor/golang.org/x/sys/unix/mkerrors.sh create mode 100644 vendor/golang.org/x/sys/unix/mkpost.go create mode 100755 vendor/golang.org/x/sys/unix/mksyscall.pl create mode 100755 vendor/golang.org/x/sys/unix/mksyscall_solaris.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_darwin.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl create mode 100644 vendor/golang.org/x/sys/unix/mmap_unix_test.go create mode 100644 vendor/golang.org/x/sys/unix/openbsd_pledge.go create mode 100644 vendor/golang.org/x/sys/unix/openbsd_test.go create mode 100644 vendor/golang.org/x/sys/unix/pagesize_unix.go create mode 100644 vendor/golang.org/x/sys/unix/race.go create mode 100644 vendor/golang.org/x/sys/unix/race0.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_linux.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix.go create mode 100644 vendor/golang.org/x/sys/unix/str.go create mode 100644 vendor/golang.org/x/sys/unix/syscall.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_bsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_bsd_test.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_test.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_test.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_no_getwd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris_test.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_test.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix_test.go create mode 100644 vendor/golang.org/x/sys/unix/timestruct.go create mode 100644 vendor/golang.org/x/sys/unix/types_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/types_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/types_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/types_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zptrace386_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptracearm_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptracemips_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptracemipsle_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go create mode 100644 vendor/golang.org/x/text/.gitattributes create mode 100644 vendor/golang.org/x/text/.gitignore create mode 100644 vendor/golang.org/x/text/AUTHORS create mode 100644 vendor/golang.org/x/text/CONTRIBUTING.md create mode 100644 vendor/golang.org/x/text/CONTRIBUTORS create mode 100644 vendor/golang.org/x/text/LICENSE create mode 100644 vendor/golang.org/x/text/PATENTS create mode 100644 vendor/golang.org/x/text/README.md create mode 100644 vendor/golang.org/x/text/codereview.cfg create mode 100644 vendor/golang.org/x/text/collate/build/builder.go create mode 100644 vendor/golang.org/x/text/collate/build/builder_test.go create mode 100644 vendor/golang.org/x/text/collate/build/colelem.go create mode 100644 vendor/golang.org/x/text/collate/build/colelem_test.go create mode 100644 vendor/golang.org/x/text/collate/build/contract.go create mode 100644 vendor/golang.org/x/text/collate/build/contract_test.go create mode 100644 vendor/golang.org/x/text/collate/build/order.go create mode 100644 vendor/golang.org/x/text/collate/build/order_test.go create mode 100644 vendor/golang.org/x/text/collate/build/table.go create mode 100644 vendor/golang.org/x/text/collate/build/trie.go create mode 100644 vendor/golang.org/x/text/collate/build/trie_test.go create mode 100644 vendor/golang.org/x/text/collate/collate.go create mode 100644 vendor/golang.org/x/text/collate/collate_test.go create mode 100644 vendor/golang.org/x/text/collate/export_test.go create mode 100644 vendor/golang.org/x/text/collate/index.go create mode 100644 vendor/golang.org/x/text/collate/maketables.go create mode 100644 vendor/golang.org/x/text/collate/option.go create mode 100644 vendor/golang.org/x/text/collate/option_test.go create mode 100644 vendor/golang.org/x/text/collate/reg_test.go create mode 100644 vendor/golang.org/x/text/collate/sort.go create mode 100644 vendor/golang.org/x/text/collate/sort_test.go create mode 100644 vendor/golang.org/x/text/collate/table_test.go create mode 100644 vendor/golang.org/x/text/collate/tables.go create mode 100644 vendor/golang.org/x/text/doc.go create mode 100644 vendor/golang.org/x/text/encoding/encoding.go create mode 100644 vendor/golang.org/x/text/encoding/encoding_test.go create mode 100644 vendor/golang.org/x/text/encoding/example_test.go create mode 100644 vendor/golang.org/x/text/encoding/internal/identifier/gen.go create mode 100644 vendor/golang.org/x/text/encoding/internal/identifier/identifier.go create mode 100644 vendor/golang.org/x/text/encoding/internal/identifier/mib.go create mode 100644 vendor/golang.org/x/text/encoding/internal/internal.go create mode 100644 vendor/golang.org/x/text/encoding/unicode/override.go create mode 100644 vendor/golang.org/x/text/encoding/unicode/unicode.go create mode 100644 vendor/golang.org/x/text/encoding/unicode/unicode_test.go create mode 100644 vendor/golang.org/x/text/gen.go create mode 100644 vendor/golang.org/x/text/internal/colltab/collate_test.go create mode 100644 vendor/golang.org/x/text/internal/colltab/collelem.go create mode 100644 vendor/golang.org/x/text/internal/colltab/collelem_test.go create mode 100644 vendor/golang.org/x/text/internal/colltab/colltab.go create mode 100644 vendor/golang.org/x/text/internal/colltab/colltab_test.go create mode 100644 vendor/golang.org/x/text/internal/colltab/contract.go create mode 100644 vendor/golang.org/x/text/internal/colltab/contract_test.go create mode 100644 vendor/golang.org/x/text/internal/colltab/iter.go create mode 100644 vendor/golang.org/x/text/internal/colltab/iter_test.go create mode 100644 vendor/golang.org/x/text/internal/colltab/numeric.go create mode 100644 vendor/golang.org/x/text/internal/colltab/numeric_test.go create mode 100644 vendor/golang.org/x/text/internal/colltab/table.go create mode 100644 vendor/golang.org/x/text/internal/colltab/trie.go create mode 100644 vendor/golang.org/x/text/internal/colltab/trie_test.go create mode 100644 vendor/golang.org/x/text/internal/colltab/weighter.go create mode 100644 vendor/golang.org/x/text/internal/colltab/weighter_test.go create mode 100644 vendor/golang.org/x/text/internal/gen.go create mode 100644 vendor/golang.org/x/text/internal/gen/code.go create mode 100644 vendor/golang.org/x/text/internal/gen/gen.go create mode 100644 vendor/golang.org/x/text/internal/gen_test.go create mode 100644 vendor/golang.org/x/text/internal/internal.go create mode 100644 vendor/golang.org/x/text/internal/internal_test.go create mode 100644 vendor/golang.org/x/text/internal/match.go create mode 100644 vendor/golang.org/x/text/internal/match_test.go create mode 100644 vendor/golang.org/x/text/internal/tables.go create mode 100644 vendor/golang.org/x/text/internal/tag/tag.go create mode 100644 vendor/golang.org/x/text/internal/tag/tag_test.go create mode 100644 vendor/golang.org/x/text/internal/triegen/compact.go create mode 100644 vendor/golang.org/x/text/internal/triegen/data_test.go create mode 100644 vendor/golang.org/x/text/internal/triegen/example_compact_test.go create mode 100644 vendor/golang.org/x/text/internal/triegen/example_test.go create mode 100644 vendor/golang.org/x/text/internal/triegen/gen_test.go create mode 100644 vendor/golang.org/x/text/internal/triegen/print.go create mode 100644 vendor/golang.org/x/text/internal/triegen/triegen.go create mode 100644 vendor/golang.org/x/text/internal/ucd/example_test.go create mode 100644 vendor/golang.org/x/text/internal/ucd/ucd.go create mode 100644 vendor/golang.org/x/text/internal/ucd/ucd_test.go create mode 100644 vendor/golang.org/x/text/internal/utf8internal/utf8internal.go create mode 100644 vendor/golang.org/x/text/language/Makefile create mode 100644 vendor/golang.org/x/text/language/common.go create mode 100644 vendor/golang.org/x/text/language/coverage.go create mode 100644 vendor/golang.org/x/text/language/coverage_test.go create mode 100644 vendor/golang.org/x/text/language/doc.go create mode 100644 vendor/golang.org/x/text/language/examples_test.go create mode 100644 vendor/golang.org/x/text/language/gen.go create mode 100644 vendor/golang.org/x/text/language/gen_common.go create mode 100644 vendor/golang.org/x/text/language/gen_index.go create mode 100644 vendor/golang.org/x/text/language/go1_1.go create mode 100644 vendor/golang.org/x/text/language/go1_2.go create mode 100644 vendor/golang.org/x/text/language/httpexample_test.go create mode 100644 vendor/golang.org/x/text/language/index.go create mode 100644 vendor/golang.org/x/text/language/language.go create mode 100644 vendor/golang.org/x/text/language/language_test.go create mode 100644 vendor/golang.org/x/text/language/lookup.go create mode 100644 vendor/golang.org/x/text/language/lookup_test.go create mode 100644 vendor/golang.org/x/text/language/match.go create mode 100644 vendor/golang.org/x/text/language/match_test.go create mode 100644 vendor/golang.org/x/text/language/parse.go create mode 100644 vendor/golang.org/x/text/language/parse_test.go create mode 100644 vendor/golang.org/x/text/language/tables.go create mode 100644 vendor/golang.org/x/text/language/tags.go create mode 100644 vendor/golang.org/x/text/runes/cond.go create mode 100644 vendor/golang.org/x/text/runes/cond_test.go create mode 100644 vendor/golang.org/x/text/runes/example_test.go create mode 100644 vendor/golang.org/x/text/runes/runes.go create mode 100644 vendor/golang.org/x/text/runes/runes_test.go create mode 100644 vendor/golang.org/x/text/secure/bidirule/bench_test.go create mode 100644 vendor/golang.org/x/text/secure/bidirule/bidirule.go create mode 100644 vendor/golang.org/x/text/secure/bidirule/bidirule_test.go create mode 100644 vendor/golang.org/x/text/secure/doc.go create mode 100644 vendor/golang.org/x/text/transform/examples_test.go create mode 100644 vendor/golang.org/x/text/transform/transform.go create mode 100644 vendor/golang.org/x/text/transform/transform_test.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/bidi.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/bracket.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/core.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/core_test.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_ranges.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/gen_trieval.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/prop.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/ranges_test.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/tables.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/tables_test.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/trieval.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/base.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/cldr.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/cldr_test.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/collate.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/collate_test.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/data_test.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/decode.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/examples_test.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/makexml.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/resolve.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/resolve_test.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/slice.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/slice_test.go create mode 100644 vendor/golang.org/x/text/unicode/cldr/xml.go create mode 100644 vendor/golang.org/x/text/unicode/doc.go create mode 100644 vendor/golang.org/x/text/unicode/norm/composition.go create mode 100644 vendor/golang.org/x/text/unicode/norm/composition_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/example_iter_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/example_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/forminfo.go create mode 100644 vendor/golang.org/x/text/unicode/norm/forminfo_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/input.go create mode 100644 vendor/golang.org/x/text/unicode/norm/iter.go create mode 100644 vendor/golang.org/x/text/unicode/norm/iter_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/maketables.go create mode 100644 vendor/golang.org/x/text/unicode/norm/normalize.go create mode 100644 vendor/golang.org/x/text/unicode/norm/normalize_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/readwriter.go create mode 100644 vendor/golang.org/x/text/unicode/norm/readwriter_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/tables.go create mode 100644 vendor/golang.org/x/text/unicode/norm/transform.go create mode 100644 vendor/golang.org/x/text/unicode/norm/transform_test.go create mode 100644 vendor/golang.org/x/text/unicode/norm/trie.go create mode 100644 vendor/golang.org/x/text/unicode/norm/triegen.go create mode 100644 vendor/golang.org/x/text/unicode/norm/ucd_test.go create mode 100644 vendor/golang.org/x/text/unicode/rangetable/gen.go create mode 100644 vendor/golang.org/x/text/unicode/rangetable/merge.go create mode 100644 vendor/golang.org/x/text/unicode/rangetable/merge_test.go create mode 100644 vendor/golang.org/x/text/unicode/rangetable/rangetable.go create mode 100644 vendor/golang.org/x/text/unicode/rangetable/rangetable_test.go create mode 100644 vendor/golang.org/x/text/unicode/rangetable/tables.go create mode 100644 vendor/google.golang.org/genproto/.travis.yml create mode 100644 vendor/google.golang.org/genproto/CONTRIBUTING.md create mode 100644 vendor/google.golang.org/genproto/LICENSE create mode 100644 vendor/google.golang.org/genproto/README.md create mode 100644 vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go create mode 100644 vendor/google.golang.org/genproto/regen.go create mode 100755 vendor/google.golang.org/genproto/regen.sh create mode 100644 vendor/google.golang.org/grpc/.please-update create mode 100644 vendor/google.golang.org/grpc/.travis.yml create mode 100644 vendor/google.golang.org/grpc/AUTHORS create mode 100644 vendor/google.golang.org/grpc/CONTRIBUTING.md create mode 100644 vendor/google.golang.org/grpc/LICENSE create mode 100644 vendor/google.golang.org/grpc/Makefile create mode 100644 vendor/google.golang.org/grpc/README.md create mode 100644 vendor/google.golang.org/grpc/backoff.go create mode 100644 vendor/google.golang.org/grpc/backoff_test.go create mode 100644 vendor/google.golang.org/grpc/balancer.go create mode 100644 vendor/google.golang.org/grpc/balancer/balancer.go create mode 100644 vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go create mode 100644 vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin_test.go create mode 100644 vendor/google.golang.org/grpc/balancer_conn_wrappers.go create mode 100644 vendor/google.golang.org/grpc/balancer_switching_test.go create mode 100644 vendor/google.golang.org/grpc/balancer_test.go create mode 100644 vendor/google.golang.org/grpc/balancer_v1_wrapper.go create mode 100644 vendor/google.golang.org/grpc/call.go create mode 100644 vendor/google.golang.org/grpc/call_test.go create mode 100644 vendor/google.golang.org/grpc/clientconn.go create mode 100644 vendor/google.golang.org/grpc/clientconn_test.go create mode 100644 vendor/google.golang.org/grpc/codec.go create mode 100644 vendor/google.golang.org/grpc/codec_benchmark_test.go create mode 100644 vendor/google.golang.org/grpc/codec_test.go create mode 100755 vendor/google.golang.org/grpc/codegen.sh create mode 100644 vendor/google.golang.org/grpc/codes/code_string.go create mode 100644 vendor/google.golang.org/grpc/codes/codes.go create mode 100644 vendor/google.golang.org/grpc/connectivity/connectivity.go create mode 100644 vendor/google.golang.org/grpc/credentials/credentials.go create mode 100644 vendor/google.golang.org/grpc/credentials/credentials_test.go create mode 100644 vendor/google.golang.org/grpc/credentials/credentials_util_go17.go create mode 100644 vendor/google.golang.org/grpc/credentials/credentials_util_go18.go create mode 100644 vendor/google.golang.org/grpc/credentials/credentials_util_pre_go17.go create mode 100644 vendor/google.golang.org/grpc/doc.go create mode 100644 vendor/google.golang.org/grpc/encoding/encoding.go create mode 100644 vendor/google.golang.org/grpc/go16.go create mode 100644 vendor/google.golang.org/grpc/go17.go create mode 100644 vendor/google.golang.org/grpc/grpclb.go create mode 100644 vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/messages/messages.pb.go create mode 100644 vendor/google.golang.org/grpc/grpclb/grpc_lb_v1/messages/messages.proto create mode 100644 vendor/google.golang.org/grpc/grpclb/grpclb_test.go create mode 100644 vendor/google.golang.org/grpc/grpclog/grpclog.go create mode 100644 vendor/google.golang.org/grpc/grpclog/logger.go create mode 100644 vendor/google.golang.org/grpc/grpclog/loggerv2.go create mode 100644 vendor/google.golang.org/grpc/grpclog/loggerv2_test.go create mode 100644 vendor/google.golang.org/grpc/interceptor.go create mode 100644 vendor/google.golang.org/grpc/internal/internal.go create mode 100644 vendor/google.golang.org/grpc/keepalive/keepalive.go create mode 100644 vendor/google.golang.org/grpc/metadata/metadata.go create mode 100644 vendor/google.golang.org/grpc/metadata/metadata_test.go create mode 100644 vendor/google.golang.org/grpc/naming/dns_resolver.go create mode 100644 vendor/google.golang.org/grpc/naming/dns_resolver_test.go create mode 100644 vendor/google.golang.org/grpc/naming/go17.go create mode 100644 vendor/google.golang.org/grpc/naming/go17_test.go create mode 100644 vendor/google.golang.org/grpc/naming/go18.go create mode 100644 vendor/google.golang.org/grpc/naming/go18_test.go create mode 100644 vendor/google.golang.org/grpc/naming/naming.go create mode 100644 vendor/google.golang.org/grpc/peer/peer.go create mode 100644 vendor/google.golang.org/grpc/picker_wrapper.go create mode 100644 vendor/google.golang.org/grpc/picker_wrapper_test.go create mode 100644 vendor/google.golang.org/grpc/pickfirst.go create mode 100644 vendor/google.golang.org/grpc/pickfirst_test.go create mode 100644 vendor/google.golang.org/grpc/proxy.go create mode 100644 vendor/google.golang.org/grpc/proxy_test.go create mode 100644 vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go create mode 100644 vendor/google.golang.org/grpc/resolver/dns/dns_resolver_test.go create mode 100644 vendor/google.golang.org/grpc/resolver/dns/go17.go create mode 100644 vendor/google.golang.org/grpc/resolver/dns/go17_test.go create mode 100644 vendor/google.golang.org/grpc/resolver/dns/go18.go create mode 100644 vendor/google.golang.org/grpc/resolver/dns/go18_test.go create mode 100644 vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go create mode 100644 vendor/google.golang.org/grpc/resolver/resolver.go create mode 100644 vendor/google.golang.org/grpc/resolver_conn_wrapper.go create mode 100644 vendor/google.golang.org/grpc/resolver_conn_wrapper_test.go create mode 100644 vendor/google.golang.org/grpc/rpc_util.go create mode 100644 vendor/google.golang.org/grpc/rpc_util_test.go create mode 100644 vendor/google.golang.org/grpc/server.go create mode 100644 vendor/google.golang.org/grpc/server_test.go create mode 100644 vendor/google.golang.org/grpc/service_config.go create mode 100644 vendor/google.golang.org/grpc/service_config_test.go create mode 100644 vendor/google.golang.org/grpc/stats/handlers.go create mode 100644 vendor/google.golang.org/grpc/stats/stats.go create mode 100644 vendor/google.golang.org/grpc/stats/stats_test.go create mode 100644 vendor/google.golang.org/grpc/status/status.go create mode 100644 vendor/google.golang.org/grpc/status/status_test.go create mode 100644 vendor/google.golang.org/grpc/stream.go create mode 100644 vendor/google.golang.org/grpc/tap/tap.go create mode 100644 vendor/google.golang.org/grpc/trace.go create mode 100644 vendor/google.golang.org/grpc/transport/bdp_estimator.go create mode 100644 vendor/google.golang.org/grpc/transport/control.go create mode 100644 vendor/google.golang.org/grpc/transport/go16.go create mode 100644 vendor/google.golang.org/grpc/transport/go17.go create mode 100644 vendor/google.golang.org/grpc/transport/handler_server.go create mode 100644 vendor/google.golang.org/grpc/transport/handler_server_test.go create mode 100644 vendor/google.golang.org/grpc/transport/http2_client.go create mode 100644 vendor/google.golang.org/grpc/transport/http2_server.go create mode 100644 vendor/google.golang.org/grpc/transport/http_util.go create mode 100644 vendor/google.golang.org/grpc/transport/http_util_test.go create mode 100644 vendor/google.golang.org/grpc/transport/log.go create mode 100644 vendor/google.golang.org/grpc/transport/transport.go create mode 100644 vendor/google.golang.org/grpc/transport/transport_test.go create mode 100755 vendor/google.golang.org/grpc/vet.sh create mode 100644 vendor/gopkg.in/mgo.v2/.travis.yml create mode 100644 vendor/gopkg.in/mgo.v2/LICENSE create mode 100644 vendor/gopkg.in/mgo.v2/Makefile create mode 100644 vendor/gopkg.in/mgo.v2/README.md create mode 100644 vendor/gopkg.in/mgo.v2/auth.go create mode 100644 vendor/gopkg.in/mgo.v2/auth_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/LICENSE create mode 100644 vendor/gopkg.in/mgo.v2/bson/bson.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/bson_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/decimal.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/decimal_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/decode.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/encode.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/json.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/json_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bson/specdata_test.go create mode 100644 vendor/gopkg.in/mgo.v2/bulk.go create mode 100644 vendor/gopkg.in/mgo.v2/bulk_test.go create mode 100644 vendor/gopkg.in/mgo.v2/cluster.go create mode 100644 vendor/gopkg.in/mgo.v2/cluster_test.go create mode 100644 vendor/gopkg.in/mgo.v2/doc.go create mode 100644 vendor/gopkg.in/mgo.v2/export_test.go create mode 100644 vendor/gopkg.in/mgo.v2/gridfs.go create mode 100644 vendor/gopkg.in/mgo.v2/gridfs_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/LICENSE create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/bench_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/decode.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/decode_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/encode.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/encode_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/example_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/extension.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/extension_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/fold.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/fold_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/indent.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/number_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/scanner.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/scanner_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/stream.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/stream_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/tagkey_test.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/tags.go create mode 100644 vendor/gopkg.in/mgo.v2/internal/json/tags_test.go create mode 100644 vendor/gopkg.in/mgo.v2/log.go create mode 100644 vendor/gopkg.in/mgo.v2/queue.go create mode 100644 vendor/gopkg.in/mgo.v2/queue_test.go create mode 100644 vendor/gopkg.in/mgo.v2/raceoff.go create mode 100644 vendor/gopkg.in/mgo.v2/raceon.go create mode 100644 vendor/gopkg.in/mgo.v2/saslimpl.go create mode 100644 vendor/gopkg.in/mgo.v2/saslstub.go create mode 100644 vendor/gopkg.in/mgo.v2/server.go create mode 100644 vendor/gopkg.in/mgo.v2/session.go create mode 100644 vendor/gopkg.in/mgo.v2/session_test.go create mode 100644 vendor/gopkg.in/mgo.v2/socket.go create mode 100644 vendor/gopkg.in/mgo.v2/stats.go create mode 100644 vendor/gopkg.in/mgo.v2/suite_test.go create mode 100644 vendor/gopkg.in/mgo.v2/syscall_test.go create mode 100644 vendor/gopkg.in/mgo.v2/syscall_windows_test.go create mode 100644 vendor/gopkg.in/yaml.v2/.travis.yml create mode 100644 vendor/gopkg.in/yaml.v2/LICENSE create mode 100644 vendor/gopkg.in/yaml.v2/LICENSE.libyaml create mode 100644 vendor/gopkg.in/yaml.v2/README.md create mode 100644 vendor/gopkg.in/yaml.v2/apic.go create mode 100644 vendor/gopkg.in/yaml.v2/decode.go create mode 100644 vendor/gopkg.in/yaml.v2/decode_test.go create mode 100644 vendor/gopkg.in/yaml.v2/emitterc.go create mode 100644 vendor/gopkg.in/yaml.v2/encode.go create mode 100644 vendor/gopkg.in/yaml.v2/encode_test.go create mode 100644 vendor/gopkg.in/yaml.v2/example_embedded_test.go create mode 100644 vendor/gopkg.in/yaml.v2/parserc.go create mode 100644 vendor/gopkg.in/yaml.v2/readerc.go create mode 100644 vendor/gopkg.in/yaml.v2/resolve.go create mode 100644 vendor/gopkg.in/yaml.v2/scannerc.go create mode 100644 vendor/gopkg.in/yaml.v2/sorter.go create mode 100644 vendor/gopkg.in/yaml.v2/suite_test.go create mode 100644 vendor/gopkg.in/yaml.v2/writerc.go create mode 100644 vendor/gopkg.in/yaml.v2/yaml.go create mode 100644 vendor/gopkg.in/yaml.v2/yamlh.go create mode 100644 vendor/gopkg.in/yaml.v2/yamlprivateh.go diff --git a/vendor/github.com/Azure/go-ansiterm/LICENSE b/vendor/github.com/Azure/go-ansiterm/LICENSE new file mode 100644 index 0000000..e3d9a64 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/Azure/go-ansiterm/README.md b/vendor/github.com/Azure/go-ansiterm/README.md new file mode 100644 index 0000000..261c041 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/README.md @@ -0,0 +1,12 @@ +# go-ansiterm + +This is a cross platform Ansi Terminal Emulation library. It reads a stream of Ansi characters and produces the appropriate function calls. The results of the function calls are platform dependent. + +For example the parser might receive "ESC, [, A" as a stream of three characters. This is the code for Cursor Up (http://www.vt100.net/docs/vt510-rm/CUU). The parser then calls the cursor up function (CUU()) on an event handler. The event handler determines what platform specific work must be done to cause the cursor to move up one position. + +The parser (parser.go) is a partial implementation of this state machine (http://vt100.net/emu/vt500_parser.png). There are also two event handler implementations, one for tests (test_event_handler.go) to validate that the expected events are being produced and called, the other is a Windows implementation (winterm/win_event_handler.go). + +See parser_test.go for examples exercising the state machine and generating appropriate function calls. + +----- +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/vendor/github.com/Azure/go-ansiterm/constants.go b/vendor/github.com/Azure/go-ansiterm/constants.go new file mode 100644 index 0000000..96504a3 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/constants.go @@ -0,0 +1,188 @@ +package ansiterm + +const LogEnv = "DEBUG_TERMINAL" + +// ANSI constants +// References: +// -- http://www.ecma-international.org/publications/standards/Ecma-048.htm +// -- http://man7.org/linux/man-pages/man4/console_codes.4.html +// -- http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html +// -- http://en.wikipedia.org/wiki/ANSI_escape_code +// -- http://vt100.net/emu/dec_ansi_parser +// -- http://vt100.net/emu/vt500_parser.svg +// -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html +// -- http://www.inwap.com/pdp10/ansicode.txt +const ( + // ECMA-48 Set Graphics Rendition + // Note: + // -- Constants leading with an underscore (e.g., _ANSI_xxx) are unsupported or reserved + // -- Fonts could possibly be supported via SetCurrentConsoleFontEx + // -- Windows does not expose the per-window cursor (i.e., caret) blink times + ANSI_SGR_RESET = 0 + ANSI_SGR_BOLD = 1 + ANSI_SGR_DIM = 2 + _ANSI_SGR_ITALIC = 3 + ANSI_SGR_UNDERLINE = 4 + _ANSI_SGR_BLINKSLOW = 5 + _ANSI_SGR_BLINKFAST = 6 + ANSI_SGR_REVERSE = 7 + _ANSI_SGR_INVISIBLE = 8 + _ANSI_SGR_LINETHROUGH = 9 + _ANSI_SGR_FONT_00 = 10 + _ANSI_SGR_FONT_01 = 11 + _ANSI_SGR_FONT_02 = 12 + _ANSI_SGR_FONT_03 = 13 + _ANSI_SGR_FONT_04 = 14 + _ANSI_SGR_FONT_05 = 15 + _ANSI_SGR_FONT_06 = 16 + _ANSI_SGR_FONT_07 = 17 + _ANSI_SGR_FONT_08 = 18 + _ANSI_SGR_FONT_09 = 19 + _ANSI_SGR_FONT_10 = 20 + _ANSI_SGR_DOUBLEUNDERLINE = 21 + ANSI_SGR_BOLD_DIM_OFF = 22 + _ANSI_SGR_ITALIC_OFF = 23 + ANSI_SGR_UNDERLINE_OFF = 24 + _ANSI_SGR_BLINK_OFF = 25 + _ANSI_SGR_RESERVED_00 = 26 + ANSI_SGR_REVERSE_OFF = 27 + _ANSI_SGR_INVISIBLE_OFF = 28 + _ANSI_SGR_LINETHROUGH_OFF = 29 + ANSI_SGR_FOREGROUND_BLACK = 30 + ANSI_SGR_FOREGROUND_RED = 31 + ANSI_SGR_FOREGROUND_GREEN = 32 + ANSI_SGR_FOREGROUND_YELLOW = 33 + ANSI_SGR_FOREGROUND_BLUE = 34 + ANSI_SGR_FOREGROUND_MAGENTA = 35 + ANSI_SGR_FOREGROUND_CYAN = 36 + ANSI_SGR_FOREGROUND_WHITE = 37 + _ANSI_SGR_RESERVED_01 = 38 + ANSI_SGR_FOREGROUND_DEFAULT = 39 + ANSI_SGR_BACKGROUND_BLACK = 40 + ANSI_SGR_BACKGROUND_RED = 41 + ANSI_SGR_BACKGROUND_GREEN = 42 + ANSI_SGR_BACKGROUND_YELLOW = 43 + ANSI_SGR_BACKGROUND_BLUE = 44 + ANSI_SGR_BACKGROUND_MAGENTA = 45 + ANSI_SGR_BACKGROUND_CYAN = 46 + ANSI_SGR_BACKGROUND_WHITE = 47 + _ANSI_SGR_RESERVED_02 = 48 + ANSI_SGR_BACKGROUND_DEFAULT = 49 + // 50 - 65: Unsupported + + ANSI_MAX_CMD_LENGTH = 4096 + + MAX_INPUT_EVENTS = 128 + DEFAULT_WIDTH = 80 + DEFAULT_HEIGHT = 24 + + ANSI_BEL = 0x07 + ANSI_BACKSPACE = 0x08 + ANSI_TAB = 0x09 + ANSI_LINE_FEED = 0x0A + ANSI_VERTICAL_TAB = 0x0B + ANSI_FORM_FEED = 0x0C + ANSI_CARRIAGE_RETURN = 0x0D + ANSI_ESCAPE_PRIMARY = 0x1B + ANSI_ESCAPE_SECONDARY = 0x5B + ANSI_OSC_STRING_ENTRY = 0x5D + ANSI_COMMAND_FIRST = 0x40 + ANSI_COMMAND_LAST = 0x7E + DCS_ENTRY = 0x90 + CSI_ENTRY = 0x9B + OSC_STRING = 0x9D + ANSI_PARAMETER_SEP = ";" + ANSI_CMD_G0 = '(' + ANSI_CMD_G1 = ')' + ANSI_CMD_G2 = '*' + ANSI_CMD_G3 = '+' + ANSI_CMD_DECPNM = '>' + ANSI_CMD_DECPAM = '=' + ANSI_CMD_OSC = ']' + ANSI_CMD_STR_TERM = '\\' + + KEY_CONTROL_PARAM_2 = ";2" + KEY_CONTROL_PARAM_3 = ";3" + KEY_CONTROL_PARAM_4 = ";4" + KEY_CONTROL_PARAM_5 = ";5" + KEY_CONTROL_PARAM_6 = ";6" + KEY_CONTROL_PARAM_7 = ";7" + KEY_CONTROL_PARAM_8 = ";8" + KEY_ESC_CSI = "\x1B[" + KEY_ESC_N = "\x1BN" + KEY_ESC_O = "\x1BO" + + FILL_CHARACTER = ' ' +) + +func getByteRange(start byte, end byte) []byte { + bytes := make([]byte, 0, 32) + for i := start; i <= end; i++ { + bytes = append(bytes, byte(i)) + } + + return bytes +} + +var toGroundBytes = getToGroundBytes() +var executors = getExecuteBytes() + +// SPACE 20+A0 hex Always and everywhere a blank space +// Intermediate 20-2F hex !"#$%&'()*+,-./ +var intermeds = getByteRange(0x20, 0x2F) + +// Parameters 30-3F hex 0123456789:;<=>? +// CSI Parameters 30-39, 3B hex 0123456789; +var csiParams = getByteRange(0x30, 0x3F) + +var csiCollectables = append(getByteRange(0x30, 0x39), getByteRange(0x3B, 0x3F)...) + +// Uppercase 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ +var upperCase = getByteRange(0x40, 0x5F) + +// Lowercase 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~ +var lowerCase = getByteRange(0x60, 0x7E) + +// Alphabetics 40-7E hex (all of upper and lower case) +var alphabetics = append(upperCase, lowerCase...) + +var printables = getByteRange(0x20, 0x7F) + +var escapeIntermediateToGroundBytes = getByteRange(0x30, 0x7E) +var escapeToGroundBytes = getEscapeToGroundBytes() + +// See http://www.vt100.net/emu/vt500_parser.png for description of the complex +// byte ranges below + +func getEscapeToGroundBytes() []byte { + escapeToGroundBytes := getByteRange(0x30, 0x4F) + escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x51, 0x57)...) + escapeToGroundBytes = append(escapeToGroundBytes, 0x59) + escapeToGroundBytes = append(escapeToGroundBytes, 0x5A) + escapeToGroundBytes = append(escapeToGroundBytes, 0x5C) + escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x60, 0x7E)...) + return escapeToGroundBytes +} + +func getExecuteBytes() []byte { + executeBytes := getByteRange(0x00, 0x17) + executeBytes = append(executeBytes, 0x19) + executeBytes = append(executeBytes, getByteRange(0x1C, 0x1F)...) + return executeBytes +} + +func getToGroundBytes() []byte { + groundBytes := []byte{0x18} + groundBytes = append(groundBytes, 0x1A) + groundBytes = append(groundBytes, getByteRange(0x80, 0x8F)...) + groundBytes = append(groundBytes, getByteRange(0x91, 0x97)...) + groundBytes = append(groundBytes, 0x99) + groundBytes = append(groundBytes, 0x9A) + groundBytes = append(groundBytes, 0x9C) + return groundBytes +} + +// Delete 7F hex Always and everywhere ignored +// C1 Control 80-9F hex 32 additional control characters +// G1 Displayable A1-FE hex 94 additional displayable characters +// Special A0+FF hex Same as SPACE and DELETE diff --git a/vendor/github.com/Azure/go-ansiterm/context.go b/vendor/github.com/Azure/go-ansiterm/context.go new file mode 100644 index 0000000..8d66e77 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/context.go @@ -0,0 +1,7 @@ +package ansiterm + +type ansiContext struct { + currentChar byte + paramBuffer []byte + interBuffer []byte +} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go new file mode 100644 index 0000000..bcbe00d --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go @@ -0,0 +1,49 @@ +package ansiterm + +type csiEntryState struct { + baseState +} + +func (csiState csiEntryState) Handle(b byte) (s state, e error) { + csiState.parser.logf("CsiEntry::Handle %#x", b) + + nextState, err := csiState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(alphabetics, b): + return csiState.parser.ground, nil + case sliceContains(csiCollectables, b): + return csiState.parser.csiParam, nil + case sliceContains(executors, b): + return csiState, csiState.parser.execute() + } + + return csiState, nil +} + +func (csiState csiEntryState) Transition(s state) error { + csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name()) + csiState.baseState.Transition(s) + + switch s { + case csiState.parser.ground: + return csiState.parser.csiDispatch() + case csiState.parser.csiParam: + switch { + case sliceContains(csiParams, csiState.parser.context.currentChar): + csiState.parser.collectParam() + case sliceContains(intermeds, csiState.parser.context.currentChar): + csiState.parser.collectInter() + } + } + + return nil +} + +func (csiState csiEntryState) Enter() error { + csiState.parser.clear() + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go new file mode 100644 index 0000000..7ed5e01 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go @@ -0,0 +1,38 @@ +package ansiterm + +type csiParamState struct { + baseState +} + +func (csiState csiParamState) Handle(b byte) (s state, e error) { + csiState.parser.logf("CsiParam::Handle %#x", b) + + nextState, err := csiState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(alphabetics, b): + return csiState.parser.ground, nil + case sliceContains(csiCollectables, b): + csiState.parser.collectParam() + return csiState, nil + case sliceContains(executors, b): + return csiState, csiState.parser.execute() + } + + return csiState, nil +} + +func (csiState csiParamState) Transition(s state) error { + csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name()) + csiState.baseState.Transition(s) + + switch s { + case csiState.parser.ground: + return csiState.parser.csiDispatch() + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go new file mode 100644 index 0000000..1c719db --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go @@ -0,0 +1,36 @@ +package ansiterm + +type escapeIntermediateState struct { + baseState +} + +func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { + escState.parser.logf("escapeIntermediateState::Handle %#x", b) + nextState, err := escState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(intermeds, b): + return escState, escState.parser.collectInter() + case sliceContains(executors, b): + return escState, escState.parser.execute() + case sliceContains(escapeIntermediateToGroundBytes, b): + return escState.parser.ground, nil + } + + return escState, nil +} + +func (escState escapeIntermediateState) Transition(s state) error { + escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name()) + escState.baseState.Transition(s) + + switch s { + case escState.parser.ground: + return escState.parser.escDispatch() + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_state.go b/vendor/github.com/Azure/go-ansiterm/escape_state.go new file mode 100644 index 0000000..6390abd --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/escape_state.go @@ -0,0 +1,47 @@ +package ansiterm + +type escapeState struct { + baseState +} + +func (escState escapeState) Handle(b byte) (s state, e error) { + escState.parser.logf("escapeState::Handle %#x", b) + nextState, err := escState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case b == ANSI_ESCAPE_SECONDARY: + return escState.parser.csiEntry, nil + case b == ANSI_OSC_STRING_ENTRY: + return escState.parser.oscString, nil + case sliceContains(executors, b): + return escState, escState.parser.execute() + case sliceContains(escapeToGroundBytes, b): + return escState.parser.ground, nil + case sliceContains(intermeds, b): + return escState.parser.escapeIntermediate, nil + } + + return escState, nil +} + +func (escState escapeState) Transition(s state) error { + escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name()) + escState.baseState.Transition(s) + + switch s { + case escState.parser.ground: + return escState.parser.escDispatch() + case escState.parser.escapeIntermediate: + return escState.parser.collectInter() + } + + return nil +} + +func (escState escapeState) Enter() error { + escState.parser.clear() + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/event_handler.go b/vendor/github.com/Azure/go-ansiterm/event_handler.go new file mode 100644 index 0000000..98087b3 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/event_handler.go @@ -0,0 +1,90 @@ +package ansiterm + +type AnsiEventHandler interface { + // Print + Print(b byte) error + + // Execute C0 commands + Execute(b byte) error + + // CUrsor Up + CUU(int) error + + // CUrsor Down + CUD(int) error + + // CUrsor Forward + CUF(int) error + + // CUrsor Backward + CUB(int) error + + // Cursor to Next Line + CNL(int) error + + // Cursor to Previous Line + CPL(int) error + + // Cursor Horizontal position Absolute + CHA(int) error + + // Vertical line Position Absolute + VPA(int) error + + // CUrsor Position + CUP(int, int) error + + // Horizontal and Vertical Position (depends on PUM) + HVP(int, int) error + + // Text Cursor Enable Mode + DECTCEM(bool) error + + // Origin Mode + DECOM(bool) error + + // 132 Column Mode + DECCOLM(bool) error + + // Erase in Display + ED(int) error + + // Erase in Line + EL(int) error + + // Insert Line + IL(int) error + + // Delete Line + DL(int) error + + // Insert Character + ICH(int) error + + // Delete Character + DCH(int) error + + // Set Graphics Rendition + SGR([]int) error + + // Pan Down + SU(int) error + + // Pan Up + SD(int) error + + // Device Attributes + DA([]string) error + + // Set Top and Bottom Margins + DECSTBM(int, int) error + + // Index + IND() error + + // Reverse Index + RI() error + + // Flush updates from previous commands + Flush() error +} diff --git a/vendor/github.com/Azure/go-ansiterm/ground_state.go b/vendor/github.com/Azure/go-ansiterm/ground_state.go new file mode 100644 index 0000000..52451e9 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/ground_state.go @@ -0,0 +1,24 @@ +package ansiterm + +type groundState struct { + baseState +} + +func (gs groundState) Handle(b byte) (s state, e error) { + gs.parser.context.currentChar = b + + nextState, err := gs.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(printables, b): + return gs, gs.parser.print() + + case sliceContains(executors, b): + return gs, gs.parser.execute() + } + + return gs, nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go new file mode 100644 index 0000000..593b10a --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go @@ -0,0 +1,31 @@ +package ansiterm + +type oscStringState struct { + baseState +} + +func (oscState oscStringState) Handle(b byte) (s state, e error) { + oscState.parser.logf("OscString::Handle %#x", b) + nextState, err := oscState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case isOscStringTerminator(b): + return oscState.parser.ground, nil + } + + return oscState, nil +} + +// See below for OSC string terminators for linux +// http://man7.org/linux/man-pages/man4/console_codes.4.html +func isOscStringTerminator(b byte) bool { + + if b == ANSI_BEL || b == 0x5C { + return true + } + + return false +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser.go b/vendor/github.com/Azure/go-ansiterm/parser.go new file mode 100644 index 0000000..03cec7a --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser.go @@ -0,0 +1,151 @@ +package ansiterm + +import ( + "errors" + "log" + "os" +) + +type AnsiParser struct { + currState state + eventHandler AnsiEventHandler + context *ansiContext + csiEntry state + csiParam state + dcsEntry state + escape state + escapeIntermediate state + error state + ground state + oscString state + stateMap []state + + logf func(string, ...interface{}) +} + +type Option func(*AnsiParser) + +func WithLogf(f func(string, ...interface{})) Option { + return func(ap *AnsiParser) { + ap.logf = f + } +} + +func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser { + ap := &AnsiParser{ + eventHandler: evtHandler, + context: &ansiContext{}, + } + for _, o := range opts { + o(ap) + } + + if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" { + logFile, _ := os.Create("ansiParser.log") + logger := log.New(logFile, "", log.LstdFlags) + if ap.logf != nil { + l := ap.logf + ap.logf = func(s string, v ...interface{}) { + l(s, v...) + logger.Printf(s, v...) + } + } else { + ap.logf = logger.Printf + } + } + + if ap.logf == nil { + ap.logf = func(string, ...interface{}) {} + } + + ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}} + ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}} + ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}} + ap.escape = escapeState{baseState{name: "Escape", parser: ap}} + ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}} + ap.error = errorState{baseState{name: "Error", parser: ap}} + ap.ground = groundState{baseState{name: "Ground", parser: ap}} + ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}} + + ap.stateMap = []state{ + ap.csiEntry, + ap.csiParam, + ap.dcsEntry, + ap.escape, + ap.escapeIntermediate, + ap.error, + ap.ground, + ap.oscString, + } + + ap.currState = getState(initialState, ap.stateMap) + + ap.logf("CreateParser: parser %p", ap) + return ap +} + +func getState(name string, states []state) state { + for _, el := range states { + if el.Name() == name { + return el + } + } + + return nil +} + +func (ap *AnsiParser) Parse(bytes []byte) (int, error) { + for i, b := range bytes { + if err := ap.handle(b); err != nil { + return i, err + } + } + + return len(bytes), ap.eventHandler.Flush() +} + +func (ap *AnsiParser) handle(b byte) error { + ap.context.currentChar = b + newState, err := ap.currState.Handle(b) + if err != nil { + return err + } + + if newState == nil { + ap.logf("WARNING: newState is nil") + return errors.New("New state of 'nil' is invalid.") + } + + if newState != ap.currState { + if err := ap.changeState(newState); err != nil { + return err + } + } + + return nil +} + +func (ap *AnsiParser) changeState(newState state) error { + ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name()) + + // Exit old state + if err := ap.currState.Exit(); err != nil { + ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err) + return err + } + + // Perform transition action + if err := ap.currState.Transition(newState); err != nil { + ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err) + return err + } + + // Enter new state + if err := newState.Enter(); err != nil { + ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err) + return err + } + + ap.currState = newState + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go new file mode 100644 index 0000000..de0a1f9 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go @@ -0,0 +1,99 @@ +package ansiterm + +import ( + "strconv" +) + +func parseParams(bytes []byte) ([]string, error) { + paramBuff := make([]byte, 0, 0) + params := []string{} + + for _, v := range bytes { + if v == ';' { + if len(paramBuff) > 0 { + // Completed parameter, append it to the list + s := string(paramBuff) + params = append(params, s) + paramBuff = make([]byte, 0, 0) + } + } else { + paramBuff = append(paramBuff, v) + } + } + + // Last parameter may not be terminated with ';' + if len(paramBuff) > 0 { + s := string(paramBuff) + params = append(params, s) + } + + return params, nil +} + +func parseCmd(context ansiContext) (string, error) { + return string(context.currentChar), nil +} + +func getInt(params []string, dflt int) int { + i := getInts(params, 1, dflt)[0] + return i +} + +func getInts(params []string, minCount int, dflt int) []int { + ints := []int{} + + for _, v := range params { + i, _ := strconv.Atoi(v) + // Zero is mapped to the default value in VT100. + if i == 0 { + i = dflt + } + ints = append(ints, i) + } + + if len(ints) < minCount { + remaining := minCount - len(ints) + for i := 0; i < remaining; i++ { + ints = append(ints, dflt) + } + } + + return ints +} + +func (ap *AnsiParser) modeDispatch(param string, set bool) error { + switch param { + case "?3": + return ap.eventHandler.DECCOLM(set) + case "?6": + return ap.eventHandler.DECOM(set) + case "?25": + return ap.eventHandler.DECTCEM(set) + } + return nil +} + +func (ap *AnsiParser) hDispatch(params []string) error { + if len(params) == 1 { + return ap.modeDispatch(params[0], true) + } + + return nil +} + +func (ap *AnsiParser) lDispatch(params []string) error { + if len(params) == 1 { + return ap.modeDispatch(params[0], false) + } + + return nil +} + +func getEraseParam(params []string) int { + param := getInt(params, 0) + if param < 0 || 3 < param { + param = 0 + } + + return param +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_actions.go b/vendor/github.com/Azure/go-ansiterm/parser_actions.go new file mode 100644 index 0000000..0bb5e51 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_actions.go @@ -0,0 +1,119 @@ +package ansiterm + +func (ap *AnsiParser) collectParam() error { + currChar := ap.context.currentChar + ap.logf("collectParam %#x", currChar) + ap.context.paramBuffer = append(ap.context.paramBuffer, currChar) + return nil +} + +func (ap *AnsiParser) collectInter() error { + currChar := ap.context.currentChar + ap.logf("collectInter %#x", currChar) + ap.context.paramBuffer = append(ap.context.interBuffer, currChar) + return nil +} + +func (ap *AnsiParser) escDispatch() error { + cmd, _ := parseCmd(*ap.context) + intermeds := ap.context.interBuffer + ap.logf("escDispatch currentChar: %#x", ap.context.currentChar) + ap.logf("escDispatch: %v(%v)", cmd, intermeds) + + switch cmd { + case "D": // IND + return ap.eventHandler.IND() + case "E": // NEL, equivalent to CRLF + err := ap.eventHandler.Execute(ANSI_CARRIAGE_RETURN) + if err == nil { + err = ap.eventHandler.Execute(ANSI_LINE_FEED) + } + return err + case "M": // RI + return ap.eventHandler.RI() + } + + return nil +} + +func (ap *AnsiParser) csiDispatch() error { + cmd, _ := parseCmd(*ap.context) + params, _ := parseParams(ap.context.paramBuffer) + ap.logf("Parsed params: %v with length: %d", params, len(params)) + + ap.logf("csiDispatch: %v(%v)", cmd, params) + + switch cmd { + case "@": + return ap.eventHandler.ICH(getInt(params, 1)) + case "A": + return ap.eventHandler.CUU(getInt(params, 1)) + case "B": + return ap.eventHandler.CUD(getInt(params, 1)) + case "C": + return ap.eventHandler.CUF(getInt(params, 1)) + case "D": + return ap.eventHandler.CUB(getInt(params, 1)) + case "E": + return ap.eventHandler.CNL(getInt(params, 1)) + case "F": + return ap.eventHandler.CPL(getInt(params, 1)) + case "G": + return ap.eventHandler.CHA(getInt(params, 1)) + case "H": + ints := getInts(params, 2, 1) + x, y := ints[0], ints[1] + return ap.eventHandler.CUP(x, y) + case "J": + param := getEraseParam(params) + return ap.eventHandler.ED(param) + case "K": + param := getEraseParam(params) + return ap.eventHandler.EL(param) + case "L": + return ap.eventHandler.IL(getInt(params, 1)) + case "M": + return ap.eventHandler.DL(getInt(params, 1)) + case "P": + return ap.eventHandler.DCH(getInt(params, 1)) + case "S": + return ap.eventHandler.SU(getInt(params, 1)) + case "T": + return ap.eventHandler.SD(getInt(params, 1)) + case "c": + return ap.eventHandler.DA(params) + case "d": + return ap.eventHandler.VPA(getInt(params, 1)) + case "f": + ints := getInts(params, 2, 1) + x, y := ints[0], ints[1] + return ap.eventHandler.HVP(x, y) + case "h": + return ap.hDispatch(params) + case "l": + return ap.lDispatch(params) + case "m": + return ap.eventHandler.SGR(getInts(params, 1, 0)) + case "r": + ints := getInts(params, 2, 1) + top, bottom := ints[0], ints[1] + return ap.eventHandler.DECSTBM(top, bottom) + default: + ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context) + return nil + } + +} + +func (ap *AnsiParser) print() error { + return ap.eventHandler.Print(ap.context.currentChar) +} + +func (ap *AnsiParser) clear() error { + ap.context = &ansiContext{} + return nil +} + +func (ap *AnsiParser) execute() error { + return ap.eventHandler.Execute(ap.context.currentChar) +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_test.go b/vendor/github.com/Azure/go-ansiterm/parser_test.go new file mode 100644 index 0000000..cd4888f --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_test.go @@ -0,0 +1,141 @@ +package ansiterm + +import ( + "fmt" + "testing" +) + +func TestStateTransitions(t *testing.T) { + stateTransitionHelper(t, "CsiEntry", "Ground", alphabetics) + stateTransitionHelper(t, "CsiEntry", "CsiParam", csiCollectables) + stateTransitionHelper(t, "Escape", "CsiEntry", []byte{ANSI_ESCAPE_SECONDARY}) + stateTransitionHelper(t, "Escape", "OscString", []byte{0x5D}) + stateTransitionHelper(t, "Escape", "Ground", escapeToGroundBytes) + stateTransitionHelper(t, "Escape", "EscapeIntermediate", intermeds) + stateTransitionHelper(t, "EscapeIntermediate", "EscapeIntermediate", intermeds) + stateTransitionHelper(t, "EscapeIntermediate", "EscapeIntermediate", executors) + stateTransitionHelper(t, "EscapeIntermediate", "Ground", escapeIntermediateToGroundBytes) + stateTransitionHelper(t, "OscString", "Ground", []byte{ANSI_BEL}) + stateTransitionHelper(t, "OscString", "Ground", []byte{0x5C}) + stateTransitionHelper(t, "Ground", "Ground", executors) +} + +func TestAnyToX(t *testing.T) { + anyToXHelper(t, []byte{ANSI_ESCAPE_PRIMARY}, "Escape") + anyToXHelper(t, []byte{DCS_ENTRY}, "DcsEntry") + anyToXHelper(t, []byte{OSC_STRING}, "OscString") + anyToXHelper(t, []byte{CSI_ENTRY}, "CsiEntry") + anyToXHelper(t, toGroundBytes, "Ground") +} + +func TestCollectCsiParams(t *testing.T) { + parser, _ := createTestParser("CsiEntry") + parser.Parse(csiCollectables) + + buffer := parser.context.paramBuffer + bufferCount := len(buffer) + + if bufferCount != len(csiCollectables) { + t.Errorf("Buffer: %v", buffer) + t.Errorf("CsiParams: %v", csiCollectables) + t.Errorf("Buffer count failure: %d != %d", bufferCount, len(csiParams)) + return + } + + for i, v := range csiCollectables { + if v != buffer[i] { + t.Errorf("Buffer: %v", buffer) + t.Errorf("CsiParams: %v", csiParams) + t.Errorf("Mismatch at buffer[%d] = %d", i, buffer[i]) + } + } +} + +func TestParseParams(t *testing.T) { + parseParamsHelper(t, []byte{}, []string{}) + parseParamsHelper(t, []byte{';'}, []string{}) + parseParamsHelper(t, []byte{';', ';'}, []string{}) + parseParamsHelper(t, []byte{'7'}, []string{"7"}) + parseParamsHelper(t, []byte{'7', ';'}, []string{"7"}) + parseParamsHelper(t, []byte{'7', ';', ';'}, []string{"7"}) + parseParamsHelper(t, []byte{'7', ';', ';', '8'}, []string{"7", "8"}) + parseParamsHelper(t, []byte{'7', ';', '8', ';'}, []string{"7", "8"}) + parseParamsHelper(t, []byte{'7', ';', ';', '8', ';', ';'}, []string{"7", "8"}) + parseParamsHelper(t, []byte{'7', '8'}, []string{"78"}) + parseParamsHelper(t, []byte{'7', '8', ';'}, []string{"78"}) + parseParamsHelper(t, []byte{'7', '8', ';', '9', '0'}, []string{"78", "90"}) + parseParamsHelper(t, []byte{'7', '8', ';', ';', '9', '0'}, []string{"78", "90"}) + parseParamsHelper(t, []byte{'7', '8', ';', '9', '0', ';'}, []string{"78", "90"}) + parseParamsHelper(t, []byte{'7', '8', ';', '9', '0', ';', ';'}, []string{"78", "90"}) +} + +func TestCursor(t *testing.T) { + cursorSingleParamHelper(t, 'A', "CUU") + cursorSingleParamHelper(t, 'B', "CUD") + cursorSingleParamHelper(t, 'C', "CUF") + cursorSingleParamHelper(t, 'D', "CUB") + cursorSingleParamHelper(t, 'E', "CNL") + cursorSingleParamHelper(t, 'F', "CPL") + cursorSingleParamHelper(t, 'G', "CHA") + cursorTwoParamHelper(t, 'H', "CUP") + cursorTwoParamHelper(t, 'f', "HVP") + funcCallParamHelper(t, []byte{'?', '2', '5', 'h'}, "CsiEntry", "Ground", []string{"DECTCEM([true])"}) + funcCallParamHelper(t, []byte{'?', '2', '5', 'l'}, "CsiEntry", "Ground", []string{"DECTCEM([false])"}) +} + +func TestErase(t *testing.T) { + // Erase in Display + eraseHelper(t, 'J', "ED") + + // Erase in Line + eraseHelper(t, 'K', "EL") +} + +func TestSelectGraphicRendition(t *testing.T) { + funcCallParamHelper(t, []byte{'m'}, "CsiEntry", "Ground", []string{"SGR([0])"}) + funcCallParamHelper(t, []byte{'0', 'm'}, "CsiEntry", "Ground", []string{"SGR([0])"}) + funcCallParamHelper(t, []byte{'0', ';', '1', 'm'}, "CsiEntry", "Ground", []string{"SGR([0 1])"}) + funcCallParamHelper(t, []byte{'0', ';', '1', ';', '2', 'm'}, "CsiEntry", "Ground", []string{"SGR([0 1 2])"}) +} + +func TestScroll(t *testing.T) { + scrollHelper(t, 'S', "SU") + scrollHelper(t, 'T', "SD") +} + +func TestPrint(t *testing.T) { + parser, evtHandler := createTestParser("Ground") + parser.Parse(printables) + validateState(t, parser.currState, "Ground") + + for i, v := range printables { + expectedCall := fmt.Sprintf("Print([%s])", string(v)) + actualCall := evtHandler.FunctionCalls[i] + if actualCall != expectedCall { + t.Errorf("Actual != Expected: %v != %v at %d", actualCall, expectedCall, i) + } + } +} + +func TestClear(t *testing.T) { + p, _ := createTestParser("Ground") + fillContext(p.context) + p.clear() + validateEmptyContext(t, p.context) +} + +func TestClearOnStateChange(t *testing.T) { + clearOnStateChangeHelper(t, "Ground", "Escape", []byte{ANSI_ESCAPE_PRIMARY}) + clearOnStateChangeHelper(t, "Ground", "CsiEntry", []byte{CSI_ENTRY}) +} + +func TestC0(t *testing.T) { + expectedCall := "Execute([" + string(ANSI_LINE_FEED) + "])" + c0Helper(t, []byte{ANSI_LINE_FEED}, "Ground", []string{expectedCall}) + expectedCall = "Execute([" + string(ANSI_CARRIAGE_RETURN) + "])" + c0Helper(t, []byte{ANSI_CARRIAGE_RETURN}, "Ground", []string{expectedCall}) +} + +func TestEscDispatch(t *testing.T) { + funcCallParamHelper(t, []byte{'M'}, "Escape", "Ground", []string{"RI([])"}) +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_test_helpers_test.go b/vendor/github.com/Azure/go-ansiterm/parser_test_helpers_test.go new file mode 100644 index 0000000..562f215 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_test_helpers_test.go @@ -0,0 +1,114 @@ +package ansiterm + +import ( + "fmt" + "testing" +) + +func getStateNames() []string { + parser, _ := createTestParser("Ground") + + stateNames := []string{} + for _, state := range parser.stateMap { + stateNames = append(stateNames, state.Name()) + } + + return stateNames +} + +func stateTransitionHelper(t *testing.T, start string, end string, bytes []byte) { + for _, b := range bytes { + bytes := []byte{byte(b)} + parser, _ := createTestParser(start) + parser.Parse(bytes) + validateState(t, parser.currState, end) + } +} + +func anyToXHelper(t *testing.T, bytes []byte, expectedState string) { + for _, s := range getStateNames() { + stateTransitionHelper(t, s, expectedState, bytes) + } +} + +func funcCallParamHelper(t *testing.T, bytes []byte, start string, expected string, expectedCalls []string) { + parser, evtHandler := createTestParser(start) + parser.Parse(bytes) + validateState(t, parser.currState, expected) + validateFuncCalls(t, evtHandler.FunctionCalls, expectedCalls) +} + +func parseParamsHelper(t *testing.T, bytes []byte, expectedParams []string) { + params, err := parseParams(bytes) + + if err != nil { + t.Errorf("Parameter parse error: %v", err) + return + } + + if len(params) != len(expectedParams) { + t.Errorf("Parsed parameters: %v", params) + t.Errorf("Expected parameters: %v", expectedParams) + t.Errorf("Parameter length failure: %d != %d", len(params), len(expectedParams)) + return + } + + for i, v := range expectedParams { + if v != params[i] { + t.Errorf("Parsed parameters: %v", params) + t.Errorf("Expected parameters: %v", expectedParams) + t.Errorf("Parameter parse failure: %s != %s at position %d", v, params[i], i) + } + } +} + +func cursorSingleParamHelper(t *testing.T, command byte, funcName string) { + funcCallParamHelper(t, []byte{command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1])", funcName)}) + funcCallParamHelper(t, []byte{'0', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1])", funcName)}) + funcCallParamHelper(t, []byte{'2', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([2])", funcName)}) + funcCallParamHelper(t, []byte{'2', '3', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([23])", funcName)}) + funcCallParamHelper(t, []byte{'2', ';', '3', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([2])", funcName)}) + funcCallParamHelper(t, []byte{'2', ';', '3', ';', '4', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([2])", funcName)}) +} + +func cursorTwoParamHelper(t *testing.T, command byte, funcName string) { + funcCallParamHelper(t, []byte{command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1 1])", funcName)}) + funcCallParamHelper(t, []byte{'0', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1 1])", funcName)}) + funcCallParamHelper(t, []byte{'2', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([2 1])", funcName)}) + funcCallParamHelper(t, []byte{'2', '3', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([23 1])", funcName)}) + funcCallParamHelper(t, []byte{'2', ';', '3', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([2 3])", funcName)}) + funcCallParamHelper(t, []byte{'2', ';', '3', ';', '4', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([2 3])", funcName)}) +} + +func eraseHelper(t *testing.T, command byte, funcName string) { + funcCallParamHelper(t, []byte{command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([0])", funcName)}) + funcCallParamHelper(t, []byte{'0', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([0])", funcName)}) + funcCallParamHelper(t, []byte{'1', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1])", funcName)}) + funcCallParamHelper(t, []byte{'2', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([2])", funcName)}) + funcCallParamHelper(t, []byte{'3', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([3])", funcName)}) + funcCallParamHelper(t, []byte{'4', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([0])", funcName)}) + funcCallParamHelper(t, []byte{'1', ';', '2', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1])", funcName)}) +} + +func scrollHelper(t *testing.T, command byte, funcName string) { + funcCallParamHelper(t, []byte{command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1])", funcName)}) + funcCallParamHelper(t, []byte{'0', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1])", funcName)}) + funcCallParamHelper(t, []byte{'1', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([1])", funcName)}) + funcCallParamHelper(t, []byte{'5', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([5])", funcName)}) + funcCallParamHelper(t, []byte{'4', ';', '6', command}, "CsiEntry", "Ground", []string{fmt.Sprintf("%s([4])", funcName)}) +} + +func clearOnStateChangeHelper(t *testing.T, start string, end string, bytes []byte) { + p, _ := createTestParser(start) + fillContext(p.context) + p.Parse(bytes) + validateState(t, p.currState, end) + validateEmptyContext(t, p.context) +} + +func c0Helper(t *testing.T, bytes []byte, expectedState string, expectedCalls []string) { + parser, evtHandler := createTestParser("Ground") + parser.Parse(bytes) + validateState(t, parser.currState, expectedState) + validateFuncCalls(t, evtHandler.FunctionCalls, expectedCalls) +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_test_utilities_test.go b/vendor/github.com/Azure/go-ansiterm/parser_test_utilities_test.go new file mode 100644 index 0000000..78b885c --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_test_utilities_test.go @@ -0,0 +1,66 @@ +package ansiterm + +import ( + "testing" +) + +func createTestParser(s string) (*AnsiParser, *TestAnsiEventHandler) { + evtHandler := CreateTestAnsiEventHandler() + parser := CreateParser(s, evtHandler) + + return parser, evtHandler +} + +func validateState(t *testing.T, actualState state, expectedStateName string) { + actualName := "Nil" + + if actualState != nil { + actualName = actualState.Name() + } + + if actualName != expectedStateName { + t.Errorf("Invalid state: '%s' != '%s'", actualName, expectedStateName) + } +} + +func validateFuncCalls(t *testing.T, actualCalls []string, expectedCalls []string) { + actualCount := len(actualCalls) + expectedCount := len(expectedCalls) + + if actualCount != expectedCount { + t.Errorf("Actual calls: %v", actualCalls) + t.Errorf("Expected calls: %v", expectedCalls) + t.Errorf("Call count error: %d != %d", actualCount, expectedCount) + return + } + + for i, v := range actualCalls { + if v != expectedCalls[i] { + t.Errorf("Actual calls: %v", actualCalls) + t.Errorf("Expected calls: %v", expectedCalls) + t.Errorf("Mismatched calls: %s != %s with lengths %d and %d", v, expectedCalls[i], len(v), len(expectedCalls[i])) + } + } +} + +func fillContext(context *ansiContext) { + context.currentChar = 'A' + context.paramBuffer = []byte{'C', 'D', 'E'} + context.interBuffer = []byte{'F', 'G', 'H'} +} + +func validateEmptyContext(t *testing.T, context *ansiContext) { + var expectedCurrChar byte = 0x0 + if context.currentChar != expectedCurrChar { + t.Errorf("Currentchar mismatch '%#x' != '%#x'", context.currentChar, expectedCurrChar) + } + + if len(context.paramBuffer) != 0 { + t.Errorf("Non-empty parameter buffer: %v", context.paramBuffer) + } + + if len(context.paramBuffer) != 0 { + t.Errorf("Non-empty intermediate buffer: %v", context.interBuffer) + } + +} diff --git a/vendor/github.com/Azure/go-ansiterm/states.go b/vendor/github.com/Azure/go-ansiterm/states.go new file mode 100644 index 0000000..f2ea1fc --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/states.go @@ -0,0 +1,71 @@ +package ansiterm + +type stateID int + +type state interface { + Enter() error + Exit() error + Handle(byte) (state, error) + Name() string + Transition(state) error +} + +type baseState struct { + name string + parser *AnsiParser +} + +func (base baseState) Enter() error { + return nil +} + +func (base baseState) Exit() error { + return nil +} + +func (base baseState) Handle(b byte) (s state, e error) { + + switch { + case b == CSI_ENTRY: + return base.parser.csiEntry, nil + case b == DCS_ENTRY: + return base.parser.dcsEntry, nil + case b == ANSI_ESCAPE_PRIMARY: + return base.parser.escape, nil + case b == OSC_STRING: + return base.parser.oscString, nil + case sliceContains(toGroundBytes, b): + return base.parser.ground, nil + } + + return nil, nil +} + +func (base baseState) Name() string { + return base.name +} + +func (base baseState) Transition(s state) error { + if s == base.parser.ground { + execBytes := []byte{0x18} + execBytes = append(execBytes, 0x1A) + execBytes = append(execBytes, getByteRange(0x80, 0x8F)...) + execBytes = append(execBytes, getByteRange(0x91, 0x97)...) + execBytes = append(execBytes, 0x99) + execBytes = append(execBytes, 0x9A) + + if sliceContains(execBytes, base.parser.context.currentChar) { + return base.parser.execute() + } + } + + return nil +} + +type dcsEntryState struct { + baseState +} + +type errorState struct { + baseState +} diff --git a/vendor/github.com/Azure/go-ansiterm/test_event_handler_test.go b/vendor/github.com/Azure/go-ansiterm/test_event_handler_test.go new file mode 100644 index 0000000..60f9f30 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/test_event_handler_test.go @@ -0,0 +1,173 @@ +package ansiterm + +import ( + "fmt" + "strconv" +) + +type TestAnsiEventHandler struct { + FunctionCalls []string +} + +func CreateTestAnsiEventHandler() *TestAnsiEventHandler { + evtHandler := TestAnsiEventHandler{} + evtHandler.FunctionCalls = make([]string, 0) + return &evtHandler +} + +func (h *TestAnsiEventHandler) recordCall(call string, params []string) { + s := fmt.Sprintf("%s(%v)", call, params) + h.FunctionCalls = append(h.FunctionCalls, s) +} + +func (h *TestAnsiEventHandler) Print(b byte) error { + h.recordCall("Print", []string{string(b)}) + return nil +} + +func (h *TestAnsiEventHandler) Execute(b byte) error { + h.recordCall("Execute", []string{string(b)}) + return nil +} + +func (h *TestAnsiEventHandler) CUU(param int) error { + h.recordCall("CUU", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) CUD(param int) error { + h.recordCall("CUD", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) CUF(param int) error { + h.recordCall("CUF", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) CUB(param int) error { + h.recordCall("CUB", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) CNL(param int) error { + h.recordCall("CNL", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) CPL(param int) error { + h.recordCall("CPL", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) CHA(param int) error { + h.recordCall("CHA", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) VPA(param int) error { + h.recordCall("VPA", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) CUP(x int, y int) error { + xS, yS := strconv.Itoa(x), strconv.Itoa(y) + h.recordCall("CUP", []string{xS, yS}) + return nil +} + +func (h *TestAnsiEventHandler) HVP(x int, y int) error { + xS, yS := strconv.Itoa(x), strconv.Itoa(y) + h.recordCall("HVP", []string{xS, yS}) + return nil +} + +func (h *TestAnsiEventHandler) DECTCEM(visible bool) error { + h.recordCall("DECTCEM", []string{strconv.FormatBool(visible)}) + return nil +} + +func (h *TestAnsiEventHandler) DECOM(visible bool) error { + h.recordCall("DECOM", []string{strconv.FormatBool(visible)}) + return nil +} + +func (h *TestAnsiEventHandler) DECCOLM(use132 bool) error { + h.recordCall("DECOLM", []string{strconv.FormatBool(use132)}) + return nil +} + +func (h *TestAnsiEventHandler) ED(param int) error { + h.recordCall("ED", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) EL(param int) error { + h.recordCall("EL", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) IL(param int) error { + h.recordCall("IL", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) DL(param int) error { + h.recordCall("DL", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) ICH(param int) error { + h.recordCall("ICH", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) DCH(param int) error { + h.recordCall("DCH", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) SGR(params []int) error { + strings := []string{} + for _, v := range params { + strings = append(strings, strconv.Itoa(v)) + } + + h.recordCall("SGR", strings) + return nil +} + +func (h *TestAnsiEventHandler) SU(param int) error { + h.recordCall("SU", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) SD(param int) error { + h.recordCall("SD", []string{strconv.Itoa(param)}) + return nil +} + +func (h *TestAnsiEventHandler) DA(params []string) error { + h.recordCall("DA", params) + return nil +} + +func (h *TestAnsiEventHandler) DECSTBM(top int, bottom int) error { + topS, bottomS := strconv.Itoa(top), strconv.Itoa(bottom) + h.recordCall("DECSTBM", []string{topS, bottomS}) + return nil +} + +func (h *TestAnsiEventHandler) RI() error { + h.recordCall("RI", nil) + return nil +} + +func (h *TestAnsiEventHandler) IND() error { + h.recordCall("IND", nil) + return nil +} + +func (h *TestAnsiEventHandler) Flush() error { + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/utilities.go new file mode 100644 index 0000000..3921144 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/utilities.go @@ -0,0 +1,21 @@ +package ansiterm + +import ( + "strconv" +) + +func sliceContains(bytes []byte, b byte) bool { + for _, v := range bytes { + if v == b { + return true + } + } + + return false +} + +func convertBytesToInteger(bytes []byte) int { + s := string(bytes) + i, _ := strconv.Atoi(s) + return i +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go new file mode 100644 index 0000000..a673279 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go @@ -0,0 +1,182 @@ +// +build windows + +package winterm + +import ( + "fmt" + "os" + "strconv" + "strings" + "syscall" + + "github.com/Azure/go-ansiterm" +) + +// Windows keyboard constants +// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx. +const ( + VK_PRIOR = 0x21 // PAGE UP key + VK_NEXT = 0x22 // PAGE DOWN key + VK_END = 0x23 // END key + VK_HOME = 0x24 // HOME key + VK_LEFT = 0x25 // LEFT ARROW key + VK_UP = 0x26 // UP ARROW key + VK_RIGHT = 0x27 // RIGHT ARROW key + VK_DOWN = 0x28 // DOWN ARROW key + VK_SELECT = 0x29 // SELECT key + VK_PRINT = 0x2A // PRINT key + VK_EXECUTE = 0x2B // EXECUTE key + VK_SNAPSHOT = 0x2C // PRINT SCREEN key + VK_INSERT = 0x2D // INS key + VK_DELETE = 0x2E // DEL key + VK_HELP = 0x2F // HELP key + VK_F1 = 0x70 // F1 key + VK_F2 = 0x71 // F2 key + VK_F3 = 0x72 // F3 key + VK_F4 = 0x73 // F4 key + VK_F5 = 0x74 // F5 key + VK_F6 = 0x75 // F6 key + VK_F7 = 0x76 // F7 key + VK_F8 = 0x77 // F8 key + VK_F9 = 0x78 // F9 key + VK_F10 = 0x79 // F10 key + VK_F11 = 0x7A // F11 key + VK_F12 = 0x7B // F12 key + + RIGHT_ALT_PRESSED = 0x0001 + LEFT_ALT_PRESSED = 0x0002 + RIGHT_CTRL_PRESSED = 0x0004 + LEFT_CTRL_PRESSED = 0x0008 + SHIFT_PRESSED = 0x0010 + NUMLOCK_ON = 0x0020 + SCROLLLOCK_ON = 0x0040 + CAPSLOCK_ON = 0x0080 + ENHANCED_KEY = 0x0100 +) + +type ansiCommand struct { + CommandBytes []byte + Command string + Parameters []string + IsSpecial bool +} + +func newAnsiCommand(command []byte) *ansiCommand { + + if isCharacterSelectionCmdChar(command[1]) { + // Is Character Set Selection commands + return &ansiCommand{ + CommandBytes: command, + Command: string(command), + IsSpecial: true, + } + } + + // last char is command character + lastCharIndex := len(command) - 1 + + ac := &ansiCommand{ + CommandBytes: command, + Command: string(command[lastCharIndex]), + IsSpecial: false, + } + + // more than a single escape + if lastCharIndex != 0 { + start := 1 + // skip if double char escape sequence + if command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_ESCAPE_SECONDARY { + start++ + } + // convert this to GetNextParam method + ac.Parameters = strings.Split(string(command[start:lastCharIndex]), ansiterm.ANSI_PARAMETER_SEP) + } + + return ac +} + +func (ac *ansiCommand) paramAsSHORT(index int, defaultValue int16) int16 { + if index < 0 || index >= len(ac.Parameters) { + return defaultValue + } + + param, err := strconv.ParseInt(ac.Parameters[index], 10, 16) + if err != nil { + return defaultValue + } + + return int16(param) +} + +func (ac *ansiCommand) String() string { + return fmt.Sprintf("0x%v \"%v\" (\"%v\")", + bytesToHex(ac.CommandBytes), + ac.Command, + strings.Join(ac.Parameters, "\",\"")) +} + +// isAnsiCommandChar returns true if the passed byte falls within the range of ANSI commands. +// See http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html. +func isAnsiCommandChar(b byte) bool { + switch { + case ansiterm.ANSI_COMMAND_FIRST <= b && b <= ansiterm.ANSI_COMMAND_LAST && b != ansiterm.ANSI_ESCAPE_SECONDARY: + return true + case b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_OSC || b == ansiterm.ANSI_CMD_DECPAM || b == ansiterm.ANSI_CMD_DECPNM: + // non-CSI escape sequence terminator + return true + case b == ansiterm.ANSI_CMD_STR_TERM || b == ansiterm.ANSI_BEL: + // String escape sequence terminator + return true + } + return false +} + +func isXtermOscSequence(command []byte, current byte) bool { + return (len(command) >= 2 && command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_CMD_OSC && current != ansiterm.ANSI_BEL) +} + +func isCharacterSelectionCmdChar(b byte) bool { + return (b == ansiterm.ANSI_CMD_G0 || b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_G2 || b == ansiterm.ANSI_CMD_G3) +} + +// bytesToHex converts a slice of bytes to a human-readable string. +func bytesToHex(b []byte) string { + hex := make([]string, len(b)) + for i, ch := range b { + hex[i] = fmt.Sprintf("%X", ch) + } + return strings.Join(hex, "") +} + +// ensureInRange adjusts the passed value, if necessary, to ensure it is within +// the passed min / max range. +func ensureInRange(n int16, min int16, max int16) int16 { + if n < min { + return min + } else if n > max { + return max + } else { + return n + } +} + +func GetStdFile(nFile int) (*os.File, uintptr) { + var file *os.File + switch nFile { + case syscall.STD_INPUT_HANDLE: + file = os.Stdin + case syscall.STD_OUTPUT_HANDLE: + file = os.Stdout + case syscall.STD_ERROR_HANDLE: + file = os.Stderr + default: + panic(fmt.Errorf("Invalid standard handle identifier: %v", nFile)) + } + + fd, err := syscall.GetStdHandle(nFile) + if err != nil { + panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err)) + } + + return file, uintptr(fd) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/api.go b/vendor/github.com/Azure/go-ansiterm/winterm/api.go new file mode 100644 index 0000000..6055e33 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/api.go @@ -0,0 +1,327 @@ +// +build windows + +package winterm + +import ( + "fmt" + "syscall" + "unsafe" +) + +//=========================================================================================================== +// IMPORTANT NOTE: +// +// The methods below make extensive use of the "unsafe" package to obtain the required pointers. +// Beginning in Go 1.3, the garbage collector may release local variables (e.g., incoming arguments, stack +// variables) the pointers reference *before* the API completes. +// +// As a result, in those cases, the code must hint that the variables remain in active by invoking the +// dummy method "use" (see below). Newer versions of Go are planned to change the mechanism to no longer +// require unsafe pointers. +// +// If you add or modify methods, ENSURE protection of local variables through the "use" builtin to inform +// the garbage collector the variables remain in use if: +// +// -- The value is not a pointer (e.g., int32, struct) +// -- The value is not referenced by the method after passing the pointer to Windows +// +// See http://golang.org/doc/go1.3. +//=========================================================================================================== + +var ( + kernel32DLL = syscall.NewLazyDLL("kernel32.dll") + + getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo") + setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo") + setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition") + setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode") + getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo") + setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize") + scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA") + setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute") + setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo") + writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW") + readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW") + waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject") +) + +// Windows Console constants +const ( + // Console modes + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. + ENABLE_PROCESSED_INPUT = 0x0001 + ENABLE_LINE_INPUT = 0x0002 + ENABLE_ECHO_INPUT = 0x0004 + ENABLE_WINDOW_INPUT = 0x0008 + ENABLE_MOUSE_INPUT = 0x0010 + ENABLE_INSERT_MODE = 0x0020 + ENABLE_QUICK_EDIT_MODE = 0x0040 + ENABLE_EXTENDED_FLAGS = 0x0080 + ENABLE_AUTO_POSITION = 0x0100 + ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200 + + ENABLE_PROCESSED_OUTPUT = 0x0001 + ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 + DISABLE_NEWLINE_AUTO_RETURN = 0x0008 + ENABLE_LVB_GRID_WORLDWIDE = 0x0010 + + // Character attributes + // Note: + // -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan). + // Clearing all foreground or background colors results in black; setting all creates white. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes. + FOREGROUND_BLUE uint16 = 0x0001 + FOREGROUND_GREEN uint16 = 0x0002 + FOREGROUND_RED uint16 = 0x0004 + FOREGROUND_INTENSITY uint16 = 0x0008 + FOREGROUND_MASK uint16 = 0x000F + + BACKGROUND_BLUE uint16 = 0x0010 + BACKGROUND_GREEN uint16 = 0x0020 + BACKGROUND_RED uint16 = 0x0040 + BACKGROUND_INTENSITY uint16 = 0x0080 + BACKGROUND_MASK uint16 = 0x00F0 + + COMMON_LVB_MASK uint16 = 0xFF00 + COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000 + COMMON_LVB_UNDERSCORE uint16 = 0x8000 + + // Input event types + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. + KEY_EVENT = 0x0001 + MOUSE_EVENT = 0x0002 + WINDOW_BUFFER_SIZE_EVENT = 0x0004 + MENU_EVENT = 0x0008 + FOCUS_EVENT = 0x0010 + + // WaitForSingleObject return codes + WAIT_ABANDONED = 0x00000080 + WAIT_FAILED = 0xFFFFFFFF + WAIT_SIGNALED = 0x0000000 + WAIT_TIMEOUT = 0x00000102 + + // WaitForSingleObject wait duration + WAIT_INFINITE = 0xFFFFFFFF + WAIT_ONE_SECOND = 1000 + WAIT_HALF_SECOND = 500 + WAIT_QUARTER_SECOND = 250 +) + +// Windows API Console types +// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682101(v=vs.85).aspx for Console specific types (e.g., COORD) +// -- See https://msdn.microsoft.com/en-us/library/aa296569(v=vs.60).aspx for comments on alignment +type ( + CHAR_INFO struct { + UnicodeChar uint16 + Attributes uint16 + } + + CONSOLE_CURSOR_INFO struct { + Size uint32 + Visible int32 + } + + CONSOLE_SCREEN_BUFFER_INFO struct { + Size COORD + CursorPosition COORD + Attributes uint16 + Window SMALL_RECT + MaximumWindowSize COORD + } + + COORD struct { + X int16 + Y int16 + } + + SMALL_RECT struct { + Left int16 + Top int16 + Right int16 + Bottom int16 + } + + // INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. + INPUT_RECORD struct { + EventType uint16 + KeyEvent KEY_EVENT_RECORD + } + + KEY_EVENT_RECORD struct { + KeyDown int32 + RepeatCount uint16 + VirtualKeyCode uint16 + VirtualScanCode uint16 + UnicodeChar uint16 + ControlKeyState uint32 + } + + WINDOW_BUFFER_SIZE struct { + Size COORD + } +) + +// boolToBOOL converts a Go bool into a Windows int32. +func boolToBOOL(f bool) int32 { + if f { + return int32(1) + } else { + return int32(0) + } +} + +// GetConsoleCursorInfo retrieves information about the size and visiblity of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683163(v=vs.85).aspx. +func GetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { + r1, r2, err := getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) + return checkError(r1, r2, err) +} + +// SetConsoleCursorInfo sets the size and visiblity of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx. +func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { + r1, r2, err := setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) + return checkError(r1, r2, err) +} + +// SetConsoleCursorPosition location of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx. +func SetConsoleCursorPosition(handle uintptr, coord COORD) error { + r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord)) + use(coord) + return checkError(r1, r2, err) +} + +// GetConsoleMode gets the console mode for given file descriptor +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx. +func GetConsoleMode(handle uintptr) (mode uint32, err error) { + err = syscall.GetConsoleMode(syscall.Handle(handle), &mode) + return mode, err +} + +// SetConsoleMode sets the console mode for given file descriptor +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. +func SetConsoleMode(handle uintptr, mode uint32) error { + r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0) + use(mode) + return checkError(r1, r2, err) +} + +// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer. +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx. +func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) { + info := CONSOLE_SCREEN_BUFFER_INFO{} + err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)) + if err != nil { + return nil, err + } + return &info, nil +} + +func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error { + r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char))) + use(scrollRect) + use(clipRect) + use(destOrigin) + use(char) + return checkError(r1, r2, err) +} + +// SetConsoleScreenBufferSize sets the size of the console screen buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx. +func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error { + r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord)) + use(coord) + return checkError(r1, r2, err) +} + +// SetConsoleTextAttribute sets the attributes of characters written to the +// console screen buffer by the WriteFile or WriteConsole function. +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx. +func SetConsoleTextAttribute(handle uintptr, attribute uint16) error { + r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0) + use(attribute) + return checkError(r1, r2, err) +} + +// SetConsoleWindowInfo sets the size and position of the console screen buffer's window. +// Note that the size and location must be within and no larger than the backing console screen buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx. +func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error { + r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect))) + use(isAbsolute) + use(rect) + return checkError(r1, r2, err) +} + +// WriteConsoleOutput writes the CHAR_INFOs from the provided buffer to the active console buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx. +func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error { + r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion))) + use(buffer) + use(bufferSize) + use(bufferCoord) + return checkError(r1, r2, err) +} + +// ReadConsoleInput reads (and removes) data from the console input buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx. +func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error { + r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count))) + use(buffer) + return checkError(r1, r2, err) +} + +// WaitForSingleObject waits for the passed handle to be signaled. +// It returns true if the handle was signaled; false otherwise. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx. +func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) { + r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait))) + switch r1 { + case WAIT_ABANDONED, WAIT_TIMEOUT: + return false, nil + case WAIT_SIGNALED: + return true, nil + } + use(msWait) + return false, err +} + +// String helpers +func (info CONSOLE_SCREEN_BUFFER_INFO) String() string { + return fmt.Sprintf("Size(%v) Cursor(%v) Window(%v) Max(%v)", info.Size, info.CursorPosition, info.Window, info.MaximumWindowSize) +} + +func (coord COORD) String() string { + return fmt.Sprintf("%v,%v", coord.X, coord.Y) +} + +func (rect SMALL_RECT) String() string { + return fmt.Sprintf("(%v,%v),(%v,%v)", rect.Left, rect.Top, rect.Right, rect.Bottom) +} + +// checkError evaluates the results of a Windows API call and returns the error if it failed. +func checkError(r1, r2 uintptr, err error) error { + // Windows APIs return non-zero to indicate success + if r1 != 0 { + return nil + } + + // Return the error if provided, otherwise default to EINVAL + if err != nil { + return err + } + return syscall.EINVAL +} + +// coordToPointer converts a COORD into a uintptr (by fooling the type system). +func coordToPointer(c COORD) uintptr { + // Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass. + return uintptr(*((*uint32)(unsafe.Pointer(&c)))) +} + +// use is a no-op, but the compiler cannot see that it is. +// Calling use(p) ensures that p is kept live until that point. +func use(p interface{}) {} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go b/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go new file mode 100644 index 0000000..cbec8f7 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go @@ -0,0 +1,100 @@ +// +build windows + +package winterm + +import "github.com/Azure/go-ansiterm" + +const ( + FOREGROUND_COLOR_MASK = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE + BACKGROUND_COLOR_MASK = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE +) + +// collectAnsiIntoWindowsAttributes modifies the passed Windows text mode flags to reflect the +// request represented by the passed ANSI mode. +func collectAnsiIntoWindowsAttributes(windowsMode uint16, inverted bool, baseMode uint16, ansiMode int16) (uint16, bool) { + switch ansiMode { + + // Mode styles + case ansiterm.ANSI_SGR_BOLD: + windowsMode = windowsMode | FOREGROUND_INTENSITY + + case ansiterm.ANSI_SGR_DIM, ansiterm.ANSI_SGR_BOLD_DIM_OFF: + windowsMode &^= FOREGROUND_INTENSITY + + case ansiterm.ANSI_SGR_UNDERLINE: + windowsMode = windowsMode | COMMON_LVB_UNDERSCORE + + case ansiterm.ANSI_SGR_REVERSE: + inverted = true + + case ansiterm.ANSI_SGR_REVERSE_OFF: + inverted = false + + case ansiterm.ANSI_SGR_UNDERLINE_OFF: + windowsMode &^= COMMON_LVB_UNDERSCORE + + // Foreground colors + case ansiterm.ANSI_SGR_FOREGROUND_DEFAULT: + windowsMode = (windowsMode &^ FOREGROUND_MASK) | (baseMode & FOREGROUND_MASK) + + case ansiterm.ANSI_SGR_FOREGROUND_BLACK: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) + + case ansiterm.ANSI_SGR_FOREGROUND_RED: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED + + case ansiterm.ANSI_SGR_FOREGROUND_GREEN: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN + + case ansiterm.ANSI_SGR_FOREGROUND_YELLOW: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN + + case ansiterm.ANSI_SGR_FOREGROUND_BLUE: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_MAGENTA: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_CYAN: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_WHITE: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE + + // Background colors + case ansiterm.ANSI_SGR_BACKGROUND_DEFAULT: + // Black with no intensity + windowsMode = (windowsMode &^ BACKGROUND_MASK) | (baseMode & BACKGROUND_MASK) + + case ansiterm.ANSI_SGR_BACKGROUND_BLACK: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) + + case ansiterm.ANSI_SGR_BACKGROUND_RED: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED + + case ansiterm.ANSI_SGR_BACKGROUND_GREEN: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN + + case ansiterm.ANSI_SGR_BACKGROUND_YELLOW: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN + + case ansiterm.ANSI_SGR_BACKGROUND_BLUE: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_MAGENTA: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_CYAN: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_WHITE: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE + } + + return windowsMode, inverted +} + +// invertAttributes inverts the foreground and background colors of a Windows attributes value +func invertAttributes(windowsMode uint16) uint16 { + return (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go new file mode 100644 index 0000000..3ee06ea --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go @@ -0,0 +1,101 @@ +// +build windows + +package winterm + +const ( + horizontal = iota + vertical +) + +func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT { + if h.originMode { + sr := h.effectiveSr(info.Window) + return SMALL_RECT{ + Top: sr.top, + Bottom: sr.bottom, + Left: 0, + Right: info.Size.X - 1, + } + } else { + return SMALL_RECT{ + Top: info.Window.Top, + Bottom: info.Window.Bottom, + Left: 0, + Right: info.Size.X - 1, + } + } +} + +// setCursorPosition sets the cursor to the specified position, bounded to the screen size +func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL_RECT) error { + position.X = ensureInRange(position.X, window.Left, window.Right) + position.Y = ensureInRange(position.Y, window.Top, window.Bottom) + err := SetConsoleCursorPosition(h.fd, position) + if err != nil { + return err + } + h.logf("Cursor position set: (%d, %d)", position.X, position.Y) + return err +} + +func (h *windowsAnsiEventHandler) moveCursorVertical(param int) error { + return h.moveCursor(vertical, param) +} + +func (h *windowsAnsiEventHandler) moveCursorHorizontal(param int) error { + return h.moveCursor(horizontal, param) +} + +func (h *windowsAnsiEventHandler) moveCursor(moveMode int, param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + switch moveMode { + case horizontal: + position.X += int16(param) + case vertical: + position.Y += int16(param) + } + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) moveCursorLine(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + position.X = 0 + position.Y += int16(param) + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + position.X = int16(param) - 1 + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go new file mode 100644 index 0000000..244b5fa --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go @@ -0,0 +1,84 @@ +// +build windows + +package winterm + +import "github.com/Azure/go-ansiterm" + +func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD, toCoord COORD) error { + // Ignore an invalid (negative area) request + if toCoord.Y < fromCoord.Y { + return nil + } + + var err error + + var coordStart = COORD{} + var coordEnd = COORD{} + + xCurrent, yCurrent := fromCoord.X, fromCoord.Y + xEnd, yEnd := toCoord.X, toCoord.Y + + // Clear any partial initial line + if xCurrent > 0 { + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yCurrent + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + xCurrent = 0 + yCurrent += 1 + } + + // Clear intervening rectangular section + if yCurrent < yEnd { + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yEnd-1 + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + xCurrent = 0 + yCurrent = yEnd + } + + // Clear remaining partial ending line + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yEnd + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error { + region := SMALL_RECT{Top: fromCoord.Y, Left: fromCoord.X, Bottom: toCoord.Y, Right: toCoord.X} + width := toCoord.X - fromCoord.X + 1 + height := toCoord.Y - fromCoord.Y + 1 + size := uint32(width) * uint32(height) + + if size <= 0 { + return nil + } + + buffer := make([]CHAR_INFO, size) + + char := CHAR_INFO{ansiterm.FILL_CHARACTER, attributes} + for i := 0; i < int(size); i++ { + buffer[i] = char + } + + err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, ®ion) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go new file mode 100644 index 0000000..2d27fa1 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go @@ -0,0 +1,118 @@ +// +build windows + +package winterm + +// effectiveSr gets the current effective scroll region in buffer coordinates +func (h *windowsAnsiEventHandler) effectiveSr(window SMALL_RECT) scrollRegion { + top := addInRange(window.Top, h.sr.top, window.Top, window.Bottom) + bottom := addInRange(window.Top, h.sr.bottom, window.Top, window.Bottom) + if top >= bottom { + top = window.Top + bottom = window.Bottom + } + return scrollRegion{top: top, bottom: bottom} +} + +func (h *windowsAnsiEventHandler) scrollUp(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + sr := h.effectiveSr(info.Window) + return h.scroll(param, sr, info) +} + +func (h *windowsAnsiEventHandler) scrollDown(param int) error { + return h.scrollUp(-param) +} + +func (h *windowsAnsiEventHandler) deleteLines(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + start := info.CursorPosition.Y + sr := h.effectiveSr(info.Window) + // Lines cannot be inserted or deleted outside the scrolling region. + if start >= sr.top && start <= sr.bottom { + sr.top = start + return h.scroll(param, sr, info) + } else { + return nil + } +} + +func (h *windowsAnsiEventHandler) insertLines(param int) error { + return h.deleteLines(-param) +} + +// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates. +func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error { + h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom) + h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom) + + // Copy from and clip to the scroll region (full buffer width) + scrollRect := SMALL_RECT{ + Top: sr.top, + Bottom: sr.bottom, + Left: 0, + Right: info.Size.X - 1, + } + + // Origin to which area should be copied + destOrigin := COORD{ + X: 0, + Y: sr.top - int16(param), + } + + char := CHAR_INFO{ + UnicodeChar: ' ', + Attributes: h.attributes, + } + + if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { + return err + } + return nil +} + +func (h *windowsAnsiEventHandler) deleteCharacters(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + return h.scrollLine(param, info.CursorPosition, info) +} + +func (h *windowsAnsiEventHandler) insertCharacters(param int) error { + return h.deleteCharacters(-param) +} + +// scrollLine scrolls a line horizontally starting at the provided position by a number of columns. +func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *CONSOLE_SCREEN_BUFFER_INFO) error { + // Copy from and clip to the scroll region (full buffer width) + scrollRect := SMALL_RECT{ + Top: position.Y, + Bottom: position.Y, + Left: position.X, + Right: info.Size.X - 1, + } + + // Origin to which area should be copied + destOrigin := COORD{ + X: position.X - int16(columns), + Y: position.Y, + } + + char := CHAR_INFO{ + UnicodeChar: ' ', + Attributes: h.attributes, + } + + if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go new file mode 100644 index 0000000..afa7635 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go @@ -0,0 +1,9 @@ +// +build windows + +package winterm + +// AddInRange increments a value by the passed quantity while ensuring the values +// always remain within the supplied min / max range. +func addInRange(n int16, increment int16, min int16, max int16) int16 { + return ensureInRange(n+increment, min, max) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go new file mode 100644 index 0000000..2d40fb7 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go @@ -0,0 +1,743 @@ +// +build windows + +package winterm + +import ( + "bytes" + "log" + "os" + "strconv" + + "github.com/Azure/go-ansiterm" +) + +type windowsAnsiEventHandler struct { + fd uintptr + file *os.File + infoReset *CONSOLE_SCREEN_BUFFER_INFO + sr scrollRegion + buffer bytes.Buffer + attributes uint16 + inverted bool + wrapNext bool + drewMarginByte bool + originMode bool + marginByte byte + curInfo *CONSOLE_SCREEN_BUFFER_INFO + curPos COORD + logf func(string, ...interface{}) +} + +type Option func(*windowsAnsiEventHandler) + +func WithLogf(f func(string, ...interface{})) Option { + return func(w *windowsAnsiEventHandler) { + w.logf = f + } +} + +func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler { + infoReset, err := GetConsoleScreenBufferInfo(fd) + if err != nil { + return nil + } + + h := &windowsAnsiEventHandler{ + fd: fd, + file: file, + infoReset: infoReset, + attributes: infoReset.Attributes, + } + for _, o := range opts { + o(h) + } + + if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { + logFile, _ := os.Create("winEventHandler.log") + logger := log.New(logFile, "", log.LstdFlags) + if h.logf != nil { + l := h.logf + h.logf = func(s string, v ...interface{}) { + l(s, v...) + logger.Printf(s, v...) + } + } else { + h.logf = logger.Printf + } + } + + if h.logf == nil { + h.logf = func(string, ...interface{}) {} + } + + return h +} + +type scrollRegion struct { + top int16 + bottom int16 +} + +// simulateLF simulates a LF or CR+LF by scrolling if necessary to handle the +// current cursor position and scroll region settings, in which case it returns +// true. If no special handling is necessary, then it does nothing and returns +// false. +// +// In the false case, the caller should ensure that a carriage return +// and line feed are inserted or that the text is otherwise wrapped. +func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) { + if h.wrapNext { + if err := h.Flush(); err != nil { + return false, err + } + h.clearWrap() + } + pos, info, err := h.getCurrentInfo() + if err != nil { + return false, err + } + sr := h.effectiveSr(info.Window) + if pos.Y == sr.bottom { + // Scrolling is necessary. Let Windows automatically scroll if the scrolling region + // is the full window. + if sr.top == info.Window.Top && sr.bottom == info.Window.Bottom { + if includeCR { + pos.X = 0 + h.updatePos(pos) + } + return false, nil + } + + // A custom scroll region is active. Scroll the window manually to simulate + // the LF. + if err := h.Flush(); err != nil { + return false, err + } + h.logf("Simulating LF inside scroll region") + if err := h.scrollUp(1); err != nil { + return false, err + } + if includeCR { + pos.X = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return false, err + } + } + return true, nil + + } else if pos.Y < info.Window.Bottom { + // Let Windows handle the LF. + pos.Y++ + if includeCR { + pos.X = 0 + } + h.updatePos(pos) + return false, nil + } else { + // The cursor is at the bottom of the screen but outside the scroll + // region. Skip the LF. + h.logf("Simulating LF outside scroll region") + if includeCR { + if err := h.Flush(); err != nil { + return false, err + } + pos.X = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return false, err + } + } + return true, nil + } +} + +// executeLF executes a LF without a CR. +func (h *windowsAnsiEventHandler) executeLF() error { + handled, err := h.simulateLF(false) + if err != nil { + return err + } + if !handled { + // Windows LF will reset the cursor column position. Write the LF + // and restore the cursor position. + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) + if pos.X != 0 { + if err := h.Flush(); err != nil { + return err + } + h.logf("Resetting cursor position for LF without CR") + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + } + } + return nil +} + +func (h *windowsAnsiEventHandler) Print(b byte) error { + if h.wrapNext { + h.buffer.WriteByte(h.marginByte) + h.clearWrap() + if _, err := h.simulateLF(true); err != nil { + return err + } + } + pos, info, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X == info.Size.X-1 { + h.wrapNext = true + h.marginByte = b + } else { + pos.X++ + h.updatePos(pos) + h.buffer.WriteByte(b) + } + return nil +} + +func (h *windowsAnsiEventHandler) Execute(b byte) error { + switch b { + case ansiterm.ANSI_TAB: + h.logf("Execute(TAB)") + // Move to the next tab stop, but preserve auto-wrap if already set. + if !h.wrapNext { + pos, info, err := h.getCurrentInfo() + if err != nil { + return err + } + pos.X = (pos.X + 8) - pos.X%8 + if pos.X >= info.Size.X { + pos.X = info.Size.X - 1 + } + if err := h.Flush(); err != nil { + return err + } + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + } + return nil + + case ansiterm.ANSI_BEL: + h.buffer.WriteByte(ansiterm.ANSI_BEL) + return nil + + case ansiterm.ANSI_BACKSPACE: + if h.wrapNext { + if err := h.Flush(); err != nil { + return err + } + h.clearWrap() + } + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X > 0 { + pos.X-- + h.updatePos(pos) + h.buffer.WriteByte(ansiterm.ANSI_BACKSPACE) + } + return nil + + case ansiterm.ANSI_VERTICAL_TAB, ansiterm.ANSI_FORM_FEED: + // Treat as true LF. + return h.executeLF() + + case ansiterm.ANSI_LINE_FEED: + // Simulate a CR and LF for now since there is no way in go-ansiterm + // to tell if the LF should include CR (and more things break when it's + // missing than when it's incorrectly added). + handled, err := h.simulateLF(true) + if handled || err != nil { + return err + } + return h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) + + case ansiterm.ANSI_CARRIAGE_RETURN: + if h.wrapNext { + if err := h.Flush(); err != nil { + return err + } + h.clearWrap() + } + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X != 0 { + pos.X = 0 + h.updatePos(pos) + h.buffer.WriteByte(ansiterm.ANSI_CARRIAGE_RETURN) + } + return nil + + default: + return nil + } +} + +func (h *windowsAnsiEventHandler) CUU(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUU: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorVertical(-param) +} + +func (h *windowsAnsiEventHandler) CUD(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUD: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorVertical(param) +} + +func (h *windowsAnsiEventHandler) CUF(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUF: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorHorizontal(param) +} + +func (h *windowsAnsiEventHandler) CUB(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUB: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorHorizontal(-param) +} + +func (h *windowsAnsiEventHandler) CNL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CNL: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorLine(param) +} + +func (h *windowsAnsiEventHandler) CPL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CPL: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorLine(-param) +} + +func (h *windowsAnsiEventHandler) CHA(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CHA: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorColumn(param) +} + +func (h *windowsAnsiEventHandler) VPA(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("VPA: [[%d]]", param) + h.clearWrap() + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + window := h.getCursorWindow(info) + position := info.CursorPosition + position.Y = window.Top + int16(param) - 1 + return h.setCursorPosition(position, window) +} + +func (h *windowsAnsiEventHandler) CUP(row int, col int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUP: [[%d %d]]", row, col) + h.clearWrap() + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + window := h.getCursorWindow(info) + position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1} + return h.setCursorPosition(position, window) +} + +func (h *windowsAnsiEventHandler) HVP(row int, col int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("HVP: [[%d %d]]", row, col) + h.clearWrap() + return h.CUP(row, col) +} + +func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)}) + h.clearWrap() + return nil +} + +func (h *windowsAnsiEventHandler) DECOM(enable bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)}) + h.clearWrap() + h.originMode = enable + return h.CUP(1, 1) +} + +func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)}) + h.clearWrap() + if err := h.ED(2); err != nil { + return err + } + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + targetWidth := int16(80) + if use132 { + targetWidth = 132 + } + if info.Size.X < targetWidth { + if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { + h.logf("set buffer failed: %v", err) + return err + } + } + window := info.Window + window.Left = 0 + window.Right = targetWidth - 1 + if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { + h.logf("set window failed: %v", err) + return err + } + if info.Size.X > targetWidth { + if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { + h.logf("set buffer failed: %v", err) + return err + } + } + return SetConsoleCursorPosition(h.fd, COORD{0, 0}) +} + +func (h *windowsAnsiEventHandler) ED(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("ED: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + + // [J -- Erases from the cursor to the end of the screen, including the cursor position. + // [1J -- Erases from the beginning of the screen to the cursor, including the cursor position. + // [2J -- Erases the complete display. The cursor does not move. + // Notes: + // -- Clearing the entire buffer, versus just the Window, works best for Windows Consoles + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + var start COORD + var end COORD + + switch param { + case 0: + start = info.CursorPosition + end = COORD{info.Size.X - 1, info.Size.Y - 1} + + case 1: + start = COORD{0, 0} + end = info.CursorPosition + + case 2: + start = COORD{0, 0} + end = COORD{info.Size.X - 1, info.Size.Y - 1} + } + + err = h.clearRange(h.attributes, start, end) + if err != nil { + return err + } + + // If the whole buffer was cleared, move the window to the top while preserving + // the window-relative cursor position. + if param == 2 { + pos := info.CursorPosition + window := info.Window + pos.Y -= window.Top + window.Bottom -= window.Top + window.Top = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { + return err + } + } + + return nil +} + +func (h *windowsAnsiEventHandler) EL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("EL: [%v]", strconv.Itoa(param)) + h.clearWrap() + + // [K -- Erases from the cursor to the end of the line, including the cursor position. + // [1K -- Erases from the beginning of the line to the cursor, including the cursor position. + // [2K -- Erases the complete line. + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + var start COORD + var end COORD + + switch param { + case 0: + start = info.CursorPosition + end = COORD{info.Size.X, info.CursorPosition.Y} + + case 1: + start = COORD{0, info.CursorPosition.Y} + end = info.CursorPosition + + case 2: + start = COORD{0, info.CursorPosition.Y} + end = COORD{info.Size.X, info.CursorPosition.Y} + } + + err = h.clearRange(h.attributes, start, end) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) IL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("IL: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.insertLines(param) +} + +func (h *windowsAnsiEventHandler) DL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DL: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.deleteLines(param) +} + +func (h *windowsAnsiEventHandler) ICH(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("ICH: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.insertCharacters(param) +} + +func (h *windowsAnsiEventHandler) DCH(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DCH: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.deleteCharacters(param) +} + +func (h *windowsAnsiEventHandler) SGR(params []int) error { + if err := h.Flush(); err != nil { + return err + } + strings := []string{} + for _, v := range params { + strings = append(strings, strconv.Itoa(v)) + } + + h.logf("SGR: [%v]", strings) + + if len(params) <= 0 { + h.attributes = h.infoReset.Attributes + h.inverted = false + } else { + for _, attr := range params { + + if attr == ansiterm.ANSI_SGR_RESET { + h.attributes = h.infoReset.Attributes + h.inverted = false + continue + } + + h.attributes, h.inverted = collectAnsiIntoWindowsAttributes(h.attributes, h.inverted, h.infoReset.Attributes, int16(attr)) + } + } + + attributes := h.attributes + if h.inverted { + attributes = invertAttributes(attributes) + } + err := SetConsoleTextAttribute(h.fd, attributes) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) SU(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("SU: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.scrollUp(param) +} + +func (h *windowsAnsiEventHandler) SD(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("SD: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.scrollDown(param) +} + +func (h *windowsAnsiEventHandler) DA(params []string) error { + h.logf("DA: [%v]", params) + // DA cannot be implemented because it must send data on the VT100 input stream, + // which is not available to go-ansiterm. + return nil +} + +func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECSTBM: [%d, %d]", top, bottom) + + // Windows is 0 indexed, Linux is 1 indexed + h.sr.top = int16(top - 1) + h.sr.bottom = int16(bottom - 1) + + // This command also moves the cursor to the origin. + h.clearWrap() + return h.CUP(1, 1) +} + +func (h *windowsAnsiEventHandler) RI() error { + if err := h.Flush(); err != nil { + return err + } + h.logf("RI: []") + h.clearWrap() + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + sr := h.effectiveSr(info.Window) + if info.CursorPosition.Y == sr.top { + return h.scrollDown(1) + } + + return h.moveCursorVertical(-1) +} + +func (h *windowsAnsiEventHandler) IND() error { + h.logf("IND: []") + return h.executeLF() +} + +func (h *windowsAnsiEventHandler) Flush() error { + h.curInfo = nil + if h.buffer.Len() > 0 { + h.logf("Flush: [%s]", h.buffer.Bytes()) + if _, err := h.buffer.WriteTo(h.file); err != nil { + return err + } + } + + if h.wrapNext && !h.drewMarginByte { + h.logf("Flush: drawing margin byte '%c'", h.marginByte) + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}} + size := COORD{1, 1} + position := COORD{0, 0} + region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y} + if err := WriteConsoleOutput(h.fd, charInfo, size, position, ®ion); err != nil { + return err + } + h.drewMarginByte = true + } + return nil +} + +// cacheConsoleInfo ensures that the current console screen information has been queried +// since the last call to Flush(). It must be called before accessing h.curInfo or h.curPos. +func (h *windowsAnsiEventHandler) getCurrentInfo() (COORD, *CONSOLE_SCREEN_BUFFER_INFO, error) { + if h.curInfo == nil { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return COORD{}, nil, err + } + h.curInfo = info + h.curPos = info.CursorPosition + } + return h.curPos, h.curInfo, nil +} + +func (h *windowsAnsiEventHandler) updatePos(pos COORD) { + if h.curInfo == nil { + panic("failed to call getCurrentInfo before calling updatePos") + } + h.curPos = pos +} + +// clearWrap clears the state where the cursor is in the margin +// waiting for the next character before wrapping the line. This must +// be done before most operations that act on the cursor. +func (h *windowsAnsiEventHandler) clearWrap() { + h.wrapNext = false + h.drewMarginByte = false +} diff --git a/vendor/github.com/alecthomas/template/LICENSE b/vendor/github.com/alecthomas/template/LICENSE new file mode 100644 index 0000000..7448756 --- /dev/null +++ b/vendor/github.com/alecthomas/template/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/alecthomas/template/README.md b/vendor/github.com/alecthomas/template/README.md new file mode 100644 index 0000000..ef6a8ee --- /dev/null +++ b/vendor/github.com/alecthomas/template/README.md @@ -0,0 +1,25 @@ +# Go's `text/template` package with newline elision + +This is a fork of Go 1.4's [text/template](http://golang.org/pkg/text/template/) package with one addition: a backslash immediately after a closing delimiter will delete all subsequent newlines until a non-newline. + +eg. + +``` +{{if true}}\ +hello +{{end}}\ +``` + +Will result in: + +``` +hello\n +``` + +Rather than: + +``` +\n +hello\n +\n +``` diff --git a/vendor/github.com/alecthomas/template/doc.go b/vendor/github.com/alecthomas/template/doc.go new file mode 100644 index 0000000..223c595 --- /dev/null +++ b/vendor/github.com/alecthomas/template/doc.go @@ -0,0 +1,406 @@ +// 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. + +/* +Package template implements data-driven templates for generating textual output. + +To generate HTML output, see package html/template, which has the same interface +as this package but automatically secures HTML output against certain attacks. + +Templates are executed by applying them to a data structure. Annotations in the +template refer to elements of the data structure (typically a field of a struct +or a key in a map) to control execution and derive values to be displayed. +Execution of the template walks the structure and sets the cursor, represented +by a period '.' and called "dot", to the value at the current location in the +structure as execution proceeds. + +The input text for a template is UTF-8-encoded text in any format. +"Actions"--data evaluations or control structures--are delimited by +"{{" and "}}"; all text outside actions is copied to the output unchanged. +Actions may not span newlines, although comments can. + +Once parsed, a template may be executed safely in parallel. + +Here is a trivial example that prints "17 items are made of wool". + + type Inventory struct { + Material string + Count uint + } + sweaters := Inventory{"wool", 17} + tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}") + if err != nil { panic(err) } + err = tmpl.Execute(os.Stdout, sweaters) + if err != nil { panic(err) } + +More intricate examples appear below. + +Actions + +Here is the list of actions. "Arguments" and "pipelines" are evaluations of +data, defined in detail below. + +*/ +// {{/* a comment */}} +// A comment; discarded. May contain newlines. +// Comments do not nest and must start and end at the +// delimiters, as shown here. +/* + + {{pipeline}} + The default textual representation of the value of the pipeline + is copied to the output. + + {{if pipeline}} T1 {{end}} + If the value of the pipeline is empty, no output is generated; + otherwise, T1 is executed. The empty values are false, 0, any + nil pointer or interface value, and any array, slice, map, or + string of length zero. + Dot is unaffected. + + {{if pipeline}} T1 {{else}} T0 {{end}} + If the value of the pipeline is empty, T0 is executed; + otherwise, T1 is executed. Dot is unaffected. + + {{if pipeline}} T1 {{else if pipeline}} T0 {{end}} + To simplify the appearance of if-else chains, the else action + of an if may include another if directly; the effect is exactly + the same as writing + {{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}} + + {{range pipeline}} T1 {{end}} + The value of the pipeline must be an array, slice, map, or channel. + If the value of the pipeline has length zero, nothing is output; + otherwise, dot is set to the successive elements of the array, + slice, or map and T1 is executed. If the value is a map and the + keys are of basic type with a defined order ("comparable"), the + elements will be visited in sorted key order. + + {{range pipeline}} T1 {{else}} T0 {{end}} + The value of the pipeline must be an array, slice, map, or channel. + If the value of the pipeline has length zero, dot is unaffected and + T0 is executed; otherwise, dot is set to the successive elements + of the array, slice, or map and T1 is executed. + + {{template "name"}} + The template with the specified name is executed with nil data. + + {{template "name" pipeline}} + The template with the specified name is executed with dot set + to the value of the pipeline. + + {{with pipeline}} T1 {{end}} + If the value of the pipeline is empty, no output is generated; + otherwise, dot is set to the value of the pipeline and T1 is + executed. + + {{with pipeline}} T1 {{else}} T0 {{end}} + If the value of the pipeline is empty, dot is unaffected and T0 + is executed; otherwise, dot is set to the value of the pipeline + and T1 is executed. + +Arguments + +An argument is a simple value, denoted by one of the following. + + - A boolean, string, character, integer, floating-point, imaginary + or complex constant in Go syntax. These behave like Go's untyped + constants, although raw strings may not span newlines. + - The keyword nil, representing an untyped Go nil. + - The character '.' (period): + . + The result is the value of dot. + - A variable name, which is a (possibly empty) alphanumeric string + preceded by a dollar sign, such as + $piOver2 + or + $ + The result is the value of the variable. + Variables are described below. + - The name of a field of the data, which must be a struct, preceded + by a period, such as + .Field + The result is the value of the field. Field invocations may be + chained: + .Field1.Field2 + Fields can also be evaluated on variables, including chaining: + $x.Field1.Field2 + - The name of a key of the data, which must be a map, preceded + by a period, such as + .Key + The result is the map element value indexed by the key. + Key invocations may be chained and combined with fields to any + depth: + .Field1.Key1.Field2.Key2 + Although the key must be an alphanumeric identifier, unlike with + field names they do not need to start with an upper case letter. + Keys can also be evaluated on variables, including chaining: + $x.key1.key2 + - The name of a niladic method of the data, preceded by a period, + such as + .Method + The result is the value of invoking the method with dot as the + receiver, dot.Method(). Such a method must have one return value (of + any type) or two return values, the second of which is an error. + If it has two and the returned error is non-nil, execution terminates + and an error is returned to the caller as the value of Execute. + Method invocations may be chained and combined with fields and keys + to any depth: + .Field1.Key1.Method1.Field2.Key2.Method2 + Methods can also be evaluated on variables, including chaining: + $x.Method1.Field + - The name of a niladic function, such as + fun + The result is the value of invoking the function, fun(). The return + types and values behave as in methods. Functions and function + names are described below. + - A parenthesized instance of one the above, for grouping. The result + may be accessed by a field or map key invocation. + print (.F1 arg1) (.F2 arg2) + (.StructValuedMethod "arg").Field + +Arguments may evaluate to any type; if they are pointers the implementation +automatically indirects to the base type when required. +If an evaluation yields a function value, such as a function-valued +field of a struct, the function is not invoked automatically, but it +can be used as a truth value for an if action and the like. To invoke +it, use the call function, defined below. + +A pipeline is a possibly chained sequence of "commands". A command is a simple +value (argument) or a function or method call, possibly with multiple arguments: + + Argument + The result is the value of evaluating the argument. + .Method [Argument...] + The method can be alone or the last element of a chain but, + unlike methods in the middle of a chain, it can take arguments. + The result is the value of calling the method with the + arguments: + dot.Method(Argument1, etc.) + functionName [Argument...] + The result is the value of calling the function associated + with the name: + function(Argument1, etc.) + Functions and function names are described below. + +Pipelines + +A pipeline may be "chained" by separating a sequence of commands with pipeline +characters '|'. In a chained pipeline, the result of the each command is +passed as the last argument of the following command. The output of the final +command in the pipeline is the value of the pipeline. + +The output of a command will be either one value or two values, the second of +which has type error. If that second value is present and evaluates to +non-nil, execution terminates and the error is returned to the caller of +Execute. + +Variables + +A pipeline inside an action may initialize a variable to capture the result. +The initialization has syntax + + $variable := pipeline + +where $variable is the name of the variable. An action that declares a +variable produces no output. + +If a "range" action initializes a variable, the variable is set to the +successive elements of the iteration. Also, a "range" may declare two +variables, separated by a comma: + + range $index, $element := pipeline + +in which case $index and $element are set to the successive values of the +array/slice index or map key and element, respectively. Note that if there is +only one variable, it is assigned the element; this is opposite to the +convention in Go range clauses. + +A variable's scope extends to the "end" action of the control structure ("if", +"with", or "range") in which it is declared, or to the end of the template if +there is no such control structure. A template invocation does not inherit +variables from the point of its invocation. + +When execution begins, $ is set to the data argument passed to Execute, that is, +to the starting value of dot. + +Examples + +Here are some example one-line templates demonstrating pipelines and variables. +All produce the quoted word "output": + + {{"\"output\""}} + A string constant. + {{`"output"`}} + A raw string constant. + {{printf "%q" "output"}} + A function call. + {{"output" | printf "%q"}} + A function call whose final argument comes from the previous + command. + {{printf "%q" (print "out" "put")}} + A parenthesized argument. + {{"put" | printf "%s%s" "out" | printf "%q"}} + A more elaborate call. + {{"output" | printf "%s" | printf "%q"}} + A longer chain. + {{with "output"}}{{printf "%q" .}}{{end}} + A with action using dot. + {{with $x := "output" | printf "%q"}}{{$x}}{{end}} + A with action that creates and uses a variable. + {{with $x := "output"}}{{printf "%q" $x}}{{end}} + A with action that uses the variable in another action. + {{with $x := "output"}}{{$x | printf "%q"}}{{end}} + The same, but pipelined. + +Functions + +During execution functions are found in two function maps: first in the +template, then in the global function map. By default, no functions are defined +in the template but the Funcs method can be used to add them. + +Predefined global functions are named as follows. + + and + Returns the boolean AND of its arguments by returning the + first empty argument or the last argument, that is, + "and x y" behaves as "if x then y else x". All the + arguments are evaluated. + call + Returns the result of calling the first argument, which + must be a function, with the remaining arguments as parameters. + Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where + Y is a func-valued field, map entry, or the like. + The first argument must be the result of an evaluation + that yields a value of function type (as distinct from + a predefined function such as print). The function must + return either one or two result values, the second of which + is of type error. If the arguments don't match the function + or the returned error value is non-nil, execution stops. + html + Returns the escaped HTML equivalent of the textual + representation of its arguments. + index + Returns the result of indexing its first argument by the + following arguments. Thus "index x 1 2 3" is, in Go syntax, + x[1][2][3]. Each indexed item must be a map, slice, or array. + js + Returns the escaped JavaScript equivalent of the textual + representation of its arguments. + len + Returns the integer length of its argument. + not + Returns the boolean negation of its single argument. + or + Returns the boolean OR of its arguments by returning the + first non-empty argument or the last argument, that is, + "or x y" behaves as "if x then x else y". All the + arguments are evaluated. + print + An alias for fmt.Sprint + printf + An alias for fmt.Sprintf + println + An alias for fmt.Sprintln + urlquery + Returns the escaped value of the textual representation of + its arguments in a form suitable for embedding in a URL query. + +The boolean functions take any zero value to be false and a non-zero +value to be true. + +There is also a set of binary comparison operators defined as +functions: + + eq + Returns the boolean truth of arg1 == arg2 + ne + Returns the boolean truth of arg1 != arg2 + lt + Returns the boolean truth of arg1 < arg2 + le + Returns the boolean truth of arg1 <= arg2 + gt + Returns the boolean truth of arg1 > arg2 + ge + Returns the boolean truth of arg1 >= arg2 + +For simpler multi-way equality tests, eq (only) accepts two or more +arguments and compares the second and subsequent to the first, +returning in effect + + arg1==arg2 || arg1==arg3 || arg1==arg4 ... + +(Unlike with || in Go, however, eq is a function call and all the +arguments will be evaluated.) + +The comparison functions work on basic types only (or named basic +types, such as "type Celsius float32"). They implement the Go rules +for comparison of values, except that size and exact type are +ignored, so any integer value, signed or unsigned, may be compared +with any other integer value. (The arithmetic value is compared, +not the bit pattern, so all negative integers are less than all +unsigned integers.) However, as usual, one may not compare an int +with a float32 and so on. + +Associated templates + +Each template is named by a string specified when it is created. Also, each +template is associated with zero or more other templates that it may invoke by +name; such associations are transitive and form a name space of templates. + +A template may use a template invocation to instantiate another associated +template; see the explanation of the "template" action above. The name must be +that of a template associated with the template that contains the invocation. + +Nested template definitions + +When parsing a template, another template may be defined and associated with the +template being parsed. Template definitions must appear at the top level of the +template, much like global variables in a Go program. + +The syntax of such definitions is to surround each template declaration with a +"define" and "end" action. + +The define action names the template being created by providing a string +constant. Here is a simple example: + + `{{define "T1"}}ONE{{end}} + {{define "T2"}}TWO{{end}} + {{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}} + {{template "T3"}}` + +This defines two templates, T1 and T2, and a third T3 that invokes the other two +when it is executed. Finally it invokes T3. If executed this template will +produce the text + + ONE TWO + +By construction, a template may reside in only one association. If it's +necessary to have a template addressable from multiple associations, the +template definition must be parsed multiple times to create distinct *Template +values, or must be copied with the Clone or AddParseTree method. + +Parse may be called multiple times to assemble the various associated templates; +see the ParseFiles and ParseGlob functions and methods for simple ways to parse +related templates stored in files. + +A template may be executed directly or through ExecuteTemplate, which executes +an associated template identified by name. To invoke our example above, we +might write, + + err := tmpl.Execute(os.Stdout, "no data needed") + if err != nil { + log.Fatalf("execution failed: %s", err) + } + +or to invoke a particular template explicitly by name, + + err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed") + if err != nil { + log.Fatalf("execution failed: %s", err) + } + +*/ +package template diff --git a/vendor/github.com/alecthomas/template/example_test.go b/vendor/github.com/alecthomas/template/example_test.go new file mode 100644 index 0000000..461ec05 --- /dev/null +++ b/vendor/github.com/alecthomas/template/example_test.go @@ -0,0 +1,72 @@ +// 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. + +package template_test + +import ( + "log" + "os" + + "github.com/alecthomas/template" +) + +func ExampleTemplate() { + // Define a template. + const letter = ` +Dear {{.Name}}, +{{if .Attended}} +It was a pleasure to see you at the wedding.{{else}} +It is a shame you couldn't make it to the wedding.{{end}} +{{with .Gift}}Thank you for the lovely {{.}}. +{{end}} +Best wishes, +Josie +` + + // Prepare some data to insert into the template. + type Recipient struct { + Name, Gift string + Attended bool + } + var recipients = []Recipient{ + {"Aunt Mildred", "bone china tea set", true}, + {"Uncle John", "moleskin pants", false}, + {"Cousin Rodney", "", false}, + } + + // Create a new template and parse the letter into it. + t := template.Must(template.New("letter").Parse(letter)) + + // Execute the template for each recipient. + for _, r := range recipients { + err := t.Execute(os.Stdout, r) + if err != nil { + log.Println("executing template:", err) + } + } + + // Output: + // Dear Aunt Mildred, + // + // It was a pleasure to see you at the wedding. + // Thank you for the lovely bone china tea set. + // + // Best wishes, + // Josie + // + // Dear Uncle John, + // + // It is a shame you couldn't make it to the wedding. + // Thank you for the lovely moleskin pants. + // + // Best wishes, + // Josie + // + // Dear Cousin Rodney, + // + // It is a shame you couldn't make it to the wedding. + // + // Best wishes, + // Josie +} diff --git a/vendor/github.com/alecthomas/template/examplefiles_test.go b/vendor/github.com/alecthomas/template/examplefiles_test.go new file mode 100644 index 0000000..0c7181d --- /dev/null +++ b/vendor/github.com/alecthomas/template/examplefiles_test.go @@ -0,0 +1,183 @@ +// Copyright 2012 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. + +package template_test + +import ( + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + + "github.com/alecthomas/template" +) + +// templateFile defines the contents of a template to be stored in a file, for testing. +type templateFile struct { + name string + contents string +} + +func createTestDir(files []templateFile) string { + dir, err := ioutil.TempDir("", "template") + if err != nil { + log.Fatal(err) + } + for _, file := range files { + f, err := os.Create(filepath.Join(dir, file.name)) + if err != nil { + log.Fatal(err) + } + defer f.Close() + _, err = io.WriteString(f, file.contents) + if err != nil { + log.Fatal(err) + } + } + return dir +} + +// Here we demonstrate loading a set of templates from a directory. +func ExampleTemplate_glob() { + // Here we create a temporary directory and populate it with our sample + // template definition files; usually the template files would already + // exist in some location known to the program. + dir := createTestDir([]templateFile{ + // T0.tmpl is a plain template file that just invokes T1. + {"T0.tmpl", `T0 invokes T1: ({{template "T1"}})`}, + // T1.tmpl defines a template, T1 that invokes T2. + {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`}, + // T2.tmpl defines a template T2. + {"T2.tmpl", `{{define "T2"}}This is T2{{end}}`}, + }) + // Clean up after the test; another quirk of running as an example. + defer os.RemoveAll(dir) + + // pattern is the glob pattern used to find all the template files. + pattern := filepath.Join(dir, "*.tmpl") + + // Here starts the example proper. + // T0.tmpl is the first name matched, so it becomes the starting template, + // the value returned by ParseGlob. + tmpl := template.Must(template.ParseGlob(pattern)) + + err := tmpl.Execute(os.Stdout, nil) + if err != nil { + log.Fatalf("template execution: %s", err) + } + // Output: + // T0 invokes T1: (T1 invokes T2: (This is T2)) +} + +// This example demonstrates one way to share some templates +// and use them in different contexts. In this variant we add multiple driver +// templates by hand to an existing bundle of templates. +func ExampleTemplate_helpers() { + // Here we create a temporary directory and populate it with our sample + // template definition files; usually the template files would already + // exist in some location known to the program. + dir := createTestDir([]templateFile{ + // T1.tmpl defines a template, T1 that invokes T2. + {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`}, + // T2.tmpl defines a template T2. + {"T2.tmpl", `{{define "T2"}}This is T2{{end}}`}, + }) + // Clean up after the test; another quirk of running as an example. + defer os.RemoveAll(dir) + + // pattern is the glob pattern used to find all the template files. + pattern := filepath.Join(dir, "*.tmpl") + + // Here starts the example proper. + // Load the helpers. + templates := template.Must(template.ParseGlob(pattern)) + // Add one driver template to the bunch; we do this with an explicit template definition. + _, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}") + if err != nil { + log.Fatal("parsing driver1: ", err) + } + // Add another driver template. + _, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}") + if err != nil { + log.Fatal("parsing driver2: ", err) + } + // We load all the templates before execution. This package does not require + // that behavior but html/template's escaping does, so it's a good habit. + err = templates.ExecuteTemplate(os.Stdout, "driver1", nil) + if err != nil { + log.Fatalf("driver1 execution: %s", err) + } + err = templates.ExecuteTemplate(os.Stdout, "driver2", nil) + if err != nil { + log.Fatalf("driver2 execution: %s", err) + } + // Output: + // Driver 1 calls T1: (T1 invokes T2: (This is T2)) + // Driver 2 calls T2: (This is T2) +} + +// This example demonstrates how to use one group of driver +// templates with distinct sets of helper templates. +func ExampleTemplate_share() { + // Here we create a temporary directory and populate it with our sample + // template definition files; usually the template files would already + // exist in some location known to the program. + dir := createTestDir([]templateFile{ + // T0.tmpl is a plain template file that just invokes T1. + {"T0.tmpl", "T0 ({{.}} version) invokes T1: ({{template `T1`}})\n"}, + // T1.tmpl defines a template, T1 that invokes T2. Note T2 is not defined + {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`}, + }) + // Clean up after the test; another quirk of running as an example. + defer os.RemoveAll(dir) + + // pattern is the glob pattern used to find all the template files. + pattern := filepath.Join(dir, "*.tmpl") + + // Here starts the example proper. + // Load the drivers. + drivers := template.Must(template.ParseGlob(pattern)) + + // We must define an implementation of the T2 template. First we clone + // the drivers, then add a definition of T2 to the template name space. + + // 1. Clone the helper set to create a new name space from which to run them. + first, err := drivers.Clone() + if err != nil { + log.Fatal("cloning helpers: ", err) + } + // 2. Define T2, version A, and parse it. + _, err = first.Parse("{{define `T2`}}T2, version A{{end}}") + if err != nil { + log.Fatal("parsing T2: ", err) + } + + // Now repeat the whole thing, using a different version of T2. + // 1. Clone the drivers. + second, err := drivers.Clone() + if err != nil { + log.Fatal("cloning drivers: ", err) + } + // 2. Define T2, version B, and parse it. + _, err = second.Parse("{{define `T2`}}T2, version B{{end}}") + if err != nil { + log.Fatal("parsing T2: ", err) + } + + // Execute the templates in the reverse order to verify the + // first is unaffected by the second. + err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second") + if err != nil { + log.Fatalf("second execution: %s", err) + } + err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first") + if err != nil { + log.Fatalf("first: execution: %s", err) + } + + // Output: + // T0 (second version) invokes T1: (T1 invokes T2: (T2, version B)) + // T0 (first version) invokes T1: (T1 invokes T2: (T2, version A)) +} diff --git a/vendor/github.com/alecthomas/template/examplefunc_test.go b/vendor/github.com/alecthomas/template/examplefunc_test.go new file mode 100644 index 0000000..8767cfd --- /dev/null +++ b/vendor/github.com/alecthomas/template/examplefunc_test.go @@ -0,0 +1,55 @@ +// Copyright 2012 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. + +package template_test + +import ( + "log" + "os" + "strings" + + "github.com/alecthomas/template" +) + +// This example demonstrates a custom function to process template text. +// It installs the strings.Title function and uses it to +// Make Title Text Look Good In Our Template's Output. +func ExampleTemplate_func() { + // First we create a FuncMap with which to register the function. + funcMap := template.FuncMap{ + // The name "title" is what the function will be called in the template text. + "title": strings.Title, + } + + // A simple template definition to test our function. + // We print the input text several ways: + // - the original + // - title-cased + // - title-cased and then printed with %q + // - printed with %q and then title-cased. + const templateText = ` +Input: {{printf "%q" .}} +Output 0: {{title .}} +Output 1: {{title . | printf "%q"}} +Output 2: {{printf "%q" . | title}} +` + + // Create a template, add the function map, and parse the text. + tmpl, err := template.New("titleTest").Funcs(funcMap).Parse(templateText) + if err != nil { + log.Fatalf("parsing: %s", err) + } + + // Run the template to verify the output. + err = tmpl.Execute(os.Stdout, "the go programming language") + if err != nil { + log.Fatalf("execution: %s", err) + } + + // Output: + // Input: "the go programming language" + // Output 0: The Go Programming Language + // Output 1: "The Go Programming Language" + // Output 2: "The Go Programming Language" +} diff --git a/vendor/github.com/alecthomas/template/exec.go b/vendor/github.com/alecthomas/template/exec.go new file mode 100644 index 0000000..c3078e5 --- /dev/null +++ b/vendor/github.com/alecthomas/template/exec.go @@ -0,0 +1,845 @@ +// 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. + +package template + +import ( + "bytes" + "fmt" + "io" + "reflect" + "runtime" + "sort" + "strings" + + "github.com/alecthomas/template/parse" +) + +// state represents the state of an execution. It's not part of the +// template so that multiple executions of the same template +// can execute in parallel. +type state struct { + tmpl *Template + wr io.Writer + node parse.Node // current node, for errors + vars []variable // push-down stack of variable values. +} + +// variable holds the dynamic value of a variable such as $, $x etc. +type variable struct { + name string + value reflect.Value +} + +// push pushes a new variable on the stack. +func (s *state) push(name string, value reflect.Value) { + s.vars = append(s.vars, variable{name, value}) +} + +// mark returns the length of the variable stack. +func (s *state) mark() int { + return len(s.vars) +} + +// pop pops the variable stack up to the mark. +func (s *state) pop(mark int) { + s.vars = s.vars[0:mark] +} + +// setVar overwrites the top-nth variable on the stack. Used by range iterations. +func (s *state) setVar(n int, value reflect.Value) { + s.vars[len(s.vars)-n].value = value +} + +// varValue returns the value of the named variable. +func (s *state) varValue(name string) reflect.Value { + for i := s.mark() - 1; i >= 0; i-- { + if s.vars[i].name == name { + return s.vars[i].value + } + } + s.errorf("undefined variable: %s", name) + return zero +} + +var zero reflect.Value + +// at marks the state to be on node n, for error reporting. +func (s *state) at(node parse.Node) { + s.node = node +} + +// doublePercent returns the string with %'s replaced by %%, if necessary, +// so it can be used safely inside a Printf format string. +func doublePercent(str string) string { + if strings.Contains(str, "%") { + str = strings.Replace(str, "%", "%%", -1) + } + return str +} + +// errorf formats the error and terminates processing. +func (s *state) errorf(format string, args ...interface{}) { + name := doublePercent(s.tmpl.Name()) + if s.node == nil { + format = fmt.Sprintf("template: %s: %s", name, format) + } else { + location, context := s.tmpl.ErrorContext(s.node) + format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format) + } + panic(fmt.Errorf(format, args...)) +} + +// errRecover is the handler that turns panics into returns from the top +// level of Parse. +func errRecover(errp *error) { + e := recover() + if e != nil { + switch err := e.(type) { + case runtime.Error: + panic(e) + case error: + *errp = err + default: + panic(e) + } + } +} + +// ExecuteTemplate applies the template associated with t that has the given name +// to the specified data object and writes the output to wr. +// If an error occurs executing the template or writing its output, +// execution stops, but partial results may already have been written to +// the output writer. +// A template may be executed safely in parallel. +func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { + tmpl := t.tmpl[name] + if tmpl == nil { + return fmt.Errorf("template: no template %q associated with template %q", name, t.name) + } + return tmpl.Execute(wr, data) +} + +// Execute applies a parsed template to the specified data object, +// and writes the output to wr. +// If an error occurs executing the template or writing its output, +// execution stops, but partial results may already have been written to +// the output writer. +// A template may be executed safely in parallel. +func (t *Template) Execute(wr io.Writer, data interface{}) (err error) { + defer errRecover(&err) + value := reflect.ValueOf(data) + state := &state{ + tmpl: t, + wr: wr, + vars: []variable{{"$", value}}, + } + t.init() + if t.Tree == nil || t.Root == nil { + var b bytes.Buffer + for name, tmpl := range t.tmpl { + if tmpl.Tree == nil || tmpl.Root == nil { + continue + } + if b.Len() > 0 { + b.WriteString(", ") + } + fmt.Fprintf(&b, "%q", name) + } + var s string + if b.Len() > 0 { + s = "; defined templates are: " + b.String() + } + state.errorf("%q is an incomplete or empty template%s", t.Name(), s) + } + state.walk(value, t.Root) + return +} + +// Walk functions step through the major pieces of the template structure, +// generating output as they go. +func (s *state) walk(dot reflect.Value, node parse.Node) { + s.at(node) + switch node := node.(type) { + case *parse.ActionNode: + // Do not pop variables so they persist until next end. + // Also, if the action declares variables, don't print the result. + val := s.evalPipeline(dot, node.Pipe) + if len(node.Pipe.Decl) == 0 { + s.printValue(node, val) + } + case *parse.IfNode: + s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList) + case *parse.ListNode: + for _, node := range node.Nodes { + s.walk(dot, node) + } + case *parse.RangeNode: + s.walkRange(dot, node) + case *parse.TemplateNode: + s.walkTemplate(dot, node) + case *parse.TextNode: + if _, err := s.wr.Write(node.Text); err != nil { + s.errorf("%s", err) + } + case *parse.WithNode: + s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList) + default: + s.errorf("unknown node: %s", node) + } +} + +// walkIfOrWith walks an 'if' or 'with' node. The two control structures +// are identical in behavior except that 'with' sets dot. +func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) { + defer s.pop(s.mark()) + val := s.evalPipeline(dot, pipe) + truth, ok := isTrue(val) + if !ok { + s.errorf("if/with can't use %v", val) + } + if truth { + if typ == parse.NodeWith { + s.walk(val, list) + } else { + s.walk(dot, list) + } + } else if elseList != nil { + s.walk(dot, elseList) + } +} + +// isTrue reports whether the value is 'true', in the sense of not the zero of its type, +// and whether the value has a meaningful truth value. +func isTrue(val reflect.Value) (truth, ok bool) { + if !val.IsValid() { + // Something like var x interface{}, never set. It's a form of nil. + return false, true + } + switch val.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + truth = val.Len() > 0 + case reflect.Bool: + truth = val.Bool() + case reflect.Complex64, reflect.Complex128: + truth = val.Complex() != 0 + case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: + truth = !val.IsNil() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + truth = val.Int() != 0 + case reflect.Float32, reflect.Float64: + truth = val.Float() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + truth = val.Uint() != 0 + case reflect.Struct: + truth = true // Struct values are always true. + default: + return + } + return truth, true +} + +func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { + s.at(r) + defer s.pop(s.mark()) + val, _ := indirect(s.evalPipeline(dot, r.Pipe)) + // mark top of stack before any variables in the body are pushed. + mark := s.mark() + oneIteration := func(index, elem reflect.Value) { + // Set top var (lexically the second if there are two) to the element. + if len(r.Pipe.Decl) > 0 { + s.setVar(1, elem) + } + // Set next var (lexically the first if there are two) to the index. + if len(r.Pipe.Decl) > 1 { + s.setVar(2, index) + } + s.walk(elem, r.List) + s.pop(mark) + } + switch val.Kind() { + case reflect.Array, reflect.Slice: + if val.Len() == 0 { + break + } + for i := 0; i < val.Len(); i++ { + oneIteration(reflect.ValueOf(i), val.Index(i)) + } + return + case reflect.Map: + if val.Len() == 0 { + break + } + for _, key := range sortKeys(val.MapKeys()) { + oneIteration(key, val.MapIndex(key)) + } + return + case reflect.Chan: + if val.IsNil() { + break + } + i := 0 + for ; ; i++ { + elem, ok := val.Recv() + if !ok { + break + } + oneIteration(reflect.ValueOf(i), elem) + } + if i == 0 { + break + } + return + case reflect.Invalid: + break // An invalid value is likely a nil map, etc. and acts like an empty map. + default: + s.errorf("range can't iterate over %v", val) + } + if r.ElseList != nil { + s.walk(dot, r.ElseList) + } +} + +func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) { + s.at(t) + tmpl := s.tmpl.tmpl[t.Name] + if tmpl == nil { + s.errorf("template %q not defined", t.Name) + } + // Variables declared by the pipeline persist. + dot = s.evalPipeline(dot, t.Pipe) + newState := *s + newState.tmpl = tmpl + // No dynamic scoping: template invocations inherit no variables. + newState.vars = []variable{{"$", dot}} + newState.walk(dot, tmpl.Root) +} + +// Eval functions evaluate pipelines, commands, and their elements and extract +// values from the data structure by examining fields, calling methods, and so on. +// The printing of those values happens only through walk functions. + +// evalPipeline returns the value acquired by evaluating a pipeline. If the +// pipeline has a variable declaration, the variable will be pushed on the +// stack. Callers should therefore pop the stack after they are finished +// executing commands depending on the pipeline value. +func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) { + if pipe == nil { + return + } + s.at(pipe) + for _, cmd := range pipe.Cmds { + value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg. + // If the object has type interface{}, dig down one level to the thing inside. + if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 { + value = reflect.ValueOf(value.Interface()) // lovely! + } + } + for _, variable := range pipe.Decl { + s.push(variable.Ident[0], value) + } + return value +} + +func (s *state) notAFunction(args []parse.Node, final reflect.Value) { + if len(args) > 1 || final.IsValid() { + s.errorf("can't give argument to non-function %s", args[0]) + } +} + +func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value { + firstWord := cmd.Args[0] + switch n := firstWord.(type) { + case *parse.FieldNode: + return s.evalFieldNode(dot, n, cmd.Args, final) + case *parse.ChainNode: + return s.evalChainNode(dot, n, cmd.Args, final) + case *parse.IdentifierNode: + // Must be a function. + return s.evalFunction(dot, n, cmd, cmd.Args, final) + case *parse.PipeNode: + // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored. + return s.evalPipeline(dot, n) + case *parse.VariableNode: + return s.evalVariableNode(dot, n, cmd.Args, final) + } + s.at(firstWord) + s.notAFunction(cmd.Args, final) + switch word := firstWord.(type) { + case *parse.BoolNode: + return reflect.ValueOf(word.True) + case *parse.DotNode: + return dot + case *parse.NilNode: + s.errorf("nil is not a command") + case *parse.NumberNode: + return s.idealConstant(word) + case *parse.StringNode: + return reflect.ValueOf(word.Text) + } + s.errorf("can't evaluate command %q", firstWord) + panic("not reached") +} + +// idealConstant is called to return the value of a number in a context where +// we don't know the type. In that case, the syntax of the number tells us +// its type, and we use Go rules to resolve. Note there is no such thing as +// a uint ideal constant in this situation - the value must be of int type. +func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value { + // These are ideal constants but we don't know the type + // and we have no context. (If it was a method argument, + // we'd know what we need.) The syntax guides us to some extent. + s.at(constant) + switch { + case constant.IsComplex: + return reflect.ValueOf(constant.Complex128) // incontrovertible. + case constant.IsFloat && !isHexConstant(constant.Text) && strings.IndexAny(constant.Text, ".eE") >= 0: + return reflect.ValueOf(constant.Float64) + case constant.IsInt: + n := int(constant.Int64) + if int64(n) != constant.Int64 { + s.errorf("%s overflows int", constant.Text) + } + return reflect.ValueOf(n) + case constant.IsUint: + s.errorf("%s overflows int", constant.Text) + } + return zero +} + +func isHexConstant(s string) bool { + return len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') +} + +func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value { + s.at(field) + return s.evalFieldChain(dot, dot, field, field.Ident, args, final) +} + +func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value { + s.at(chain) + // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields. + pipe := s.evalArg(dot, nil, chain.Node) + if len(chain.Field) == 0 { + s.errorf("internal error: no fields in evalChainNode") + } + return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final) +} + +func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value { + // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields. + s.at(variable) + value := s.varValue(variable.Ident[0]) + if len(variable.Ident) == 1 { + s.notAFunction(args, final) + return value + } + return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final) +} + +// evalFieldChain evaluates .X.Y.Z possibly followed by arguments. +// dot is the environment in which to evaluate arguments, while +// receiver is the value being walked along the chain. +func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value { + n := len(ident) + for i := 0; i < n-1; i++ { + receiver = s.evalField(dot, ident[i], node, nil, zero, receiver) + } + // Now if it's a method, it gets the arguments. + return s.evalField(dot, ident[n-1], node, args, final, receiver) +} + +func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value { + s.at(node) + name := node.Ident + function, ok := findFunction(name, s.tmpl) + if !ok { + s.errorf("%q is not a defined function", name) + } + return s.evalCall(dot, function, cmd, name, args, final) +} + +// evalField evaluates an expression like (.Field) or (.Field arg1 arg2). +// The 'final' argument represents the return value from the preceding +// value of the pipeline, if any. +func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value { + if !receiver.IsValid() { + return zero + } + typ := receiver.Type() + receiver, _ = indirect(receiver) + // Unless it's an interface, need to get to a value of type *T to guarantee + // we see all methods of T and *T. + ptr := receiver + if ptr.Kind() != reflect.Interface && ptr.CanAddr() { + ptr = ptr.Addr() + } + if method := ptr.MethodByName(fieldName); method.IsValid() { + return s.evalCall(dot, method, node, fieldName, args, final) + } + hasArgs := len(args) > 1 || final.IsValid() + // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil. + receiver, isNil := indirect(receiver) + if isNil { + s.errorf("nil pointer evaluating %s.%s", typ, fieldName) + } + switch receiver.Kind() { + case reflect.Struct: + tField, ok := receiver.Type().FieldByName(fieldName) + if ok { + field := receiver.FieldByIndex(tField.Index) + if tField.PkgPath != "" { // field is unexported + s.errorf("%s is an unexported field of struct type %s", fieldName, typ) + } + // If it's a function, we must call it. + if hasArgs { + s.errorf("%s has arguments but cannot be invoked as function", fieldName) + } + return field + } + s.errorf("%s is not a field of struct type %s", fieldName, typ) + case reflect.Map: + // If it's a map, attempt to use the field name as a key. + nameVal := reflect.ValueOf(fieldName) + if nameVal.Type().AssignableTo(receiver.Type().Key()) { + if hasArgs { + s.errorf("%s is not a method but has arguments", fieldName) + } + return receiver.MapIndex(nameVal) + } + } + s.errorf("can't evaluate field %s in type %s", fieldName, typ) + panic("not reached") +} + +var ( + errorType = reflect.TypeOf((*error)(nil)).Elem() + fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() +) + +// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so +// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0] +// as the function itself. +func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value { + if args != nil { + args = args[1:] // Zeroth arg is function name/node; not passed to function. + } + typ := fun.Type() + numIn := len(args) + if final.IsValid() { + numIn++ + } + numFixed := len(args) + if typ.IsVariadic() { + numFixed = typ.NumIn() - 1 // last arg is the variadic one. + if numIn < numFixed { + s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args)) + } + } else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() { + s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args)) + } + if !goodFunc(typ) { + // TODO: This could still be a confusing error; maybe goodFunc should provide info. + s.errorf("can't call method/function %q with %d results", name, typ.NumOut()) + } + // Build the arg list. + argv := make([]reflect.Value, numIn) + // Args must be evaluated. Fixed args first. + i := 0 + for ; i < numFixed && i < len(args); i++ { + argv[i] = s.evalArg(dot, typ.In(i), args[i]) + } + // Now the ... args. + if typ.IsVariadic() { + argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice. + for ; i < len(args); i++ { + argv[i] = s.evalArg(dot, argType, args[i]) + } + } + // Add final value if necessary. + if final.IsValid() { + t := typ.In(typ.NumIn() - 1) + if typ.IsVariadic() { + t = t.Elem() + } + argv[i] = s.validateType(final, t) + } + result := fun.Call(argv) + // If we have an error that is not nil, stop execution and return that error to the caller. + if len(result) == 2 && !result[1].IsNil() { + s.at(node) + s.errorf("error calling %s: %s", name, result[1].Interface().(error)) + } + return result[0] +} + +// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. +func canBeNil(typ reflect.Type) bool { + switch typ.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return true + } + return false +} + +// validateType guarantees that the value is valid and assignable to the type. +func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value { + if !value.IsValid() { + if typ == nil || canBeNil(typ) { + // An untyped nil interface{}. Accept as a proper nil value. + return reflect.Zero(typ) + } + s.errorf("invalid value; expected %s", typ) + } + if typ != nil && !value.Type().AssignableTo(typ) { + if value.Kind() == reflect.Interface && !value.IsNil() { + value = value.Elem() + if value.Type().AssignableTo(typ) { + return value + } + // fallthrough + } + // Does one dereference or indirection work? We could do more, as we + // do with method receivers, but that gets messy and method receivers + // are much more constrained, so it makes more sense there than here. + // Besides, one is almost always all you need. + switch { + case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ): + value = value.Elem() + if !value.IsValid() { + s.errorf("dereference of nil pointer of type %s", typ) + } + case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr(): + value = value.Addr() + default: + s.errorf("wrong type for value; expected %s; got %s", typ, value.Type()) + } + } + return value +} + +func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + switch arg := n.(type) { + case *parse.DotNode: + return s.validateType(dot, typ) + case *parse.NilNode: + if canBeNil(typ) { + return reflect.Zero(typ) + } + s.errorf("cannot assign nil to %s", typ) + case *parse.FieldNode: + return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ) + case *parse.VariableNode: + return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ) + case *parse.PipeNode: + return s.validateType(s.evalPipeline(dot, arg), typ) + case *parse.IdentifierNode: + return s.evalFunction(dot, arg, arg, nil, zero) + case *parse.ChainNode: + return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ) + } + switch typ.Kind() { + case reflect.Bool: + return s.evalBool(typ, n) + case reflect.Complex64, reflect.Complex128: + return s.evalComplex(typ, n) + case reflect.Float32, reflect.Float64: + return s.evalFloat(typ, n) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return s.evalInteger(typ, n) + case reflect.Interface: + if typ.NumMethod() == 0 { + return s.evalEmptyInterface(dot, n) + } + case reflect.String: + return s.evalString(typ, n) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return s.evalUnsignedInteger(typ, n) + } + s.errorf("can't handle %s for arg of type %s", n, typ) + panic("not reached") +} + +func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.BoolNode); ok { + value := reflect.New(typ).Elem() + value.SetBool(n.True) + return value + } + s.errorf("expected bool; found %s", n) + panic("not reached") +} + +func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.StringNode); ok { + value := reflect.New(typ).Elem() + value.SetString(n.Text) + return value + } + s.errorf("expected string; found %s", n) + panic("not reached") +} + +func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.NumberNode); ok && n.IsInt { + value := reflect.New(typ).Elem() + value.SetInt(n.Int64) + return value + } + s.errorf("expected integer; found %s", n) + panic("not reached") +} + +func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.NumberNode); ok && n.IsUint { + value := reflect.New(typ).Elem() + value.SetUint(n.Uint64) + return value + } + s.errorf("expected unsigned integer; found %s", n) + panic("not reached") +} + +func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.NumberNode); ok && n.IsFloat { + value := reflect.New(typ).Elem() + value.SetFloat(n.Float64) + return value + } + s.errorf("expected float; found %s", n) + panic("not reached") +} + +func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value { + if n, ok := n.(*parse.NumberNode); ok && n.IsComplex { + value := reflect.New(typ).Elem() + value.SetComplex(n.Complex128) + return value + } + s.errorf("expected complex; found %s", n) + panic("not reached") +} + +func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value { + s.at(n) + switch n := n.(type) { + case *parse.BoolNode: + return reflect.ValueOf(n.True) + case *parse.DotNode: + return dot + case *parse.FieldNode: + return s.evalFieldNode(dot, n, nil, zero) + case *parse.IdentifierNode: + return s.evalFunction(dot, n, n, nil, zero) + case *parse.NilNode: + // NilNode is handled in evalArg, the only place that calls here. + s.errorf("evalEmptyInterface: nil (can't happen)") + case *parse.NumberNode: + return s.idealConstant(n) + case *parse.StringNode: + return reflect.ValueOf(n.Text) + case *parse.VariableNode: + return s.evalVariableNode(dot, n, nil, zero) + case *parse.PipeNode: + return s.evalPipeline(dot, n) + } + s.errorf("can't handle assignment of %s to empty interface argument", n) + panic("not reached") +} + +// indirect returns the item at the end of indirection, and a bool to indicate if it's nil. +// We indirect through pointers and empty interfaces (only) because +// non-empty interfaces have methods we might need. +func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { + for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { + if v.IsNil() { + return v, true + } + if v.Kind() == reflect.Interface && v.NumMethod() > 0 { + break + } + } + return v, false +} + +// printValue writes the textual representation of the value to the output of +// the template. +func (s *state) printValue(n parse.Node, v reflect.Value) { + s.at(n) + iface, ok := printableValue(v) + if !ok { + s.errorf("can't print %s of type %s", n, v.Type()) + } + fmt.Fprint(s.wr, iface) +} + +// printableValue returns the, possibly indirected, interface value inside v that +// is best for a call to formatted printer. +func printableValue(v reflect.Value) (interface{}, bool) { + if v.Kind() == reflect.Ptr { + v, _ = indirect(v) // fmt.Fprint handles nil. + } + if !v.IsValid() { + return "", true + } + + if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { + if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) { + v = v.Addr() + } else { + switch v.Kind() { + case reflect.Chan, reflect.Func: + return nil, false + } + } + } + return v.Interface(), true +} + +// Types to help sort the keys in a map for reproducible output. + +type rvs []reflect.Value + +func (x rvs) Len() int { return len(x) } +func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +type rvInts struct{ rvs } + +func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() } + +type rvUints struct{ rvs } + +func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() } + +type rvFloats struct{ rvs } + +func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() } + +type rvStrings struct{ rvs } + +func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() } + +// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys. +func sortKeys(v []reflect.Value) []reflect.Value { + if len(v) <= 1 { + return v + } + switch v[0].Kind() { + case reflect.Float32, reflect.Float64: + sort.Sort(rvFloats{v}) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + sort.Sort(rvInts{v}) + case reflect.String: + sort.Sort(rvStrings{v}) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + sort.Sort(rvUints{v}) + } + return v +} diff --git a/vendor/github.com/alecthomas/template/exec_test.go b/vendor/github.com/alecthomas/template/exec_test.go new file mode 100644 index 0000000..69c213e --- /dev/null +++ b/vendor/github.com/alecthomas/template/exec_test.go @@ -0,0 +1,1044 @@ +// 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. + +package template + +import ( + "bytes" + "errors" + "flag" + "fmt" + "reflect" + "strings" + "testing" +) + +var debug = flag.Bool("debug", false, "show the errors produced by the tests") + +// T has lots of interesting pieces to use to test execution. +type T struct { + // Basics + True bool + I int + U16 uint16 + X string + FloatZero float64 + ComplexZero complex128 + // Nested structs. + U *U + // Struct with String method. + V0 V + V1, V2 *V + // Struct with Error method. + W0 W + W1, W2 *W + // Slices + SI []int + SIEmpty []int + SB []bool + // Maps + MSI map[string]int + MSIone map[string]int // one element, for deterministic output + MSIEmpty map[string]int + MXI map[interface{}]int + MII map[int]int + SMSI []map[string]int + // Empty interfaces; used to see if we can dig inside one. + Empty0 interface{} // nil + Empty1 interface{} + Empty2 interface{} + Empty3 interface{} + Empty4 interface{} + // Non-empty interface. + NonEmptyInterface I + // Stringer. + Str fmt.Stringer + Err error + // Pointers + PI *int + PS *string + PSI *[]int + NIL *int + // Function (not method) + BinaryFunc func(string, string) string + VariadicFunc func(...string) string + VariadicFuncInt func(int, ...string) string + NilOKFunc func(*int) bool + ErrFunc func() (string, error) + // Template to test evaluation of templates. + Tmpl *Template + // Unexported field; cannot be accessed by template. + unexported int +} + +type U struct { + V string +} + +type V struct { + j int +} + +func (v *V) String() string { + if v == nil { + return "nilV" + } + return fmt.Sprintf("<%d>", v.j) +} + +type W struct { + k int +} + +func (w *W) Error() string { + if w == nil { + return "nilW" + } + return fmt.Sprintf("[%d]", w.k) +} + +var tVal = &T{ + True: true, + I: 17, + U16: 16, + X: "x", + U: &U{"v"}, + V0: V{6666}, + V1: &V{7777}, // leave V2 as nil + W0: W{888}, + W1: &W{999}, // leave W2 as nil + SI: []int{3, 4, 5}, + SB: []bool{true, false}, + MSI: map[string]int{"one": 1, "two": 2, "three": 3}, + MSIone: map[string]int{"one": 1}, + MXI: map[interface{}]int{"one": 1}, + MII: map[int]int{1: 1}, + SMSI: []map[string]int{ + {"one": 1, "two": 2}, + {"eleven": 11, "twelve": 12}, + }, + Empty1: 3, + Empty2: "empty2", + Empty3: []int{7, 8}, + Empty4: &U{"UinEmpty"}, + NonEmptyInterface: new(T), + Str: bytes.NewBuffer([]byte("foozle")), + Err: errors.New("erroozle"), + PI: newInt(23), + PS: newString("a string"), + PSI: newIntSlice(21, 22, 23), + BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) }, + VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") }, + VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") }, + NilOKFunc: func(s *int) bool { return s == nil }, + ErrFunc: func() (string, error) { return "bla", nil }, + Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X +} + +// A non-empty interface. +type I interface { + Method0() string +} + +var iVal I = tVal + +// Helpers for creation. +func newInt(n int) *int { + return &n +} + +func newString(s string) *string { + return &s +} + +func newIntSlice(n ...int) *[]int { + p := new([]int) + *p = make([]int, len(n)) + copy(*p, n) + return p +} + +// Simple methods with and without arguments. +func (t *T) Method0() string { + return "M0" +} + +func (t *T) Method1(a int) int { + return a +} + +func (t *T) Method2(a uint16, b string) string { + return fmt.Sprintf("Method2: %d %s", a, b) +} + +func (t *T) Method3(v interface{}) string { + return fmt.Sprintf("Method3: %v", v) +} + +func (t *T) Copy() *T { + n := new(T) + *n = *t + return n +} + +func (t *T) MAdd(a int, b []int) []int { + v := make([]int, len(b)) + for i, x := range b { + v[i] = x + a + } + return v +} + +var myError = errors.New("my error") + +// MyError returns a value and an error according to its argument. +func (t *T) MyError(error bool) (bool, error) { + if error { + return true, myError + } + return false, nil +} + +// A few methods to test chaining. +func (t *T) GetU() *U { + return t.U +} + +func (u *U) TrueFalse(b bool) string { + if b { + return "true" + } + return "" +} + +func typeOf(arg interface{}) string { + return fmt.Sprintf("%T", arg) +} + +type execTest struct { + name string + input string + output string + data interface{} + ok bool +} + +// bigInt and bigUint are hex string representing numbers either side +// of the max int boundary. +// We do it this way so the test doesn't depend on ints being 32 bits. +var ( + bigInt = fmt.Sprintf("0x%x", int(1<", tVal, true}, + {"map .one interface", "{{.MXI.one}}", "1", tVal, true}, + {"map .WRONG args", "{{.MSI.one 1}}", "", tVal, false}, + {"map .WRONG type", "{{.MII.one}}", "", tVal, false}, + + // Dots of all kinds to test basic evaluation. + {"dot int", "<{{.}}>", "<13>", 13, true}, + {"dot uint", "<{{.}}>", "<14>", uint(14), true}, + {"dot float", "<{{.}}>", "<15.1>", 15.1, true}, + {"dot bool", "<{{.}}>", "", true, true}, + {"dot complex", "<{{.}}>", "<(16.2-17i)>", 16.2 - 17i, true}, + {"dot string", "<{{.}}>", "", "hello", true}, + {"dot slice", "<{{.}}>", "<[-1 -2 -3]>", []int{-1, -2, -3}, true}, + {"dot map", "<{{.}}>", "", map[string]int{"two": 22}, true}, + {"dot struct", "<{{.}}>", "<{7 seven}>", struct { + a int + b string + }{7, "seven"}, true}, + + // Variables. + {"$ int", "{{$}}", "123", 123, true}, + {"$.I", "{{$.I}}", "17", tVal, true}, + {"$.U.V", "{{$.U.V}}", "v", tVal, true}, + {"declare in action", "{{$x := $.U.V}}{{$x}}", "v", tVal, true}, + + // Type with String method. + {"V{6666}.String()", "-{{.V0}}-", "-<6666>-", tVal, true}, + {"&V{7777}.String()", "-{{.V1}}-", "-<7777>-", tVal, true}, + {"(*V)(nil).String()", "-{{.V2}}-", "-nilV-", tVal, true}, + + // Type with Error method. + {"W{888}.Error()", "-{{.W0}}-", "-[888]-", tVal, true}, + {"&W{999}.Error()", "-{{.W1}}-", "-[999]-", tVal, true}, + {"(*W)(nil).Error()", "-{{.W2}}-", "-nilW-", tVal, true}, + + // Pointers. + {"*int", "{{.PI}}", "23", tVal, true}, + {"*string", "{{.PS}}", "a string", tVal, true}, + {"*[]int", "{{.PSI}}", "[21 22 23]", tVal, true}, + {"*[]int[1]", "{{index .PSI 1}}", "22", tVal, true}, + {"NIL", "{{.NIL}}", "", tVal, true}, + + // Empty interfaces holding values. + {"empty nil", "{{.Empty0}}", "", tVal, true}, + {"empty with int", "{{.Empty1}}", "3", tVal, true}, + {"empty with string", "{{.Empty2}}", "empty2", tVal, true}, + {"empty with slice", "{{.Empty3}}", "[7 8]", tVal, true}, + {"empty with struct", "{{.Empty4}}", "{UinEmpty}", tVal, true}, + {"empty with struct, field", "{{.Empty4.V}}", "UinEmpty", tVal, true}, + + // Method calls. + {".Method0", "-{{.Method0}}-", "-M0-", tVal, true}, + {".Method1(1234)", "-{{.Method1 1234}}-", "-1234-", tVal, true}, + {".Method1(.I)", "-{{.Method1 .I}}-", "-17-", tVal, true}, + {".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true}, + {".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true}, + {".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true}, + {".Method3(nil constant)", "-{{.Method3 nil}}-", "-Method3: -", tVal, true}, + {".Method3(nil value)", "-{{.Method3 .MXI.unset}}-", "-Method3: -", tVal, true}, + {"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true}, + {"method on chained var", + "{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}", + "true", tVal, true}, + {"chained method", + "{{range .MSIone}}{{if $.GetU.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}", + "true", tVal, true}, + {"chained method on variable", + "{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}", + "true", tVal, true}, + {".NilOKFunc not nil", "{{call .NilOKFunc .PI}}", "false", tVal, true}, + {".NilOKFunc nil", "{{call .NilOKFunc nil}}", "true", tVal, true}, + + // Function call builtin. + {".BinaryFunc", "{{call .BinaryFunc `1` `2`}}", "[1=2]", tVal, true}, + {".VariadicFunc0", "{{call .VariadicFunc}}", "<>", tVal, true}, + {".VariadicFunc2", "{{call .VariadicFunc `he` `llo`}}", "", tVal, true}, + {".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=", tVal, true}, + {"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true}, + {"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true}, + {"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true}, + {".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true}, + + // Erroneous function calls (check args). + {".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false}, + {".BinaryFuncTooMany", "{{call .BinaryFunc `1` `2` `3`}}", "", tVal, false}, + {".BinaryFuncBad0", "{{call .BinaryFunc 1 3}}", "", tVal, false}, + {".BinaryFuncBad1", "{{call .BinaryFunc `1` 3}}", "", tVal, false}, + {".VariadicFuncBad0", "{{call .VariadicFunc 3}}", "", tVal, false}, + {".VariadicFuncIntBad0", "{{call .VariadicFuncInt}}", "", tVal, false}, + {".VariadicFuncIntBad`", "{{call .VariadicFuncInt `x`}}", "", tVal, false}, + {".VariadicFuncNilBad", "{{call .VariadicFunc nil}}", "", tVal, false}, + + // Pipelines. + {"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true}, + {"pipeline func", "-{{call .VariadicFunc `llo` | call .VariadicFunc `he` }}-", "->-", tVal, true}, + + // Parenthesized expressions + {"parens in pipeline", "{{printf `%d %d %d` (1) (2 | add 3) (add 4 (add 5 6))}}", "1 5 15", tVal, true}, + + // Parenthesized expressions with field accesses + {"parens: $ in paren", "{{($).X}}", "x", tVal, true}, + {"parens: $.GetU in paren", "{{($.GetU).V}}", "v", tVal, true}, + {"parens: $ in paren in pipe", "{{($ | echo).X}}", "x", tVal, true}, + {"parens: spaces and args", `{{(makemap "up" "down" "left" "right").left}}`, "right", tVal, true}, + + // If. + {"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true}, + {"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true}, + {"if nil", "{{if nil}}TRUE{{end}}", "", tVal, false}, + {"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true}, + {"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, + {"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true}, + {"if 0.0", "{{if .FloatZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, + {"if 1.5i", "{{if 1.5i}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true}, + {"if 0.0i", "{{if .ComplexZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, + {"if emptystring", "{{if ``}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"if string", "{{if `notempty`}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true}, + {"if emptyslice", "{{if .SIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"if slice", "{{if .SI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true}, + {"if emptymap", "{{if .MSIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"if map", "{{if .MSI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true}, + {"if map unset", "{{if .MXI.none}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, + {"if map not unset", "{{if not .MXI.none}}ZERO{{else}}NON-ZERO{{end}}", "ZERO", tVal, true}, + {"if $x with $y int", "{{if $x := true}}{{with $y := .I}}{{$x}},{{$y}}{{end}}{{end}}", "true,17", tVal, true}, + {"if $x with $x int", "{{if $x := true}}{{with $x := .I}}{{$x}},{{end}}{{$x}}{{end}}", "17,true", tVal, true}, + {"if else if", "{{if false}}FALSE{{else if true}}TRUE{{end}}", "TRUE", tVal, true}, + {"if else chain", "{{if eq 1 3}}1{{else if eq 2 3}}2{{else if eq 3 3}}3{{end}}", "3", tVal, true}, + + // Print etc. + {"print", `{{print "hello, print"}}`, "hello, print", tVal, true}, + {"print 123", `{{print 1 2 3}}`, "1 2 3", tVal, true}, + {"print nil", `{{print nil}}`, "", tVal, true}, + {"println", `{{println 1 2 3}}`, "1 2 3\n", tVal, true}, + {"printf int", `{{printf "%04x" 127}}`, "007f", tVal, true}, + {"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true}, + {"printf complex", `{{printf "%g" 1+7i}}`, "(1+7i)", tVal, true}, + {"printf string", `{{printf "%s" "hello"}}`, "hello", tVal, true}, + {"printf function", `{{printf "%#q" zeroArgs}}`, "`zeroArgs`", tVal, true}, + {"printf field", `{{printf "%s" .U.V}}`, "v", tVal, true}, + {"printf method", `{{printf "%s" .Method0}}`, "M0", tVal, true}, + {"printf dot", `{{with .I}}{{printf "%d" .}}{{end}}`, "17", tVal, true}, + {"printf var", `{{with $x := .I}}{{printf "%d" $x}}{{end}}`, "17", tVal, true}, + {"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) M0", tVal, true}, + + // HTML. + {"html", `{{html ""}}`, + "<script>alert("XSS");</script>", nil, true}, + {"html pipeline", `{{printf "" | html}}`, + "<script>alert("XSS");</script>", nil, true}, + {"html", `{{html .PS}}`, "a string", tVal, true}, + + // JavaScript. + {"js", `{{js .}}`, `It\'d be nice.`, `It'd be nice.`, true}, + + // URL query. + {"urlquery", `{{"http://www.example.org/"|urlquery}}`, "http%3A%2F%2Fwww.example.org%2F", nil, true}, + + // Booleans + {"not", "{{not true}} {{not false}}", "false true", nil, true}, + {"and", "{{and false 0}} {{and 1 0}} {{and 0 true}} {{and 1 1}}", "false 0 0 1", nil, true}, + {"or", "{{or 0 0}} {{or 1 0}} {{or 0 true}} {{or 1 1}}", "0 1 true 1", nil, true}, + {"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true}, + {"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, + + // Indexing. + {"slice[0]", "{{index .SI 0}}", "3", tVal, true}, + {"slice[1]", "{{index .SI 1}}", "4", tVal, true}, + {"slice[HUGE]", "{{index .SI 10}}", "", tVal, false}, + {"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false}, + {"map[one]", "{{index .MSI `one`}}", "1", tVal, true}, + {"map[two]", "{{index .MSI `two`}}", "2", tVal, true}, + {"map[NO]", "{{index .MSI `XXX`}}", "0", tVal, true}, + {"map[nil]", "{{index .MSI nil}}", "0", tVal, true}, + {"map[WRONG]", "{{index .MSI 10}}", "", tVal, false}, + {"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true}, + + // Len. + {"slice", "{{len .SI}}", "3", tVal, true}, + {"map", "{{len .MSI }}", "3", tVal, true}, + {"len of int", "{{len 3}}", "", tVal, false}, + {"len of nothing", "{{len .Empty0}}", "", tVal, false}, + + // With. + {"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true}, + {"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true}, + {"with 1", "{{with 1}}{{.}}{{else}}ZERO{{end}}", "1", tVal, true}, + {"with 0", "{{with 0}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true}, + {"with 1.5", "{{with 1.5}}{{.}}{{else}}ZERO{{end}}", "1.5", tVal, true}, + {"with 0.0", "{{with .FloatZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true}, + {"with 1.5i", "{{with 1.5i}}{{.}}{{else}}ZERO{{end}}", "(0+1.5i)", tVal, true}, + {"with 0.0i", "{{with .ComplexZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true}, + {"with emptystring", "{{with ``}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"with string", "{{with `notempty`}}{{.}}{{else}}EMPTY{{end}}", "notempty", tVal, true}, + {"with emptyslice", "{{with .SIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"with slice", "{{with .SI}}{{.}}{{else}}EMPTY{{end}}", "[3 4 5]", tVal, true}, + {"with emptymap", "{{with .MSIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"with map", "{{with .MSIone}}{{.}}{{else}}EMPTY{{end}}", "map[one:1]", tVal, true}, + {"with empty interface, struct field", "{{with .Empty4}}{{.V}}{{end}}", "UinEmpty", tVal, true}, + {"with $x int", "{{with $x := .I}}{{$x}}{{end}}", "17", tVal, true}, + {"with $x struct.U.V", "{{with $x := $}}{{$x.U.V}}{{end}}", "v", tVal, true}, + {"with variable and action", "{{with $x := $}}{{$y := $.U.V}}{{$y}}{{end}}", "v", tVal, true}, + + // Range. + {"range []int", "{{range .SI}}-{{.}}-{{end}}", "-3--4--5-", tVal, true}, + {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true}, + {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, + {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true}, + {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true}, + {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true}, + {"range empty map no else", "{{range .MSIEmpty}}-{{.}}-{{end}}", "", tVal, true}, + {"range map else", "{{range .MSI}}-{{.}}-{{else}}EMPTY{{end}}", "-1--3--2-", tVal, true}, + {"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, + {"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true}, + {"range empty nil", "{{range .Empty0}}-{{.}}-{{end}}", "", tVal, true}, + {"range $x SI", "{{range $x := .SI}}<{{$x}}>{{end}}", "<3><4><5>", tVal, true}, + {"range $x $y SI", "{{range $x, $y := .SI}}<{{$x}}={{$y}}>{{end}}", "<0=3><1=4><2=5>", tVal, true}, + {"range $x MSIone", "{{range $x := .MSIone}}<{{$x}}>{{end}}", "<1>", tVal, true}, + {"range $x $y MSIone", "{{range $x, $y := .MSIone}}<{{$x}}={{$y}}>{{end}}", "", tVal, true}, + {"range $x PSI", "{{range $x := .PSI}}<{{$x}}>{{end}}", "<21><22><23>", tVal, true}, + {"declare in range", "{{range $x := .PSI}}<{{$foo:=$x}}{{$x}}>{{end}}", "<21><22><23>", tVal, true}, + {"range count", `{{range $i, $x := count 5}}[{{$i}}]{{$x}}{{end}}`, "[0]a[1]b[2]c[3]d[4]e", tVal, true}, + {"range nil count", `{{range $i, $x := count 0}}{{else}}empty{{end}}`, "empty", tVal, true}, + + // Cute examples. + {"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true}, + {"or as if false", `{{or .SIEmpty "slice is empty"}}`, "slice is empty", tVal, true}, + + // Error handling. + {"error method, error", "{{.MyError true}}", "", tVal, false}, + {"error method, no error", "{{.MyError false}}", "false", tVal, true}, + + // Fixed bugs. + // Must separate dot and receiver; otherwise args are evaluated with dot set to variable. + {"bug0", "{{range .MSIone}}{{if $.Method1 .}}X{{end}}{{end}}", "X", tVal, true}, + // Do not loop endlessly in indirect for non-empty interfaces. + // The bug appears with *interface only; looped forever. + {"bug1", "{{.Method0}}", "M0", &iVal, true}, + // Was taking address of interface field, so method set was empty. + {"bug2", "{{$.NonEmptyInterface.Method0}}", "M0", tVal, true}, + // Struct values were not legal in with - mere oversight. + {"bug3", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true}, + // Nil interface values in if. + {"bug4", "{{if .Empty0}}non-nil{{else}}nil{{end}}", "nil", tVal, true}, + // Stringer. + {"bug5", "{{.Str}}", "foozle", tVal, true}, + {"bug5a", "{{.Err}}", "erroozle", tVal, true}, + // Args need to be indirected and dereferenced sometimes. + {"bug6a", "{{vfunc .V0 .V1}}", "vfunc", tVal, true}, + {"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true}, + {"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true}, + {"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true}, + // Legal parse but illegal execution: non-function should have no arguments. + {"bug7a", "{{3 2}}", "", tVal, false}, + {"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false}, + {"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false}, + // Pipelined arg was not being type-checked. + {"bug8a", "{{3|oneArg}}", "", tVal, false}, + {"bug8b", "{{4|dddArg 3}}", "", tVal, false}, + // A bug was introduced that broke map lookups for lower-case names. + {"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true}, + // Field chain starting with function did not work. + {"bug10", "{{mapOfThree.three}}-{{(mapOfThree).three}}", "3-3", 0, true}, + // Dereferencing nil pointer while evaluating function arguments should not panic. Issue 7333. + {"bug11", "{{valueString .PS}}", "", T{}, false}, + // 0xef gave constant type float64. Issue 8622. + {"bug12xe", "{{printf `%T` 0xef}}", "int", T{}, true}, + {"bug12xE", "{{printf `%T` 0xEE}}", "int", T{}, true}, + {"bug12Xe", "{{printf `%T` 0Xef}}", "int", T{}, true}, + {"bug12XE", "{{printf `%T` 0XEE}}", "int", T{}, true}, + // Chained nodes did not work as arguments. Issue 8473. + {"bug13", "{{print (.Copy).I}}", "17", tVal, true}, +} + +func zeroArgs() string { + return "zeroArgs" +} + +func oneArg(a string) string { + return "oneArg=" + a +} + +func dddArg(a int, b ...string) string { + return fmt.Sprintln(a, b) +} + +// count returns a channel that will deliver n sequential 1-letter strings starting at "a" +func count(n int) chan string { + if n == 0 { + return nil + } + c := make(chan string) + go func() { + for i := 0; i < n; i++ { + c <- "abcdefghijklmnop"[i : i+1] + } + close(c) + }() + return c +} + +// vfunc takes a *V and a V +func vfunc(V, *V) string { + return "vfunc" +} + +// valueString takes a string, not a pointer. +func valueString(v string) string { + return "value is ignored" +} + +func add(args ...int) int { + sum := 0 + for _, x := range args { + sum += x + } + return sum +} + +func echo(arg interface{}) interface{} { + return arg +} + +func makemap(arg ...string) map[string]string { + if len(arg)%2 != 0 { + panic("bad makemap") + } + m := make(map[string]string) + for i := 0; i < len(arg); i += 2 { + m[arg[i]] = arg[i+1] + } + return m +} + +func stringer(s fmt.Stringer) string { + return s.String() +} + +func mapOfThree() interface{} { + return map[string]int{"three": 3} +} + +func testExecute(execTests []execTest, template *Template, t *testing.T) { + b := new(bytes.Buffer) + funcs := FuncMap{ + "add": add, + "count": count, + "dddArg": dddArg, + "echo": echo, + "makemap": makemap, + "mapOfThree": mapOfThree, + "oneArg": oneArg, + "stringer": stringer, + "typeOf": typeOf, + "valueString": valueString, + "vfunc": vfunc, + "zeroArgs": zeroArgs, + } + for _, test := range execTests { + var tmpl *Template + var err error + if template == nil { + tmpl, err = New(test.name).Funcs(funcs).Parse(test.input) + } else { + tmpl, err = template.New(test.name).Funcs(funcs).Parse(test.input) + } + if err != nil { + t.Errorf("%s: parse error: %s", test.name, err) + continue + } + b.Reset() + err = tmpl.Execute(b, test.data) + switch { + case !test.ok && err == nil: + t.Errorf("%s: expected error; got none", test.name) + continue + case test.ok && err != nil: + t.Errorf("%s: unexpected execute error: %s", test.name, err) + continue + case !test.ok && err != nil: + // expected error, got one + if *debug { + fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err) + } + } + result := b.String() + if result != test.output { + t.Errorf("%s: expected\n\t%q\ngot\n\t%q", test.name, test.output, result) + } + } +} + +func TestExecute(t *testing.T) { + testExecute(execTests, nil, t) +} + +var delimPairs = []string{ + "", "", // default + "{{", "}}", // same as default + "<<", ">>", // distinct + "|", "|", // same + "(日)", "(本)", // peculiar +} + +func TestDelims(t *testing.T) { + const hello = "Hello, world" + var value = struct{ Str string }{hello} + for i := 0; i < len(delimPairs); i += 2 { + text := ".Str" + left := delimPairs[i+0] + trueLeft := left + right := delimPairs[i+1] + trueRight := right + if left == "" { // default case + trueLeft = "{{" + } + if right == "" { // default case + trueRight = "}}" + } + text = trueLeft + text + trueRight + // Now add a comment + text += trueLeft + "/*comment*/" + trueRight + // Now add an action containing a string. + text += trueLeft + `"` + trueLeft + `"` + trueRight + // At this point text looks like `{{.Str}}{{/*comment*/}}{{"{{"}}`. + tmpl, err := New("delims").Delims(left, right).Parse(text) + if err != nil { + t.Fatalf("delim %q text %q parse err %s", left, text, err) + } + var b = new(bytes.Buffer) + err = tmpl.Execute(b, value) + if err != nil { + t.Fatalf("delim %q exec err %s", left, err) + } + if b.String() != hello+trueLeft { + t.Errorf("expected %q got %q", hello+trueLeft, b.String()) + } + } +} + +// Check that an error from a method flows back to the top. +func TestExecuteError(t *testing.T) { + b := new(bytes.Buffer) + tmpl := New("error") + _, err := tmpl.Parse("{{.MyError true}}") + if err != nil { + t.Fatalf("parse error: %s", err) + } + err = tmpl.Execute(b, tVal) + if err == nil { + t.Errorf("expected error; got none") + } else if !strings.Contains(err.Error(), myError.Error()) { + if *debug { + fmt.Printf("test execute error: %s\n", err) + } + t.Errorf("expected myError; got %s", err) + } +} + +const execErrorText = `line 1 +line 2 +line 3 +{{template "one" .}} +{{define "one"}}{{template "two" .}}{{end}} +{{define "two"}}{{template "three" .}}{{end}} +{{define "three"}}{{index "hi" $}}{{end}}` + +// Check that an error from a nested template contains all the relevant information. +func TestExecError(t *testing.T) { + tmpl, err := New("top").Parse(execErrorText) + if err != nil { + t.Fatal("parse error:", err) + } + var b bytes.Buffer + err = tmpl.Execute(&b, 5) // 5 is out of range indexing "hi" + if err == nil { + t.Fatal("expected error") + } + const want = `template: top:7:20: executing "three" at : error calling index: index out of range: 5` + got := err.Error() + if got != want { + t.Errorf("expected\n%q\ngot\n%q", want, got) + } +} + +func TestJSEscaping(t *testing.T) { + testCases := []struct { + in, exp string + }{ + {`a`, `a`}, + {`'foo`, `\'foo`}, + {`Go "jump" \`, `Go \"jump\" \\`}, + {`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`}, + {"unprintable \uFDFF", `unprintable \uFDFF`}, + {``, `\x3Chtml\x3E`}, + } + for _, tc := range testCases { + s := JSEscapeString(tc.in) + if s != tc.exp { + t.Errorf("JS escaping [%s] got [%s] want [%s]", tc.in, s, tc.exp) + } + } +} + +// A nice example: walk a binary tree. + +type Tree struct { + Val int + Left, Right *Tree +} + +// Use different delimiters to test Set.Delims. +const treeTemplate = ` + (define "tree") + [ + (.Val) + (with .Left) + (template "tree" .) + (end) + (with .Right) + (template "tree" .) + (end) + ] + (end) +` + +func TestTree(t *testing.T) { + var tree = &Tree{ + 1, + &Tree{ + 2, &Tree{ + 3, + &Tree{ + 4, nil, nil, + }, + nil, + }, + &Tree{ + 5, + &Tree{ + 6, nil, nil, + }, + nil, + }, + }, + &Tree{ + 7, + &Tree{ + 8, + &Tree{ + 9, nil, nil, + }, + nil, + }, + &Tree{ + 10, + &Tree{ + 11, nil, nil, + }, + nil, + }, + }, + } + tmpl, err := New("root").Delims("(", ")").Parse(treeTemplate) + if err != nil { + t.Fatal("parse error:", err) + } + var b bytes.Buffer + stripSpace := func(r rune) rune { + if r == '\t' || r == '\n' { + return -1 + } + return r + } + const expect = "[1[2[3[4]][5[6]]][7[8[9]][10[11]]]]" + // First by looking up the template. + err = tmpl.Lookup("tree").Execute(&b, tree) + if err != nil { + t.Fatal("exec error:", err) + } + result := strings.Map(stripSpace, b.String()) + if result != expect { + t.Errorf("expected %q got %q", expect, result) + } + // Then direct to execution. + b.Reset() + err = tmpl.ExecuteTemplate(&b, "tree", tree) + if err != nil { + t.Fatal("exec error:", err) + } + result = strings.Map(stripSpace, b.String()) + if result != expect { + t.Errorf("expected %q got %q", expect, result) + } +} + +func TestExecuteOnNewTemplate(t *testing.T) { + // This is issue 3872. + _ = New("Name").Templates() +} + +const testTemplates = `{{define "one"}}one{{end}}{{define "two"}}two{{end}}` + +func TestMessageForExecuteEmpty(t *testing.T) { + // Test a truly empty template. + tmpl := New("empty") + var b bytes.Buffer + err := tmpl.Execute(&b, 0) + if err == nil { + t.Fatal("expected initial error") + } + got := err.Error() + want := `template: empty: "empty" is an incomplete or empty template` + if got != want { + t.Errorf("expected error %s got %s", want, got) + } + // Add a non-empty template to check that the error is helpful. + tests, err := New("").Parse(testTemplates) + if err != nil { + t.Fatal(err) + } + tmpl.AddParseTree("secondary", tests.Tree) + err = tmpl.Execute(&b, 0) + if err == nil { + t.Fatal("expected second error") + } + got = err.Error() + want = `template: empty: "empty" is an incomplete or empty template; defined templates are: "secondary"` + if got != want { + t.Errorf("expected error %s got %s", want, got) + } + // Make sure we can execute the secondary. + err = tmpl.ExecuteTemplate(&b, "secondary", 0) + if err != nil { + t.Fatal(err) + } +} + +func TestFinalForPrintf(t *testing.T) { + tmpl, err := New("").Parse(`{{"x" | printf}}`) + if err != nil { + t.Fatal(err) + } + var b bytes.Buffer + err = tmpl.Execute(&b, 0) + if err != nil { + t.Fatal(err) + } +} + +type cmpTest struct { + expr string + truth string + ok bool +} + +var cmpTests = []cmpTest{ + {"eq true true", "true", true}, + {"eq true false", "false", true}, + {"eq 1+2i 1+2i", "true", true}, + {"eq 1+2i 1+3i", "false", true}, + {"eq 1.5 1.5", "true", true}, + {"eq 1.5 2.5", "false", true}, + {"eq 1 1", "true", true}, + {"eq 1 2", "false", true}, + {"eq `xy` `xy`", "true", true}, + {"eq `xy` `xyz`", "false", true}, + {"eq .Uthree .Uthree", "true", true}, + {"eq .Uthree .Ufour", "false", true}, + {"eq 3 4 5 6 3", "true", true}, + {"eq 3 4 5 6 7", "false", true}, + {"ne true true", "false", true}, + {"ne true false", "true", true}, + {"ne 1+2i 1+2i", "false", true}, + {"ne 1+2i 1+3i", "true", true}, + {"ne 1.5 1.5", "false", true}, + {"ne 1.5 2.5", "true", true}, + {"ne 1 1", "false", true}, + {"ne 1 2", "true", true}, + {"ne `xy` `xy`", "false", true}, + {"ne `xy` `xyz`", "true", true}, + {"ne .Uthree .Uthree", "false", true}, + {"ne .Uthree .Ufour", "true", true}, + {"lt 1.5 1.5", "false", true}, + {"lt 1.5 2.5", "true", true}, + {"lt 1 1", "false", true}, + {"lt 1 2", "true", true}, + {"lt `xy` `xy`", "false", true}, + {"lt `xy` `xyz`", "true", true}, + {"lt .Uthree .Uthree", "false", true}, + {"lt .Uthree .Ufour", "true", true}, + {"le 1.5 1.5", "true", true}, + {"le 1.5 2.5", "true", true}, + {"le 2.5 1.5", "false", true}, + {"le 1 1", "true", true}, + {"le 1 2", "true", true}, + {"le 2 1", "false", true}, + {"le `xy` `xy`", "true", true}, + {"le `xy` `xyz`", "true", true}, + {"le `xyz` `xy`", "false", true}, + {"le .Uthree .Uthree", "true", true}, + {"le .Uthree .Ufour", "true", true}, + {"le .Ufour .Uthree", "false", true}, + {"gt 1.5 1.5", "false", true}, + {"gt 1.5 2.5", "false", true}, + {"gt 1 1", "false", true}, + {"gt 2 1", "true", true}, + {"gt 1 2", "false", true}, + {"gt `xy` `xy`", "false", true}, + {"gt `xy` `xyz`", "false", true}, + {"gt .Uthree .Uthree", "false", true}, + {"gt .Uthree .Ufour", "false", true}, + {"gt .Ufour .Uthree", "true", true}, + {"ge 1.5 1.5", "true", true}, + {"ge 1.5 2.5", "false", true}, + {"ge 2.5 1.5", "true", true}, + {"ge 1 1", "true", true}, + {"ge 1 2", "false", true}, + {"ge 2 1", "true", true}, + {"ge `xy` `xy`", "true", true}, + {"ge `xy` `xyz`", "false", true}, + {"ge `xyz` `xy`", "true", true}, + {"ge .Uthree .Uthree", "true", true}, + {"ge .Uthree .Ufour", "false", true}, + {"ge .Ufour .Uthree", "true", true}, + // Mixing signed and unsigned integers. + {"eq .Uthree .Three", "true", true}, + {"eq .Three .Uthree", "true", true}, + {"le .Uthree .Three", "true", true}, + {"le .Three .Uthree", "true", true}, + {"ge .Uthree .Three", "true", true}, + {"ge .Three .Uthree", "true", true}, + {"lt .Uthree .Three", "false", true}, + {"lt .Three .Uthree", "false", true}, + {"gt .Uthree .Three", "false", true}, + {"gt .Three .Uthree", "false", true}, + {"eq .Ufour .Three", "false", true}, + {"lt .Ufour .Three", "false", true}, + {"gt .Ufour .Three", "true", true}, + {"eq .NegOne .Uthree", "false", true}, + {"eq .Uthree .NegOne", "false", true}, + {"ne .NegOne .Uthree", "true", true}, + {"ne .Uthree .NegOne", "true", true}, + {"lt .NegOne .Uthree", "true", true}, + {"lt .Uthree .NegOne", "false", true}, + {"le .NegOne .Uthree", "true", true}, + {"le .Uthree .NegOne", "false", true}, + {"gt .NegOne .Uthree", "false", true}, + {"gt .Uthree .NegOne", "true", true}, + {"ge .NegOne .Uthree", "false", true}, + {"ge .Uthree .NegOne", "true", true}, + {"eq (index `x` 0) 'x'", "true", true}, // The example that triggered this rule. + {"eq (index `x` 0) 'y'", "false", true}, + // Errors + {"eq `xy` 1", "", false}, // Different types. + {"eq 2 2.0", "", false}, // Different types. + {"lt true true", "", false}, // Unordered types. + {"lt 1+0i 1+0i", "", false}, // Unordered types. +} + +func TestComparison(t *testing.T) { + b := new(bytes.Buffer) + var cmpStruct = struct { + Uthree, Ufour uint + NegOne, Three int + }{3, 4, -1, 3} + for _, test := range cmpTests { + text := fmt.Sprintf("{{if %s}}true{{else}}false{{end}}", test.expr) + tmpl, err := New("empty").Parse(text) + if err != nil { + t.Fatalf("%q: %s", test.expr, err) + } + b.Reset() + err = tmpl.Execute(b, &cmpStruct) + if test.ok && err != nil { + t.Errorf("%s errored incorrectly: %s", test.expr, err) + continue + } + if !test.ok && err == nil { + t.Errorf("%s did not error", test.expr) + continue + } + if b.String() != test.truth { + t.Errorf("%s: want %s; got %s", test.expr, test.truth, b.String()) + } + } +} diff --git a/vendor/github.com/alecthomas/template/funcs.go b/vendor/github.com/alecthomas/template/funcs.go new file mode 100644 index 0000000..39ee5ed --- /dev/null +++ b/vendor/github.com/alecthomas/template/funcs.go @@ -0,0 +1,598 @@ +// 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. + +package template + +import ( + "bytes" + "errors" + "fmt" + "io" + "net/url" + "reflect" + "strings" + "unicode" + "unicode/utf8" +) + +// FuncMap is the type of the map defining the mapping from names to functions. +// Each function must have either a single return value, or two return values of +// which the second has type error. In that case, if the second (error) +// return value evaluates to non-nil during execution, execution terminates and +// Execute returns that error. +type FuncMap map[string]interface{} + +var builtins = FuncMap{ + "and": and, + "call": call, + "html": HTMLEscaper, + "index": index, + "js": JSEscaper, + "len": length, + "not": not, + "or": or, + "print": fmt.Sprint, + "printf": fmt.Sprintf, + "println": fmt.Sprintln, + "urlquery": URLQueryEscaper, + + // Comparisons + "eq": eq, // == + "ge": ge, // >= + "gt": gt, // > + "le": le, // <= + "lt": lt, // < + "ne": ne, // != +} + +var builtinFuncs = createValueFuncs(builtins) + +// createValueFuncs turns a FuncMap into a map[string]reflect.Value +func createValueFuncs(funcMap FuncMap) map[string]reflect.Value { + m := make(map[string]reflect.Value) + addValueFuncs(m, funcMap) + return m +} + +// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values. +func addValueFuncs(out map[string]reflect.Value, in FuncMap) { + for name, fn := range in { + v := reflect.ValueOf(fn) + if v.Kind() != reflect.Func { + panic("value for " + name + " not a function") + } + if !goodFunc(v.Type()) { + panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut())) + } + out[name] = v + } +} + +// addFuncs adds to values the functions in funcs. It does no checking of the input - +// call addValueFuncs first. +func addFuncs(out, in FuncMap) { + for name, fn := range in { + out[name] = fn + } +} + +// goodFunc checks that the function or method has the right result signature. +func goodFunc(typ reflect.Type) bool { + // We allow functions with 1 result or 2 results where the second is an error. + switch { + case typ.NumOut() == 1: + return true + case typ.NumOut() == 2 && typ.Out(1) == errorType: + return true + } + return false +} + +// findFunction looks for a function in the template, and global map. +func findFunction(name string, tmpl *Template) (reflect.Value, bool) { + if tmpl != nil && tmpl.common != nil { + if fn := tmpl.execFuncs[name]; fn.IsValid() { + return fn, true + } + } + if fn := builtinFuncs[name]; fn.IsValid() { + return fn, true + } + return reflect.Value{}, false +} + +// Indexing. + +// index returns the result of indexing its first argument by the following +// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each +// indexed item must be a map, slice, or array. +func index(item interface{}, indices ...interface{}) (interface{}, error) { + v := reflect.ValueOf(item) + for _, i := range indices { + index := reflect.ValueOf(i) + var isNil bool + if v, isNil = indirect(v); isNil { + return nil, fmt.Errorf("index of nil pointer") + } + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.String: + var x int64 + switch index.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + x = index.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + x = int64(index.Uint()) + default: + return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type()) + } + if x < 0 || x >= int64(v.Len()) { + return nil, fmt.Errorf("index out of range: %d", x) + } + v = v.Index(int(x)) + case reflect.Map: + if !index.IsValid() { + index = reflect.Zero(v.Type().Key()) + } + if !index.Type().AssignableTo(v.Type().Key()) { + return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type()) + } + if x := v.MapIndex(index); x.IsValid() { + v = x + } else { + v = reflect.Zero(v.Type().Elem()) + } + default: + return nil, fmt.Errorf("can't index item of type %s", v.Type()) + } + } + return v.Interface(), nil +} + +// Length + +// length returns the length of the item, with an error if it has no defined length. +func length(item interface{}) (int, error) { + v, isNil := indirect(reflect.ValueOf(item)) + if isNil { + return 0, fmt.Errorf("len of nil pointer") + } + switch v.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String: + return v.Len(), nil + } + return 0, fmt.Errorf("len of type %s", v.Type()) +} + +// Function invocation + +// call returns the result of evaluating the first argument as a function. +// The function must return 1 result, or 2 results, the second of which is an error. +func call(fn interface{}, args ...interface{}) (interface{}, error) { + v := reflect.ValueOf(fn) + typ := v.Type() + if typ.Kind() != reflect.Func { + return nil, fmt.Errorf("non-function of type %s", typ) + } + if !goodFunc(typ) { + return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut()) + } + numIn := typ.NumIn() + var dddType reflect.Type + if typ.IsVariadic() { + if len(args) < numIn-1 { + return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1) + } + dddType = typ.In(numIn - 1).Elem() + } else { + if len(args) != numIn { + return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn) + } + } + argv := make([]reflect.Value, len(args)) + for i, arg := range args { + value := reflect.ValueOf(arg) + // Compute the expected type. Clumsy because of variadics. + var argType reflect.Type + if !typ.IsVariadic() || i < numIn-1 { + argType = typ.In(i) + } else { + argType = dddType + } + if !value.IsValid() && canBeNil(argType) { + value = reflect.Zero(argType) + } + if !value.Type().AssignableTo(argType) { + return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType) + } + argv[i] = value + } + result := v.Call(argv) + if len(result) == 2 && !result[1].IsNil() { + return result[0].Interface(), result[1].Interface().(error) + } + return result[0].Interface(), nil +} + +// Boolean logic. + +func truth(a interface{}) bool { + t, _ := isTrue(reflect.ValueOf(a)) + return t +} + +// and computes the Boolean AND of its arguments, returning +// the first false argument it encounters, or the last argument. +func and(arg0 interface{}, args ...interface{}) interface{} { + if !truth(arg0) { + return arg0 + } + for i := range args { + arg0 = args[i] + if !truth(arg0) { + break + } + } + return arg0 +} + +// or computes the Boolean OR of its arguments, returning +// the first true argument it encounters, or the last argument. +func or(arg0 interface{}, args ...interface{}) interface{} { + if truth(arg0) { + return arg0 + } + for i := range args { + arg0 = args[i] + if truth(arg0) { + break + } + } + return arg0 +} + +// not returns the Boolean negation of its argument. +func not(arg interface{}) (truth bool) { + truth, _ = isTrue(reflect.ValueOf(arg)) + return !truth +} + +// Comparison. + +// TODO: Perhaps allow comparison between signed and unsigned integers. + +var ( + errBadComparisonType = errors.New("invalid type for comparison") + errBadComparison = errors.New("incompatible types for comparison") + errNoComparison = errors.New("missing argument for comparison") +) + +type kind int + +const ( + invalidKind kind = iota + boolKind + complexKind + intKind + floatKind + integerKind + stringKind + uintKind +) + +func basicKind(v reflect.Value) (kind, error) { + switch v.Kind() { + case reflect.Bool: + return boolKind, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return intKind, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return uintKind, nil + case reflect.Float32, reflect.Float64: + return floatKind, nil + case reflect.Complex64, reflect.Complex128: + return complexKind, nil + case reflect.String: + return stringKind, nil + } + return invalidKind, errBadComparisonType +} + +// eq evaluates the comparison a == b || a == c || ... +func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) { + v1 := reflect.ValueOf(arg1) + k1, err := basicKind(v1) + if err != nil { + return false, err + } + if len(arg2) == 0 { + return false, errNoComparison + } + for _, arg := range arg2 { + v2 := reflect.ValueOf(arg) + k2, err := basicKind(v2) + if err != nil { + return false, err + } + truth := false + if k1 != k2 { + // Special case: Can compare integer values regardless of type's sign. + switch { + case k1 == intKind && k2 == uintKind: + truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint() + case k1 == uintKind && k2 == intKind: + truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int()) + default: + return false, errBadComparison + } + } else { + switch k1 { + case boolKind: + truth = v1.Bool() == v2.Bool() + case complexKind: + truth = v1.Complex() == v2.Complex() + case floatKind: + truth = v1.Float() == v2.Float() + case intKind: + truth = v1.Int() == v2.Int() + case stringKind: + truth = v1.String() == v2.String() + case uintKind: + truth = v1.Uint() == v2.Uint() + default: + panic("invalid kind") + } + } + if truth { + return true, nil + } + } + return false, nil +} + +// ne evaluates the comparison a != b. +func ne(arg1, arg2 interface{}) (bool, error) { + // != is the inverse of ==. + equal, err := eq(arg1, arg2) + return !equal, err +} + +// lt evaluates the comparison a < b. +func lt(arg1, arg2 interface{}) (bool, error) { + v1 := reflect.ValueOf(arg1) + k1, err := basicKind(v1) + if err != nil { + return false, err + } + v2 := reflect.ValueOf(arg2) + k2, err := basicKind(v2) + if err != nil { + return false, err + } + truth := false + if k1 != k2 { + // Special case: Can compare integer values regardless of type's sign. + switch { + case k1 == intKind && k2 == uintKind: + truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint() + case k1 == uintKind && k2 == intKind: + truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int()) + default: + return false, errBadComparison + } + } else { + switch k1 { + case boolKind, complexKind: + return false, errBadComparisonType + case floatKind: + truth = v1.Float() < v2.Float() + case intKind: + truth = v1.Int() < v2.Int() + case stringKind: + truth = v1.String() < v2.String() + case uintKind: + truth = v1.Uint() < v2.Uint() + default: + panic("invalid kind") + } + } + return truth, nil +} + +// le evaluates the comparison <= b. +func le(arg1, arg2 interface{}) (bool, error) { + // <= is < or ==. + lessThan, err := lt(arg1, arg2) + if lessThan || err != nil { + return lessThan, err + } + return eq(arg1, arg2) +} + +// gt evaluates the comparison a > b. +func gt(arg1, arg2 interface{}) (bool, error) { + // > is the inverse of <=. + lessOrEqual, err := le(arg1, arg2) + if err != nil { + return false, err + } + return !lessOrEqual, nil +} + +// ge evaluates the comparison a >= b. +func ge(arg1, arg2 interface{}) (bool, error) { + // >= is the inverse of <. + lessThan, err := lt(arg1, arg2) + if err != nil { + return false, err + } + return !lessThan, nil +} + +// HTML escaping. + +var ( + htmlQuot = []byte(""") // shorter than """ + htmlApos = []byte("'") // shorter than "'" and apos was not in HTML until HTML5 + htmlAmp = []byte("&") + htmlLt = []byte("<") + htmlGt = []byte(">") +) + +// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b. +func HTMLEscape(w io.Writer, b []byte) { + last := 0 + for i, c := range b { + var html []byte + switch c { + case '"': + html = htmlQuot + case '\'': + html = htmlApos + case '&': + html = htmlAmp + case '<': + html = htmlLt + case '>': + html = htmlGt + default: + continue + } + w.Write(b[last:i]) + w.Write(html) + last = i + 1 + } + w.Write(b[last:]) +} + +// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s. +func HTMLEscapeString(s string) string { + // Avoid allocation if we can. + if strings.IndexAny(s, `'"&<>`) < 0 { + return s + } + var b bytes.Buffer + HTMLEscape(&b, []byte(s)) + return b.String() +} + +// HTMLEscaper returns the escaped HTML equivalent of the textual +// representation of its arguments. +func HTMLEscaper(args ...interface{}) string { + return HTMLEscapeString(evalArgs(args)) +} + +// JavaScript escaping. + +var ( + jsLowUni = []byte(`\u00`) + hex = []byte("0123456789ABCDEF") + + jsBackslash = []byte(`\\`) + jsApos = []byte(`\'`) + jsQuot = []byte(`\"`) + jsLt = []byte(`\x3C`) + jsGt = []byte(`\x3E`) +) + +// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b. +func JSEscape(w io.Writer, b []byte) { + last := 0 + for i := 0; i < len(b); i++ { + c := b[i] + + if !jsIsSpecial(rune(c)) { + // fast path: nothing to do + continue + } + w.Write(b[last:i]) + + if c < utf8.RuneSelf { + // Quotes, slashes and angle brackets get quoted. + // Control characters get written as \u00XX. + switch c { + case '\\': + w.Write(jsBackslash) + case '\'': + w.Write(jsApos) + case '"': + w.Write(jsQuot) + case '<': + w.Write(jsLt) + case '>': + w.Write(jsGt) + default: + w.Write(jsLowUni) + t, b := c>>4, c&0x0f + w.Write(hex[t : t+1]) + w.Write(hex[b : b+1]) + } + } else { + // Unicode rune. + r, size := utf8.DecodeRune(b[i:]) + if unicode.IsPrint(r) { + w.Write(b[i : i+size]) + } else { + fmt.Fprintf(w, "\\u%04X", r) + } + i += size - 1 + } + last = i + 1 + } + w.Write(b[last:]) +} + +// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s. +func JSEscapeString(s string) string { + // Avoid allocation if we can. + if strings.IndexFunc(s, jsIsSpecial) < 0 { + return s + } + var b bytes.Buffer + JSEscape(&b, []byte(s)) + return b.String() +} + +func jsIsSpecial(r rune) bool { + switch r { + case '\\', '\'', '"', '<', '>': + return true + } + return r < ' ' || utf8.RuneSelf <= r +} + +// JSEscaper returns the escaped JavaScript equivalent of the textual +// representation of its arguments. +func JSEscaper(args ...interface{}) string { + return JSEscapeString(evalArgs(args)) +} + +// URLQueryEscaper returns the escaped value of the textual representation of +// its arguments in a form suitable for embedding in a URL query. +func URLQueryEscaper(args ...interface{}) string { + return url.QueryEscape(evalArgs(args)) +} + +// evalArgs formats the list of arguments into a string. It is therefore equivalent to +// fmt.Sprint(args...) +// except that each argument is indirected (if a pointer), as required, +// using the same rules as the default string evaluation during template +// execution. +func evalArgs(args []interface{}) string { + ok := false + var s string + // Fast path for simple common case. + if len(args) == 1 { + s, ok = args[0].(string) + } + if !ok { + for i, arg := range args { + a, ok := printableValue(reflect.ValueOf(arg)) + if ok { + args[i] = a + } // else left fmt do its thing + } + s = fmt.Sprint(args...) + } + return s +} diff --git a/vendor/github.com/alecthomas/template/helper.go b/vendor/github.com/alecthomas/template/helper.go new file mode 100644 index 0000000..3636fb5 --- /dev/null +++ b/vendor/github.com/alecthomas/template/helper.go @@ -0,0 +1,108 @@ +// 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. + +// Helper functions to make constructing templates easier. + +package template + +import ( + "fmt" + "io/ioutil" + "path/filepath" +) + +// Functions and methods to parse templates. + +// Must is a helper that wraps a call to a function returning (*Template, error) +// and panics if the error is non-nil. It is intended for use in variable +// initializations such as +// var t = template.Must(template.New("name").Parse("text")) +func Must(t *Template, err error) *Template { + if err != nil { + panic(err) + } + return t +} + +// ParseFiles creates a new Template and parses the template definitions from +// the named files. The returned template's name will have the (base) name and +// (parsed) contents of the first file. There must be at least one file. +// If an error occurs, parsing stops and the returned *Template is nil. +func ParseFiles(filenames ...string) (*Template, error) { + return parseFiles(nil, filenames...) +} + +// ParseFiles parses the named files and associates the resulting templates with +// t. If an error occurs, parsing stops and the returned template is nil; +// otherwise it is t. There must be at least one file. +func (t *Template) ParseFiles(filenames ...string) (*Template, error) { + return parseFiles(t, filenames...) +} + +// parseFiles is the helper for the method and function. If the argument +// template is nil, it is created from the first file. +func parseFiles(t *Template, filenames ...string) (*Template, error) { + if len(filenames) == 0 { + // Not really a problem, but be consistent. + return nil, fmt.Errorf("template: no files named in call to ParseFiles") + } + for _, filename := range filenames { + b, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + s := string(b) + name := filepath.Base(filename) + // First template becomes return value if not already defined, + // and we use that one for subsequent New calls to associate + // all the templates together. Also, if this file has the same name + // as t, this file becomes the contents of t, so + // t, err := New(name).Funcs(xxx).ParseFiles(name) + // works. Otherwise we create a new template associated with t. + var tmpl *Template + if t == nil { + t = New(name) + } + if name == t.Name() { + tmpl = t + } else { + tmpl = t.New(name) + } + _, err = tmpl.Parse(s) + if err != nil { + return nil, err + } + } + return t, nil +} + +// ParseGlob creates a new Template and parses the template definitions from the +// files identified by the pattern, which must match at least one file. The +// returned template will have the (base) name and (parsed) contents of the +// first file matched by the pattern. ParseGlob is equivalent to calling +// ParseFiles with the list of files matched by the pattern. +func ParseGlob(pattern string) (*Template, error) { + return parseGlob(nil, pattern) +} + +// ParseGlob parses the template definitions in the files identified by the +// pattern and associates the resulting templates with t. The pattern is +// processed by filepath.Glob and must match at least one file. ParseGlob is +// equivalent to calling t.ParseFiles with the list of files matched by the +// pattern. +func (t *Template) ParseGlob(pattern string) (*Template, error) { + return parseGlob(t, pattern) +} + +// parseGlob is the implementation of the function and method ParseGlob. +func parseGlob(t *Template, pattern string) (*Template, error) { + filenames, err := filepath.Glob(pattern) + if err != nil { + return nil, err + } + if len(filenames) == 0 { + return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern) + } + return parseFiles(t, filenames...) +} diff --git a/vendor/github.com/alecthomas/template/multi_test.go b/vendor/github.com/alecthomas/template/multi_test.go new file mode 100644 index 0000000..8d10362 --- /dev/null +++ b/vendor/github.com/alecthomas/template/multi_test.go @@ -0,0 +1,293 @@ +// 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. + +package template + +// Tests for mulitple-template parsing and execution. + +import ( + "bytes" + "fmt" + "strings" + "testing" + + "github.com/alecthomas/template/parse" +) + +const ( + noError = true + hasError = false +) + +type multiParseTest struct { + name string + input string + ok bool + names []string + results []string +} + +var multiParseTests = []multiParseTest{ + {"empty", "", noError, + nil, + nil}, + {"one", `{{define "foo"}} FOO {{end}}`, noError, + []string{"foo"}, + []string{" FOO "}}, + {"two", `{{define "foo"}} FOO {{end}}{{define "bar"}} BAR {{end}}`, noError, + []string{"foo", "bar"}, + []string{" FOO ", " BAR "}}, + // errors + {"missing end", `{{define "foo"}} FOO `, hasError, + nil, + nil}, + {"malformed name", `{{define "foo}} FOO `, hasError, + nil, + nil}, +} + +func TestMultiParse(t *testing.T) { + for _, test := range multiParseTests { + template, err := New("root").Parse(test.input) + switch { + case err == nil && !test.ok: + t.Errorf("%q: expected error; got none", test.name) + continue + case err != nil && test.ok: + t.Errorf("%q: unexpected error: %v", test.name, err) + continue + case err != nil && !test.ok: + // expected error, got one + if *debug { + fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err) + } + continue + } + if template == nil { + continue + } + if len(template.tmpl) != len(test.names)+1 { // +1 for root + t.Errorf("%s: wrong number of templates; wanted %d got %d", test.name, len(test.names), len(template.tmpl)) + continue + } + for i, name := range test.names { + tmpl, ok := template.tmpl[name] + if !ok { + t.Errorf("%s: can't find template %q", test.name, name) + continue + } + result := tmpl.Root.String() + if result != test.results[i] { + t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.results[i]) + } + } + } +} + +var multiExecTests = []execTest{ + {"empty", "", "", nil, true}, + {"text", "some text", "some text", nil, true}, + {"invoke x", `{{template "x" .SI}}`, "TEXT", tVal, true}, + {"invoke x no args", `{{template "x"}}`, "TEXT", tVal, true}, + {"invoke dot int", `{{template "dot" .I}}`, "17", tVal, true}, + {"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true}, + {"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true}, + {"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true}, + {"variable declared by template", `{{template "nested" $x:=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true}, + + // User-defined function: test argument evaluator. + {"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true}, + {"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true}, +} + +// These strings are also in testdata/*. +const multiText1 = ` + {{define "x"}}TEXT{{end}} + {{define "dotV"}}{{.V}}{{end}} +` + +const multiText2 = ` + {{define "dot"}}{{.}}{{end}} + {{define "nested"}}{{template "dot" .}}{{end}} +` + +func TestMultiExecute(t *testing.T) { + // Declare a couple of templates first. + template, err := New("root").Parse(multiText1) + if err != nil { + t.Fatalf("parse error for 1: %s", err) + } + _, err = template.Parse(multiText2) + if err != nil { + t.Fatalf("parse error for 2: %s", err) + } + testExecute(multiExecTests, template, t) +} + +func TestParseFiles(t *testing.T) { + _, err := ParseFiles("DOES NOT EXIST") + if err == nil { + t.Error("expected error for non-existent file; got none") + } + template := New("root") + _, err = template.ParseFiles("testdata/file1.tmpl", "testdata/file2.tmpl") + if err != nil { + t.Fatalf("error parsing files: %v", err) + } + testExecute(multiExecTests, template, t) +} + +func TestParseGlob(t *testing.T) { + _, err := ParseGlob("DOES NOT EXIST") + if err == nil { + t.Error("expected error for non-existent file; got none") + } + _, err = New("error").ParseGlob("[x") + if err == nil { + t.Error("expected error for bad pattern; got none") + } + template := New("root") + _, err = template.ParseGlob("testdata/file*.tmpl") + if err != nil { + t.Fatalf("error parsing files: %v", err) + } + testExecute(multiExecTests, template, t) +} + +// In these tests, actual content (not just template definitions) comes from the parsed files. + +var templateFileExecTests = []execTest{ + {"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\n\ny\ntemplate2\n\nx\n", 0, true}, +} + +func TestParseFilesWithData(t *testing.T) { + template, err := New("root").ParseFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") + if err != nil { + t.Fatalf("error parsing files: %v", err) + } + testExecute(templateFileExecTests, template, t) +} + +func TestParseGlobWithData(t *testing.T) { + template, err := New("root").ParseGlob("testdata/tmpl*.tmpl") + if err != nil { + t.Fatalf("error parsing files: %v", err) + } + testExecute(templateFileExecTests, template, t) +} + +const ( + cloneText1 = `{{define "a"}}{{template "b"}}{{template "c"}}{{end}}` + cloneText2 = `{{define "b"}}b{{end}}` + cloneText3 = `{{define "c"}}root{{end}}` + cloneText4 = `{{define "c"}}clone{{end}}` +) + +func TestClone(t *testing.T) { + // Create some templates and clone the root. + root, err := New("root").Parse(cloneText1) + if err != nil { + t.Fatal(err) + } + _, err = root.Parse(cloneText2) + if err != nil { + t.Fatal(err) + } + clone := Must(root.Clone()) + // Add variants to both. + _, err = root.Parse(cloneText3) + if err != nil { + t.Fatal(err) + } + _, err = clone.Parse(cloneText4) + if err != nil { + t.Fatal(err) + } + // Verify that the clone is self-consistent. + for k, v := range clone.tmpl { + if k == clone.name && v.tmpl[k] != clone { + t.Error("clone does not contain root") + } + if v != v.tmpl[v.name] { + t.Errorf("clone does not contain self for %q", k) + } + } + // Execute root. + var b bytes.Buffer + err = root.ExecuteTemplate(&b, "a", 0) + if err != nil { + t.Fatal(err) + } + if b.String() != "broot" { + t.Errorf("expected %q got %q", "broot", b.String()) + } + // Execute copy. + b.Reset() + err = clone.ExecuteTemplate(&b, "a", 0) + if err != nil { + t.Fatal(err) + } + if b.String() != "bclone" { + t.Errorf("expected %q got %q", "bclone", b.String()) + } +} + +func TestAddParseTree(t *testing.T) { + // Create some templates. + root, err := New("root").Parse(cloneText1) + if err != nil { + t.Fatal(err) + } + _, err = root.Parse(cloneText2) + if err != nil { + t.Fatal(err) + } + // Add a new parse tree. + tree, err := parse.Parse("cloneText3", cloneText3, "", "", nil, builtins) + if err != nil { + t.Fatal(err) + } + added, err := root.AddParseTree("c", tree["c"]) + // Execute. + var b bytes.Buffer + err = added.ExecuteTemplate(&b, "a", 0) + if err != nil { + t.Fatal(err) + } + if b.String() != "broot" { + t.Errorf("expected %q got %q", "broot", b.String()) + } +} + +// Issue 7032 +func TestAddParseTreeToUnparsedTemplate(t *testing.T) { + master := "{{define \"master\"}}{{end}}" + tmpl := New("master") + tree, err := parse.Parse("master", master, "", "", nil) + if err != nil { + t.Fatalf("unexpected parse err: %v", err) + } + masterTree := tree["master"] + tmpl.AddParseTree("master", masterTree) // used to panic +} + +func TestRedefinition(t *testing.T) { + var tmpl *Template + var err error + if tmpl, err = New("tmpl1").Parse(`{{define "test"}}foo{{end}}`); err != nil { + t.Fatalf("parse 1: %v", err) + } + if _, err = tmpl.Parse(`{{define "test"}}bar{{end}}`); err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "redefinition") { + t.Fatalf("expected redefinition error; got %v", err) + } + if _, err = tmpl.New("tmpl2").Parse(`{{define "test"}}bar{{end}}`); err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "redefinition") { + t.Fatalf("expected redefinition error; got %v", err) + } +} diff --git a/vendor/github.com/alecthomas/template/parse/lex.go b/vendor/github.com/alecthomas/template/parse/lex.go new file mode 100644 index 0000000..55f1c05 --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/lex.go @@ -0,0 +1,556 @@ +// 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. + +package parse + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" +) + +// item represents a token or text string returned from the scanner. +type item struct { + typ itemType // The type of this item. + pos Pos // The starting position, in bytes, of this item in the input string. + val string // The value of this item. +} + +func (i item) String() string { + switch { + case i.typ == itemEOF: + return "EOF" + case i.typ == itemError: + return i.val + case i.typ > itemKeyword: + return fmt.Sprintf("<%s>", i.val) + case len(i.val) > 10: + return fmt.Sprintf("%.10q...", i.val) + } + return fmt.Sprintf("%q", i.val) +} + +// itemType identifies the type of lex items. +type itemType int + +const ( + itemError itemType = iota // error occurred; value is text of error + itemBool // boolean constant + itemChar // printable ASCII character; grab bag for comma etc. + itemCharConstant // character constant + itemComplex // complex constant (1+2i); imaginary is just a number + itemColonEquals // colon-equals (':=') introducing a declaration + itemEOF + itemField // alphanumeric identifier starting with '.' + itemIdentifier // alphanumeric identifier not starting with '.' + itemLeftDelim // left action delimiter + itemLeftParen // '(' inside action + itemNumber // simple number, including imaginary + itemPipe // pipe symbol + itemRawString // raw quoted string (includes quotes) + itemRightDelim // right action delimiter + itemElideNewline // elide newline after right delim + itemRightParen // ')' inside action + itemSpace // run of spaces separating arguments + itemString // quoted string (includes quotes) + itemText // plain text + itemVariable // variable starting with '$', such as '$' or '$1' or '$hello' + // Keywords appear after all the rest. + itemKeyword // used only to delimit the keywords + itemDot // the cursor, spelled '.' + itemDefine // define keyword + itemElse // else keyword + itemEnd // end keyword + itemIf // if keyword + itemNil // the untyped nil constant, easiest to treat as a keyword + itemRange // range keyword + itemTemplate // template keyword + itemWith // with keyword +) + +var key = map[string]itemType{ + ".": itemDot, + "define": itemDefine, + "else": itemElse, + "end": itemEnd, + "if": itemIf, + "range": itemRange, + "nil": itemNil, + "template": itemTemplate, + "with": itemWith, +} + +const eof = -1 + +// stateFn represents the state of the scanner as a function that returns the next state. +type stateFn func(*lexer) stateFn + +// lexer holds the state of the scanner. +type lexer struct { + name string // the name of the input; used only for error reports + input string // the string being scanned + leftDelim string // start of action + rightDelim string // end of action + state stateFn // the next lexing function to enter + pos Pos // current position in the input + start Pos // start position of this item + width Pos // width of last rune read from input + lastPos Pos // position of most recent item returned by nextItem + items chan item // channel of scanned items + parenDepth int // nesting depth of ( ) exprs +} + +// next returns the next rune in the input. +func (l *lexer) next() rune { + if int(l.pos) >= len(l.input) { + l.width = 0 + return eof + } + r, w := utf8.DecodeRuneInString(l.input[l.pos:]) + l.width = Pos(w) + l.pos += l.width + return r +} + +// peek returns but does not consume the next rune in the input. +func (l *lexer) peek() rune { + r := l.next() + l.backup() + return r +} + +// backup steps back one rune. Can only be called once per call of next. +func (l *lexer) backup() { + l.pos -= l.width +} + +// emit passes an item back to the client. +func (l *lexer) emit(t itemType) { + l.items <- item{t, l.start, l.input[l.start:l.pos]} + l.start = l.pos +} + +// ignore skips over the pending input before this point. +func (l *lexer) ignore() { + l.start = l.pos +} + +// accept consumes the next rune if it's from the valid set. +func (l *lexer) accept(valid string) bool { + if strings.IndexRune(valid, l.next()) >= 0 { + return true + } + l.backup() + return false +} + +// acceptRun consumes a run of runes from the valid set. +func (l *lexer) acceptRun(valid string) { + for strings.IndexRune(valid, l.next()) >= 0 { + } + l.backup() +} + +// lineNumber reports which line we're on, based on the position of +// the previous item returned by nextItem. Doing it this way +// means we don't have to worry about peek double counting. +func (l *lexer) lineNumber() int { + return 1 + strings.Count(l.input[:l.lastPos], "\n") +} + +// errorf returns an error token and terminates the scan by passing +// back a nil pointer that will be the next state, terminating l.nextItem. +func (l *lexer) errorf(format string, args ...interface{}) stateFn { + l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} + return nil +} + +// nextItem returns the next item from the input. +func (l *lexer) nextItem() item { + item := <-l.items + l.lastPos = item.pos + return item +} + +// lex creates a new scanner for the input string. +func lex(name, input, left, right string) *lexer { + if left == "" { + left = leftDelim + } + if right == "" { + right = rightDelim + } + l := &lexer{ + name: name, + input: input, + leftDelim: left, + rightDelim: right, + items: make(chan item), + } + go l.run() + return l +} + +// run runs the state machine for the lexer. +func (l *lexer) run() { + for l.state = lexText; l.state != nil; { + l.state = l.state(l) + } +} + +// state functions + +const ( + leftDelim = "{{" + rightDelim = "}}" + leftComment = "/*" + rightComment = "*/" +) + +// lexText scans until an opening action delimiter, "{{". +func lexText(l *lexer) stateFn { + for { + if strings.HasPrefix(l.input[l.pos:], l.leftDelim) { + if l.pos > l.start { + l.emit(itemText) + } + return lexLeftDelim + } + if l.next() == eof { + break + } + } + // Correctly reached EOF. + if l.pos > l.start { + l.emit(itemText) + } + l.emit(itemEOF) + return nil +} + +// lexLeftDelim scans the left delimiter, which is known to be present. +func lexLeftDelim(l *lexer) stateFn { + l.pos += Pos(len(l.leftDelim)) + if strings.HasPrefix(l.input[l.pos:], leftComment) { + return lexComment + } + l.emit(itemLeftDelim) + l.parenDepth = 0 + return lexInsideAction +} + +// lexComment scans a comment. The left comment marker is known to be present. +func lexComment(l *lexer) stateFn { + l.pos += Pos(len(leftComment)) + i := strings.Index(l.input[l.pos:], rightComment) + if i < 0 { + return l.errorf("unclosed comment") + } + l.pos += Pos(i + len(rightComment)) + if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) { + return l.errorf("comment ends before closing delimiter") + + } + l.pos += Pos(len(l.rightDelim)) + l.ignore() + return lexText +} + +// lexRightDelim scans the right delimiter, which is known to be present. +func lexRightDelim(l *lexer) stateFn { + l.pos += Pos(len(l.rightDelim)) + l.emit(itemRightDelim) + if l.peek() == '\\' { + l.pos++ + l.emit(itemElideNewline) + } + return lexText +} + +// lexInsideAction scans the elements inside action delimiters. +func lexInsideAction(l *lexer) stateFn { + // Either number, quoted string, or identifier. + // Spaces separate arguments; runs of spaces turn into itemSpace. + // Pipe symbols separate and are emitted. + if strings.HasPrefix(l.input[l.pos:], l.rightDelim+"\\") || strings.HasPrefix(l.input[l.pos:], l.rightDelim) { + if l.parenDepth == 0 { + return lexRightDelim + } + return l.errorf("unclosed left paren") + } + switch r := l.next(); { + case r == eof || isEndOfLine(r): + return l.errorf("unclosed action") + case isSpace(r): + return lexSpace + case r == ':': + if l.next() != '=' { + return l.errorf("expected :=") + } + l.emit(itemColonEquals) + case r == '|': + l.emit(itemPipe) + case r == '"': + return lexQuote + case r == '`': + return lexRawQuote + case r == '$': + return lexVariable + case r == '\'': + return lexChar + case r == '.': + // special look-ahead for ".field" so we don't break l.backup(). + if l.pos < Pos(len(l.input)) { + r := l.input[l.pos] + if r < '0' || '9' < r { + return lexField + } + } + fallthrough // '.' can start a number. + case r == '+' || r == '-' || ('0' <= r && r <= '9'): + l.backup() + return lexNumber + case isAlphaNumeric(r): + l.backup() + return lexIdentifier + case r == '(': + l.emit(itemLeftParen) + l.parenDepth++ + return lexInsideAction + case r == ')': + l.emit(itemRightParen) + l.parenDepth-- + if l.parenDepth < 0 { + return l.errorf("unexpected right paren %#U", r) + } + return lexInsideAction + case r <= unicode.MaxASCII && unicode.IsPrint(r): + l.emit(itemChar) + return lexInsideAction + default: + return l.errorf("unrecognized character in action: %#U", r) + } + return lexInsideAction +} + +// lexSpace scans a run of space characters. +// One space has already been seen. +func lexSpace(l *lexer) stateFn { + for isSpace(l.peek()) { + l.next() + } + l.emit(itemSpace) + return lexInsideAction +} + +// lexIdentifier scans an alphanumeric. +func lexIdentifier(l *lexer) stateFn { +Loop: + for { + switch r := l.next(); { + case isAlphaNumeric(r): + // absorb. + default: + l.backup() + word := l.input[l.start:l.pos] + if !l.atTerminator() { + return l.errorf("bad character %#U", r) + } + switch { + case key[word] > itemKeyword: + l.emit(key[word]) + case word[0] == '.': + l.emit(itemField) + case word == "true", word == "false": + l.emit(itemBool) + default: + l.emit(itemIdentifier) + } + break Loop + } + } + return lexInsideAction +} + +// lexField scans a field: .Alphanumeric. +// The . has been scanned. +func lexField(l *lexer) stateFn { + return lexFieldOrVariable(l, itemField) +} + +// lexVariable scans a Variable: $Alphanumeric. +// The $ has been scanned. +func lexVariable(l *lexer) stateFn { + if l.atTerminator() { // Nothing interesting follows -> "$". + l.emit(itemVariable) + return lexInsideAction + } + return lexFieldOrVariable(l, itemVariable) +} + +// lexVariable scans a field or variable: [.$]Alphanumeric. +// The . or $ has been scanned. +func lexFieldOrVariable(l *lexer, typ itemType) stateFn { + if l.atTerminator() { // Nothing interesting follows -> "." or "$". + if typ == itemVariable { + l.emit(itemVariable) + } else { + l.emit(itemDot) + } + return lexInsideAction + } + var r rune + for { + r = l.next() + if !isAlphaNumeric(r) { + l.backup() + break + } + } + if !l.atTerminator() { + return l.errorf("bad character %#U", r) + } + l.emit(typ) + return lexInsideAction +} + +// atTerminator reports whether the input is at valid termination character to +// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases +// like "$x+2" not being acceptable without a space, in case we decide one +// day to implement arithmetic. +func (l *lexer) atTerminator() bool { + r := l.peek() + if isSpace(r) || isEndOfLine(r) { + return true + } + switch r { + case eof, '.', ',', '|', ':', ')', '(': + return true + } + // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will + // succeed but should fail) but only in extremely rare cases caused by willfully + // bad choice of delimiter. + if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r { + return true + } + return false +} + +// lexChar scans a character constant. The initial quote is already +// scanned. Syntax checking is done by the parser. +func lexChar(l *lexer) stateFn { +Loop: + for { + switch l.next() { + case '\\': + if r := l.next(); r != eof && r != '\n' { + break + } + fallthrough + case eof, '\n': + return l.errorf("unterminated character constant") + case '\'': + break Loop + } + } + l.emit(itemCharConstant) + return lexInsideAction +} + +// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This +// isn't a perfect number scanner - for instance it accepts "." and "0x0.2" +// and "089" - but when it's wrong the input is invalid and the parser (via +// strconv) will notice. +func lexNumber(l *lexer) stateFn { + if !l.scanNumber() { + return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) + } + if sign := l.peek(); sign == '+' || sign == '-' { + // Complex: 1+2i. No spaces, must end in 'i'. + if !l.scanNumber() || l.input[l.pos-1] != 'i' { + return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) + } + l.emit(itemComplex) + } else { + l.emit(itemNumber) + } + return lexInsideAction +} + +func (l *lexer) scanNumber() bool { + // Optional leading sign. + l.accept("+-") + // Is it hex? + digits := "0123456789" + if l.accept("0") && l.accept("xX") { + digits = "0123456789abcdefABCDEF" + } + l.acceptRun(digits) + if l.accept(".") { + l.acceptRun(digits) + } + if l.accept("eE") { + l.accept("+-") + l.acceptRun("0123456789") + } + // Is it imaginary? + l.accept("i") + // Next thing mustn't be alphanumeric. + if isAlphaNumeric(l.peek()) { + l.next() + return false + } + return true +} + +// lexQuote scans a quoted string. +func lexQuote(l *lexer) stateFn { +Loop: + for { + switch l.next() { + case '\\': + if r := l.next(); r != eof && r != '\n' { + break + } + fallthrough + case eof, '\n': + return l.errorf("unterminated quoted string") + case '"': + break Loop + } + } + l.emit(itemString) + return lexInsideAction +} + +// lexRawQuote scans a raw quoted string. +func lexRawQuote(l *lexer) stateFn { +Loop: + for { + switch l.next() { + case eof, '\n': + return l.errorf("unterminated raw quoted string") + case '`': + break Loop + } + } + l.emit(itemRawString) + return lexInsideAction +} + +// isSpace reports whether r is a space character. +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +// isEndOfLine reports whether r is an end-of-line character. +func isEndOfLine(r rune) bool { + return r == '\r' || r == '\n' +} + +// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. +func isAlphaNumeric(r rune) bool { + return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) +} diff --git a/vendor/github.com/alecthomas/template/parse/lex_test.go b/vendor/github.com/alecthomas/template/parse/lex_test.go new file mode 100644 index 0000000..3b92107 --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/lex_test.go @@ -0,0 +1,468 @@ +// 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. + +package parse + +import ( + "fmt" + "testing" +) + +// Make the types prettyprint. +var itemName = map[itemType]string{ + itemError: "error", + itemBool: "bool", + itemChar: "char", + itemCharConstant: "charconst", + itemComplex: "complex", + itemColonEquals: ":=", + itemEOF: "EOF", + itemField: "field", + itemIdentifier: "identifier", + itemLeftDelim: "left delim", + itemLeftParen: "(", + itemNumber: "number", + itemPipe: "pipe", + itemRawString: "raw string", + itemRightDelim: "right delim", + itemElideNewline: "elide newline", + itemRightParen: ")", + itemSpace: "space", + itemString: "string", + itemVariable: "variable", + + // keywords + itemDot: ".", + itemDefine: "define", + itemElse: "else", + itemIf: "if", + itemEnd: "end", + itemNil: "nil", + itemRange: "range", + itemTemplate: "template", + itemWith: "with", +} + +func (i itemType) String() string { + s := itemName[i] + if s == "" { + return fmt.Sprintf("item%d", int(i)) + } + return s +} + +type lexTest struct { + name string + input string + items []item +} + +var ( + tEOF = item{itemEOF, 0, ""} + tFor = item{itemIdentifier, 0, "for"} + tLeft = item{itemLeftDelim, 0, "{{"} + tLpar = item{itemLeftParen, 0, "("} + tPipe = item{itemPipe, 0, "|"} + tQuote = item{itemString, 0, `"abc \n\t\" "`} + tRange = item{itemRange, 0, "range"} + tRight = item{itemRightDelim, 0, "}}"} + tElideNewline = item{itemElideNewline, 0, "\\"} + tRpar = item{itemRightParen, 0, ")"} + tSpace = item{itemSpace, 0, " "} + raw = "`" + `abc\n\t\" ` + "`" + tRawQuote = item{itemRawString, 0, raw} +) + +var lexTests = []lexTest{ + {"empty", "", []item{tEOF}}, + {"spaces", " \t\n", []item{{itemText, 0, " \t\n"}, tEOF}}, + {"text", `now is the time`, []item{{itemText, 0, "now is the time"}, tEOF}}, + {"elide newline", "{{}}\\", []item{tLeft, tRight, tElideNewline, tEOF}}, + {"text with comment", "hello-{{/* this is a comment */}}-world", []item{ + {itemText, 0, "hello-"}, + {itemText, 0, "-world"}, + tEOF, + }}, + {"punctuation", "{{,@% }}", []item{ + tLeft, + {itemChar, 0, ","}, + {itemChar, 0, "@"}, + {itemChar, 0, "%"}, + tSpace, + tRight, + tEOF, + }}, + {"parens", "{{((3))}}", []item{ + tLeft, + tLpar, + tLpar, + {itemNumber, 0, "3"}, + tRpar, + tRpar, + tRight, + tEOF, + }}, + {"empty action", `{{}}`, []item{tLeft, tRight, tEOF}}, + {"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}}, + {"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}}, + {"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}}, + {"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{ + tLeft, + {itemNumber, 0, "1"}, + tSpace, + {itemNumber, 0, "02"}, + tSpace, + {itemNumber, 0, "0x14"}, + tSpace, + {itemNumber, 0, "-7.2i"}, + tSpace, + {itemNumber, 0, "1e3"}, + tSpace, + {itemNumber, 0, "+1.2e-4"}, + tSpace, + {itemNumber, 0, "4.2i"}, + tSpace, + {itemComplex, 0, "1+2i"}, + tRight, + tEOF, + }}, + {"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{ + tLeft, + {itemCharConstant, 0, `'a'`}, + tSpace, + {itemCharConstant, 0, `'\n'`}, + tSpace, + {itemCharConstant, 0, `'\''`}, + tSpace, + {itemCharConstant, 0, `'\\'`}, + tSpace, + {itemCharConstant, 0, `'\u00FF'`}, + tSpace, + {itemCharConstant, 0, `'\xFF'`}, + tSpace, + {itemCharConstant, 0, `'本'`}, + tRight, + tEOF, + }}, + {"bools", "{{true false}}", []item{ + tLeft, + {itemBool, 0, "true"}, + tSpace, + {itemBool, 0, "false"}, + tRight, + tEOF, + }}, + {"dot", "{{.}}", []item{ + tLeft, + {itemDot, 0, "."}, + tRight, + tEOF, + }}, + {"nil", "{{nil}}", []item{ + tLeft, + {itemNil, 0, "nil"}, + tRight, + tEOF, + }}, + {"dots", "{{.x . .2 .x.y.z}}", []item{ + tLeft, + {itemField, 0, ".x"}, + tSpace, + {itemDot, 0, "."}, + tSpace, + {itemNumber, 0, ".2"}, + tSpace, + {itemField, 0, ".x"}, + {itemField, 0, ".y"}, + {itemField, 0, ".z"}, + tRight, + tEOF, + }}, + {"keywords", "{{range if else end with}}", []item{ + tLeft, + {itemRange, 0, "range"}, + tSpace, + {itemIf, 0, "if"}, + tSpace, + {itemElse, 0, "else"}, + tSpace, + {itemEnd, 0, "end"}, + tSpace, + {itemWith, 0, "with"}, + tRight, + tEOF, + }}, + {"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{ + tLeft, + {itemVariable, 0, "$c"}, + tSpace, + {itemColonEquals, 0, ":="}, + tSpace, + {itemIdentifier, 0, "printf"}, + tSpace, + {itemVariable, 0, "$"}, + tSpace, + {itemVariable, 0, "$hello"}, + tSpace, + {itemVariable, 0, "$23"}, + tSpace, + {itemVariable, 0, "$"}, + tSpace, + {itemVariable, 0, "$var"}, + {itemField, 0, ".Field"}, + tSpace, + {itemField, 0, ".Method"}, + tRight, + tEOF, + }}, + {"variable invocation", "{{$x 23}}", []item{ + tLeft, + {itemVariable, 0, "$x"}, + tSpace, + {itemNumber, 0, "23"}, + tRight, + tEOF, + }}, + {"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{ + {itemText, 0, "intro "}, + tLeft, + {itemIdentifier, 0, "echo"}, + tSpace, + {itemIdentifier, 0, "hi"}, + tSpace, + {itemNumber, 0, "1.2"}, + tSpace, + tPipe, + {itemIdentifier, 0, "noargs"}, + tPipe, + {itemIdentifier, 0, "args"}, + tSpace, + {itemNumber, 0, "1"}, + tSpace, + {itemString, 0, `"hi"`}, + tRight, + {itemText, 0, " outro"}, + tEOF, + }}, + {"declaration", "{{$v := 3}}", []item{ + tLeft, + {itemVariable, 0, "$v"}, + tSpace, + {itemColonEquals, 0, ":="}, + tSpace, + {itemNumber, 0, "3"}, + tRight, + tEOF, + }}, + {"2 declarations", "{{$v , $w := 3}}", []item{ + tLeft, + {itemVariable, 0, "$v"}, + tSpace, + {itemChar, 0, ","}, + tSpace, + {itemVariable, 0, "$w"}, + tSpace, + {itemColonEquals, 0, ":="}, + tSpace, + {itemNumber, 0, "3"}, + tRight, + tEOF, + }}, + {"field of parenthesized expression", "{{(.X).Y}}", []item{ + tLeft, + tLpar, + {itemField, 0, ".X"}, + tRpar, + {itemField, 0, ".Y"}, + tRight, + tEOF, + }}, + // errors + {"badchar", "#{{\x01}}", []item{ + {itemText, 0, "#"}, + tLeft, + {itemError, 0, "unrecognized character in action: U+0001"}, + }}, + {"unclosed action", "{{\n}}", []item{ + tLeft, + {itemError, 0, "unclosed action"}, + }}, + {"EOF in action", "{{range", []item{ + tLeft, + tRange, + {itemError, 0, "unclosed action"}, + }}, + {"unclosed quote", "{{\"\n\"}}", []item{ + tLeft, + {itemError, 0, "unterminated quoted string"}, + }}, + {"unclosed raw quote", "{{`xx\n`}}", []item{ + tLeft, + {itemError, 0, "unterminated raw quoted string"}, + }}, + {"unclosed char constant", "{{'\n}}", []item{ + tLeft, + {itemError, 0, "unterminated character constant"}, + }}, + {"bad number", "{{3k}}", []item{ + tLeft, + {itemError, 0, `bad number syntax: "3k"`}, + }}, + {"unclosed paren", "{{(3}}", []item{ + tLeft, + tLpar, + {itemNumber, 0, "3"}, + {itemError, 0, `unclosed left paren`}, + }}, + {"extra right paren", "{{3)}}", []item{ + tLeft, + {itemNumber, 0, "3"}, + tRpar, + {itemError, 0, `unexpected right paren U+0029 ')'`}, + }}, + + // Fixed bugs + // Many elements in an action blew the lookahead until + // we made lexInsideAction not loop. + {"long pipeline deadlock", "{{|||||}}", []item{ + tLeft, + tPipe, + tPipe, + tPipe, + tPipe, + tPipe, + tRight, + tEOF, + }}, + {"text with bad comment", "hello-{{/*/}}-world", []item{ + {itemText, 0, "hello-"}, + {itemError, 0, `unclosed comment`}, + }}, + {"text with comment close separted from delim", "hello-{{/* */ }}-world", []item{ + {itemText, 0, "hello-"}, + {itemError, 0, `comment ends before closing delimiter`}, + }}, + // This one is an error that we can't catch because it breaks templates with + // minimized JavaScript. Should have fixed it before Go 1.1. + {"unmatched right delimiter", "hello-{.}}-world", []item{ + {itemText, 0, "hello-{.}}-world"}, + tEOF, + }}, +} + +// collect gathers the emitted items into a slice. +func collect(t *lexTest, left, right string) (items []item) { + l := lex(t.name, t.input, left, right) + for { + item := l.nextItem() + items = append(items, item) + if item.typ == itemEOF || item.typ == itemError { + break + } + } + return +} + +func equal(i1, i2 []item, checkPos bool) bool { + if len(i1) != len(i2) { + return false + } + for k := range i1 { + if i1[k].typ != i2[k].typ { + return false + } + if i1[k].val != i2[k].val { + return false + } + if checkPos && i1[k].pos != i2[k].pos { + return false + } + } + return true +} + +func TestLex(t *testing.T) { + for _, test := range lexTests { + items := collect(&test, "", "") + if !equal(items, test.items, false) { + t.Errorf("%s: got\n\t%+v\nexpected\n\t%v", test.name, items, test.items) + } + } +} + +// Some easy cases from above, but with delimiters $$ and @@ +var lexDelimTests = []lexTest{ + {"punctuation", "$$,@%{{}}@@", []item{ + tLeftDelim, + {itemChar, 0, ","}, + {itemChar, 0, "@"}, + {itemChar, 0, "%"}, + {itemChar, 0, "{"}, + {itemChar, 0, "{"}, + {itemChar, 0, "}"}, + {itemChar, 0, "}"}, + tRightDelim, + tEOF, + }}, + {"empty action", `$$@@`, []item{tLeftDelim, tRightDelim, tEOF}}, + {"for", `$$for@@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}}, + {"quote", `$$"abc \n\t\" "@@`, []item{tLeftDelim, tQuote, tRightDelim, tEOF}}, + {"raw quote", "$$" + raw + "@@", []item{tLeftDelim, tRawQuote, tRightDelim, tEOF}}, +} + +var ( + tLeftDelim = item{itemLeftDelim, 0, "$$"} + tRightDelim = item{itemRightDelim, 0, "@@"} +) + +func TestDelims(t *testing.T) { + for _, test := range lexDelimTests { + items := collect(&test, "$$", "@@") + if !equal(items, test.items, false) { + t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items) + } + } +} + +var lexPosTests = []lexTest{ + {"empty", "", []item{tEOF}}, + {"punctuation", "{{,@%#}}", []item{ + {itemLeftDelim, 0, "{{"}, + {itemChar, 2, ","}, + {itemChar, 3, "@"}, + {itemChar, 4, "%"}, + {itemChar, 5, "#"}, + {itemRightDelim, 6, "}}"}, + {itemEOF, 8, ""}, + }}, + {"sample", "0123{{hello}}xyz", []item{ + {itemText, 0, "0123"}, + {itemLeftDelim, 4, "{{"}, + {itemIdentifier, 6, "hello"}, + {itemRightDelim, 11, "}}"}, + {itemText, 13, "xyz"}, + {itemEOF, 16, ""}, + }}, +} + +// The other tests don't check position, to make the test cases easier to construct. +// This one does. +func TestPos(t *testing.T) { + for _, test := range lexPosTests { + items := collect(&test, "", "") + if !equal(items, test.items, true) { + t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items) + if len(items) == len(test.items) { + // Detailed print; avoid item.String() to expose the position value. + for i := range items { + if !equal(items[i:i+1], test.items[i:i+1], true) { + i1 := items[i] + i2 := test.items[i] + t.Errorf("\t#%d: got {%v %d %q} expected {%v %d %q}", i, i1.typ, i1.pos, i1.val, i2.typ, i2.pos, i2.val) + } + } + } + } + } +} diff --git a/vendor/github.com/alecthomas/template/parse/node.go b/vendor/github.com/alecthomas/template/parse/node.go new file mode 100644 index 0000000..55c37f6 --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/node.go @@ -0,0 +1,834 @@ +// 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. + +// Parse nodes. + +package parse + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +var textFormat = "%s" // Changed to "%q" in tests for better error messages. + +// A Node is an element in the parse tree. The interface is trivial. +// The interface contains an unexported method so that only +// types local to this package can satisfy it. +type Node interface { + Type() NodeType + String() string + // Copy does a deep copy of the Node and all its components. + // To avoid type assertions, some XxxNodes also have specialized + // CopyXxx methods that return *XxxNode. + Copy() Node + Position() Pos // byte position of start of node in full original input string + // tree returns the containing *Tree. + // It is unexported so all implementations of Node are in this package. + tree() *Tree +} + +// NodeType identifies the type of a parse tree node. +type NodeType int + +// Pos represents a byte position in the original input text from which +// this template was parsed. +type Pos int + +func (p Pos) Position() Pos { + return p +} + +// Type returns itself and provides an easy default implementation +// for embedding in a Node. Embedded in all non-trivial Nodes. +func (t NodeType) Type() NodeType { + return t +} + +const ( + NodeText NodeType = iota // Plain text. + NodeAction // A non-control action such as a field evaluation. + NodeBool // A boolean constant. + NodeChain // A sequence of field accesses. + NodeCommand // An element of a pipeline. + NodeDot // The cursor, dot. + nodeElse // An else action. Not added to tree. + nodeEnd // An end action. Not added to tree. + NodeField // A field or method name. + NodeIdentifier // An identifier; always a function name. + NodeIf // An if action. + NodeList // A list of Nodes. + NodeNil // An untyped nil constant. + NodeNumber // A numerical constant. + NodePipe // A pipeline of commands. + NodeRange // A range action. + NodeString // A string constant. + NodeTemplate // A template invocation action. + NodeVariable // A $ variable. + NodeWith // A with action. +) + +// Nodes. + +// ListNode holds a sequence of nodes. +type ListNode struct { + NodeType + Pos + tr *Tree + Nodes []Node // The element nodes in lexical order. +} + +func (t *Tree) newList(pos Pos) *ListNode { + return &ListNode{tr: t, NodeType: NodeList, Pos: pos} +} + +func (l *ListNode) append(n Node) { + l.Nodes = append(l.Nodes, n) +} + +func (l *ListNode) tree() *Tree { + return l.tr +} + +func (l *ListNode) String() string { + b := new(bytes.Buffer) + for _, n := range l.Nodes { + fmt.Fprint(b, n) + } + return b.String() +} + +func (l *ListNode) CopyList() *ListNode { + if l == nil { + return l + } + n := l.tr.newList(l.Pos) + for _, elem := range l.Nodes { + n.append(elem.Copy()) + } + return n +} + +func (l *ListNode) Copy() Node { + return l.CopyList() +} + +// TextNode holds plain text. +type TextNode struct { + NodeType + Pos + tr *Tree + Text []byte // The text; may span newlines. +} + +func (t *Tree) newText(pos Pos, text string) *TextNode { + return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)} +} + +func (t *TextNode) String() string { + return fmt.Sprintf(textFormat, t.Text) +} + +func (t *TextNode) tree() *Tree { + return t.tr +} + +func (t *TextNode) Copy() Node { + return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)} +} + +// PipeNode holds a pipeline with optional declaration +type PipeNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Decl []*VariableNode // Variable declarations in lexical order. + Cmds []*CommandNode // The commands in lexical order. +} + +func (t *Tree) newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode { + return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: decl} +} + +func (p *PipeNode) append(command *CommandNode) { + p.Cmds = append(p.Cmds, command) +} + +func (p *PipeNode) String() string { + s := "" + if len(p.Decl) > 0 { + for i, v := range p.Decl { + if i > 0 { + s += ", " + } + s += v.String() + } + s += " := " + } + for i, c := range p.Cmds { + if i > 0 { + s += " | " + } + s += c.String() + } + return s +} + +func (p *PipeNode) tree() *Tree { + return p.tr +} + +func (p *PipeNode) CopyPipe() *PipeNode { + if p == nil { + return p + } + var decl []*VariableNode + for _, d := range p.Decl { + decl = append(decl, d.Copy().(*VariableNode)) + } + n := p.tr.newPipeline(p.Pos, p.Line, decl) + for _, c := range p.Cmds { + n.append(c.Copy().(*CommandNode)) + } + return n +} + +func (p *PipeNode) Copy() Node { + return p.CopyPipe() +} + +// ActionNode holds an action (something bounded by delimiters). +// Control actions have their own nodes; ActionNode represents simple +// ones such as field evaluations and parenthesized pipelines. +type ActionNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Pipe *PipeNode // The pipeline in the action. +} + +func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode { + return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe} +} + +func (a *ActionNode) String() string { + return fmt.Sprintf("{{%s}}", a.Pipe) + +} + +func (a *ActionNode) tree() *Tree { + return a.tr +} + +func (a *ActionNode) Copy() Node { + return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe()) + +} + +// CommandNode holds a command (a pipeline inside an evaluating action). +type CommandNode struct { + NodeType + Pos + tr *Tree + Args []Node // Arguments in lexical order: Identifier, field, or constant. +} + +func (t *Tree) newCommand(pos Pos) *CommandNode { + return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos} +} + +func (c *CommandNode) append(arg Node) { + c.Args = append(c.Args, arg) +} + +func (c *CommandNode) String() string { + s := "" + for i, arg := range c.Args { + if i > 0 { + s += " " + } + if arg, ok := arg.(*PipeNode); ok { + s += "(" + arg.String() + ")" + continue + } + s += arg.String() + } + return s +} + +func (c *CommandNode) tree() *Tree { + return c.tr +} + +func (c *CommandNode) Copy() Node { + if c == nil { + return c + } + n := c.tr.newCommand(c.Pos) + for _, c := range c.Args { + n.append(c.Copy()) + } + return n +} + +// IdentifierNode holds an identifier. +type IdentifierNode struct { + NodeType + Pos + tr *Tree + Ident string // The identifier's name. +} + +// NewIdentifier returns a new IdentifierNode with the given identifier name. +func NewIdentifier(ident string) *IdentifierNode { + return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident} +} + +// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature. +// Chained for convenience. +// TODO: fix one day? +func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode { + i.Pos = pos + return i +} + +// SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature. +// Chained for convenience. +// TODO: fix one day? +func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode { + i.tr = t + return i +} + +func (i *IdentifierNode) String() string { + return i.Ident +} + +func (i *IdentifierNode) tree() *Tree { + return i.tr +} + +func (i *IdentifierNode) Copy() Node { + return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos) +} + +// VariableNode holds a list of variable names, possibly with chained field +// accesses. The dollar sign is part of the (first) name. +type VariableNode struct { + NodeType + Pos + tr *Tree + Ident []string // Variable name and fields in lexical order. +} + +func (t *Tree) newVariable(pos Pos, ident string) *VariableNode { + return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")} +} + +func (v *VariableNode) String() string { + s := "" + for i, id := range v.Ident { + if i > 0 { + s += "." + } + s += id + } + return s +} + +func (v *VariableNode) tree() *Tree { + return v.tr +} + +func (v *VariableNode) Copy() Node { + return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)} +} + +// DotNode holds the special identifier '.'. +type DotNode struct { + NodeType + Pos + tr *Tree +} + +func (t *Tree) newDot(pos Pos) *DotNode { + return &DotNode{tr: t, NodeType: NodeDot, Pos: pos} +} + +func (d *DotNode) Type() NodeType { + // Override method on embedded NodeType for API compatibility. + // TODO: Not really a problem; could change API without effect but + // api tool complains. + return NodeDot +} + +func (d *DotNode) String() string { + return "." +} + +func (d *DotNode) tree() *Tree { + return d.tr +} + +func (d *DotNode) Copy() Node { + return d.tr.newDot(d.Pos) +} + +// NilNode holds the special identifier 'nil' representing an untyped nil constant. +type NilNode struct { + NodeType + Pos + tr *Tree +} + +func (t *Tree) newNil(pos Pos) *NilNode { + return &NilNode{tr: t, NodeType: NodeNil, Pos: pos} +} + +func (n *NilNode) Type() NodeType { + // Override method on embedded NodeType for API compatibility. + // TODO: Not really a problem; could change API without effect but + // api tool complains. + return NodeNil +} + +func (n *NilNode) String() string { + return "nil" +} + +func (n *NilNode) tree() *Tree { + return n.tr +} + +func (n *NilNode) Copy() Node { + return n.tr.newNil(n.Pos) +} + +// FieldNode holds a field (identifier starting with '.'). +// The names may be chained ('.x.y'). +// The period is dropped from each ident. +type FieldNode struct { + NodeType + Pos + tr *Tree + Ident []string // The identifiers in lexical order. +} + +func (t *Tree) newField(pos Pos, ident string) *FieldNode { + return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period +} + +func (f *FieldNode) String() string { + s := "" + for _, id := range f.Ident { + s += "." + id + } + return s +} + +func (f *FieldNode) tree() *Tree { + return f.tr +} + +func (f *FieldNode) Copy() Node { + return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)} +} + +// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.'). +// The names may be chained ('.x.y'). +// The periods are dropped from each ident. +type ChainNode struct { + NodeType + Pos + tr *Tree + Node Node + Field []string // The identifiers in lexical order. +} + +func (t *Tree) newChain(pos Pos, node Node) *ChainNode { + return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node} +} + +// Add adds the named field (which should start with a period) to the end of the chain. +func (c *ChainNode) Add(field string) { + if len(field) == 0 || field[0] != '.' { + panic("no dot in field") + } + field = field[1:] // Remove leading dot. + if field == "" { + panic("empty field") + } + c.Field = append(c.Field, field) +} + +func (c *ChainNode) String() string { + s := c.Node.String() + if _, ok := c.Node.(*PipeNode); ok { + s = "(" + s + ")" + } + for _, field := range c.Field { + s += "." + field + } + return s +} + +func (c *ChainNode) tree() *Tree { + return c.tr +} + +func (c *ChainNode) Copy() Node { + return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)} +} + +// BoolNode holds a boolean constant. +type BoolNode struct { + NodeType + Pos + tr *Tree + True bool // The value of the boolean constant. +} + +func (t *Tree) newBool(pos Pos, true bool) *BoolNode { + return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true} +} + +func (b *BoolNode) String() string { + if b.True { + return "true" + } + return "false" +} + +func (b *BoolNode) tree() *Tree { + return b.tr +} + +func (b *BoolNode) Copy() Node { + return b.tr.newBool(b.Pos, b.True) +} + +// NumberNode holds a number: signed or unsigned integer, float, or complex. +// The value is parsed and stored under all the types that can represent the value. +// This simulates in a small amount of code the behavior of Go's ideal constants. +type NumberNode struct { + NodeType + Pos + tr *Tree + IsInt bool // Number has an integral value. + IsUint bool // Number has an unsigned integral value. + IsFloat bool // Number has a floating-point value. + IsComplex bool // Number is complex. + Int64 int64 // The signed integer value. + Uint64 uint64 // The unsigned integer value. + Float64 float64 // The floating-point value. + Complex128 complex128 // The complex value. + Text string // The original textual representation from the input. +} + +func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) { + n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text} + switch typ { + case itemCharConstant: + rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0]) + if err != nil { + return nil, err + } + if tail != "'" { + return nil, fmt.Errorf("malformed character constant: %s", text) + } + n.Int64 = int64(rune) + n.IsInt = true + n.Uint64 = uint64(rune) + n.IsUint = true + n.Float64 = float64(rune) // odd but those are the rules. + n.IsFloat = true + return n, nil + case itemComplex: + // fmt.Sscan can parse the pair, so let it do the work. + if _, err := fmt.Sscan(text, &n.Complex128); err != nil { + return nil, err + } + n.IsComplex = true + n.simplifyComplex() + return n, nil + } + // Imaginary constants can only be complex unless they are zero. + if len(text) > 0 && text[len(text)-1] == 'i' { + f, err := strconv.ParseFloat(text[:len(text)-1], 64) + if err == nil { + n.IsComplex = true + n.Complex128 = complex(0, f) + n.simplifyComplex() + return n, nil + } + } + // Do integer test first so we get 0x123 etc. + u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below. + if err == nil { + n.IsUint = true + n.Uint64 = u + } + i, err := strconv.ParseInt(text, 0, 64) + if err == nil { + n.IsInt = true + n.Int64 = i + if i == 0 { + n.IsUint = true // in case of -0. + n.Uint64 = u + } + } + // If an integer extraction succeeded, promote the float. + if n.IsInt { + n.IsFloat = true + n.Float64 = float64(n.Int64) + } else if n.IsUint { + n.IsFloat = true + n.Float64 = float64(n.Uint64) + } else { + f, err := strconv.ParseFloat(text, 64) + if err == nil { + n.IsFloat = true + n.Float64 = f + // If a floating-point extraction succeeded, extract the int if needed. + if !n.IsInt && float64(int64(f)) == f { + n.IsInt = true + n.Int64 = int64(f) + } + if !n.IsUint && float64(uint64(f)) == f { + n.IsUint = true + n.Uint64 = uint64(f) + } + } + } + if !n.IsInt && !n.IsUint && !n.IsFloat { + return nil, fmt.Errorf("illegal number syntax: %q", text) + } + return n, nil +} + +// simplifyComplex pulls out any other types that are represented by the complex number. +// These all require that the imaginary part be zero. +func (n *NumberNode) simplifyComplex() { + n.IsFloat = imag(n.Complex128) == 0 + if n.IsFloat { + n.Float64 = real(n.Complex128) + n.IsInt = float64(int64(n.Float64)) == n.Float64 + if n.IsInt { + n.Int64 = int64(n.Float64) + } + n.IsUint = float64(uint64(n.Float64)) == n.Float64 + if n.IsUint { + n.Uint64 = uint64(n.Float64) + } + } +} + +func (n *NumberNode) String() string { + return n.Text +} + +func (n *NumberNode) tree() *Tree { + return n.tr +} + +func (n *NumberNode) Copy() Node { + nn := new(NumberNode) + *nn = *n // Easy, fast, correct. + return nn +} + +// StringNode holds a string constant. The value has been "unquoted". +type StringNode struct { + NodeType + Pos + tr *Tree + Quoted string // The original text of the string, with quotes. + Text string // The string, after quote processing. +} + +func (t *Tree) newString(pos Pos, orig, text string) *StringNode { + return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text} +} + +func (s *StringNode) String() string { + return s.Quoted +} + +func (s *StringNode) tree() *Tree { + return s.tr +} + +func (s *StringNode) Copy() Node { + return s.tr.newString(s.Pos, s.Quoted, s.Text) +} + +// endNode represents an {{end}} action. +// It does not appear in the final parse tree. +type endNode struct { + NodeType + Pos + tr *Tree +} + +func (t *Tree) newEnd(pos Pos) *endNode { + return &endNode{tr: t, NodeType: nodeEnd, Pos: pos} +} + +func (e *endNode) String() string { + return "{{end}}" +} + +func (e *endNode) tree() *Tree { + return e.tr +} + +func (e *endNode) Copy() Node { + return e.tr.newEnd(e.Pos) +} + +// elseNode represents an {{else}} action. Does not appear in the final tree. +type elseNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) +} + +func (t *Tree) newElse(pos Pos, line int) *elseNode { + return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line} +} + +func (e *elseNode) Type() NodeType { + return nodeElse +} + +func (e *elseNode) String() string { + return "{{else}}" +} + +func (e *elseNode) tree() *Tree { + return e.tr +} + +func (e *elseNode) Copy() Node { + return e.tr.newElse(e.Pos, e.Line) +} + +// BranchNode is the common representation of if, range, and with. +type BranchNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Pipe *PipeNode // The pipeline to be evaluated. + List *ListNode // What to execute if the value is non-empty. + ElseList *ListNode // What to execute if the value is empty (nil if absent). +} + +func (b *BranchNode) String() string { + name := "" + switch b.NodeType { + case NodeIf: + name = "if" + case NodeRange: + name = "range" + case NodeWith: + name = "with" + default: + panic("unknown branch type") + } + if b.ElseList != nil { + return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList) + } + return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List) +} + +func (b *BranchNode) tree() *Tree { + return b.tr +} + +func (b *BranchNode) Copy() Node { + switch b.NodeType { + case NodeIf: + return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) + case NodeRange: + return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) + case NodeWith: + return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) + default: + panic("unknown branch type") + } +} + +// IfNode represents an {{if}} action and its commands. +type IfNode struct { + BranchNode +} + +func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode { + return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} +} + +func (i *IfNode) Copy() Node { + return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList()) +} + +// RangeNode represents a {{range}} action and its commands. +type RangeNode struct { + BranchNode +} + +func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode { + return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} +} + +func (r *RangeNode) Copy() Node { + return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList()) +} + +// WithNode represents a {{with}} action and its commands. +type WithNode struct { + BranchNode +} + +func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode { + return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} +} + +func (w *WithNode) Copy() Node { + return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList()) +} + +// TemplateNode represents a {{template}} action. +type TemplateNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Name string // The name of the template (unquoted). + Pipe *PipeNode // The command to evaluate as dot for the template. +} + +func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode { + return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe} +} + +func (t *TemplateNode) String() string { + if t.Pipe == nil { + return fmt.Sprintf("{{template %q}}", t.Name) + } + return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe) +} + +func (t *TemplateNode) tree() *Tree { + return t.tr +} + +func (t *TemplateNode) Copy() Node { + return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe()) +} diff --git a/vendor/github.com/alecthomas/template/parse/parse.go b/vendor/github.com/alecthomas/template/parse/parse.go new file mode 100644 index 0000000..0d77ade --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/parse.go @@ -0,0 +1,700 @@ +// 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. + +// Package parse builds parse trees for templates as defined by text/template +// and html/template. Clients should use those packages to construct templates +// rather than this one, which provides shared internal data structures not +// intended for general use. +package parse + +import ( + "bytes" + "fmt" + "runtime" + "strconv" + "strings" +) + +// Tree is the representation of a single parsed template. +type Tree struct { + Name string // name of the template represented by the tree. + ParseName string // name of the top-level template during parsing, for error messages. + Root *ListNode // top-level root of the tree. + text string // text parsed to create the template (or its parent) + // Parsing only; cleared after parse. + funcs []map[string]interface{} + lex *lexer + token [3]item // three-token lookahead for parser. + peekCount int + vars []string // variables defined at the moment. +} + +// Copy returns a copy of the Tree. Any parsing state is discarded. +func (t *Tree) Copy() *Tree { + if t == nil { + return nil + } + return &Tree{ + Name: t.Name, + ParseName: t.ParseName, + Root: t.Root.CopyList(), + text: t.text, + } +} + +// Parse returns a map from template name to parse.Tree, created by parsing the +// templates described in the argument string. The top-level template will be +// given the specified name. If an error is encountered, parsing stops and an +// empty map is returned with the error. +func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) { + treeSet = make(map[string]*Tree) + t := New(name) + t.text = text + _, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...) + return +} + +// next returns the next token. +func (t *Tree) next() item { + if t.peekCount > 0 { + t.peekCount-- + } else { + t.token[0] = t.lex.nextItem() + } + return t.token[t.peekCount] +} + +// backup backs the input stream up one token. +func (t *Tree) backup() { + t.peekCount++ +} + +// backup2 backs the input stream up two tokens. +// The zeroth token is already there. +func (t *Tree) backup2(t1 item) { + t.token[1] = t1 + t.peekCount = 2 +} + +// backup3 backs the input stream up three tokens +// The zeroth token is already there. +func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back. + t.token[1] = t1 + t.token[2] = t2 + t.peekCount = 3 +} + +// peek returns but does not consume the next token. +func (t *Tree) peek() item { + if t.peekCount > 0 { + return t.token[t.peekCount-1] + } + t.peekCount = 1 + t.token[0] = t.lex.nextItem() + return t.token[0] +} + +// nextNonSpace returns the next non-space token. +func (t *Tree) nextNonSpace() (token item) { + for { + token = t.next() + if token.typ != itemSpace { + break + } + } + return token +} + +// peekNonSpace returns but does not consume the next non-space token. +func (t *Tree) peekNonSpace() (token item) { + for { + token = t.next() + if token.typ != itemSpace { + break + } + } + t.backup() + return token +} + +// Parsing. + +// New allocates a new parse tree with the given name. +func New(name string, funcs ...map[string]interface{}) *Tree { + return &Tree{ + Name: name, + funcs: funcs, + } +} + +// ErrorContext returns a textual representation of the location of the node in the input text. +// The receiver is only used when the node does not have a pointer to the tree inside, +// which can occur in old code. +func (t *Tree) ErrorContext(n Node) (location, context string) { + pos := int(n.Position()) + tree := n.tree() + if tree == nil { + tree = t + } + text := tree.text[:pos] + byteNum := strings.LastIndex(text, "\n") + if byteNum == -1 { + byteNum = pos // On first line. + } else { + byteNum++ // After the newline. + byteNum = pos - byteNum + } + lineNum := 1 + strings.Count(text, "\n") + context = n.String() + if len(context) > 20 { + context = fmt.Sprintf("%.20s...", context) + } + return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context +} + +// errorf formats the error and terminates processing. +func (t *Tree) errorf(format string, args ...interface{}) { + t.Root = nil + format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format) + panic(fmt.Errorf(format, args...)) +} + +// error terminates processing. +func (t *Tree) error(err error) { + t.errorf("%s", err) +} + +// expect consumes the next token and guarantees it has the required type. +func (t *Tree) expect(expected itemType, context string) item { + token := t.nextNonSpace() + if token.typ != expected { + t.unexpected(token, context) + } + return token +} + +// expectOneOf consumes the next token and guarantees it has one of the required types. +func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item { + token := t.nextNonSpace() + if token.typ != expected1 && token.typ != expected2 { + t.unexpected(token, context) + } + return token +} + +// unexpected complains about the token and terminates processing. +func (t *Tree) unexpected(token item, context string) { + t.errorf("unexpected %s in %s", token, context) +} + +// recover is the handler that turns panics into returns from the top level of Parse. +func (t *Tree) recover(errp *error) { + e := recover() + if e != nil { + if _, ok := e.(runtime.Error); ok { + panic(e) + } + if t != nil { + t.stopParse() + } + *errp = e.(error) + } + return +} + +// startParse initializes the parser, using the lexer. +func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) { + t.Root = nil + t.lex = lex + t.vars = []string{"$"} + t.funcs = funcs +} + +// stopParse terminates parsing. +func (t *Tree) stopParse() { + t.lex = nil + t.vars = nil + t.funcs = nil +} + +// Parse parses the template definition string to construct a representation of +// the template for execution. If either action delimiter string is empty, the +// default ("{{" or "}}") is used. Embedded template definitions are added to +// the treeSet map. +func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) { + defer t.recover(&err) + t.ParseName = t.Name + t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim)) + t.text = text + t.parse(treeSet) + t.add(treeSet) + t.stopParse() + return t, nil +} + +// add adds tree to the treeSet. +func (t *Tree) add(treeSet map[string]*Tree) { + tree := treeSet[t.Name] + if tree == nil || IsEmptyTree(tree.Root) { + treeSet[t.Name] = t + return + } + if !IsEmptyTree(t.Root) { + t.errorf("template: multiple definition of template %q", t.Name) + } +} + +// IsEmptyTree reports whether this tree (node) is empty of everything but space. +func IsEmptyTree(n Node) bool { + switch n := n.(type) { + case nil: + return true + case *ActionNode: + case *IfNode: + case *ListNode: + for _, node := range n.Nodes { + if !IsEmptyTree(node) { + return false + } + } + return true + case *RangeNode: + case *TemplateNode: + case *TextNode: + return len(bytes.TrimSpace(n.Text)) == 0 + case *WithNode: + default: + panic("unknown node: " + n.String()) + } + return false +} + +// parse is the top-level parser for a template, essentially the same +// as itemList except it also parses {{define}} actions. +// It runs to EOF. +func (t *Tree) parse(treeSet map[string]*Tree) (next Node) { + t.Root = t.newList(t.peek().pos) + for t.peek().typ != itemEOF { + if t.peek().typ == itemLeftDelim { + delim := t.next() + if t.nextNonSpace().typ == itemDefine { + newT := New("definition") // name will be updated once we know it. + newT.text = t.text + newT.ParseName = t.ParseName + newT.startParse(t.funcs, t.lex) + newT.parseDefinition(treeSet) + continue + } + t.backup2(delim) + } + n := t.textOrAction() + if n.Type() == nodeEnd { + t.errorf("unexpected %s", n) + } + t.Root.append(n) + } + return nil +} + +// parseDefinition parses a {{define}} ... {{end}} template definition and +// installs the definition in the treeSet map. The "define" keyword has already +// been scanned. +func (t *Tree) parseDefinition(treeSet map[string]*Tree) { + const context = "define clause" + name := t.expectOneOf(itemString, itemRawString, context) + var err error + t.Name, err = strconv.Unquote(name.val) + if err != nil { + t.error(err) + } + t.expect(itemRightDelim, context) + var end Node + t.Root, end = t.itemList() + if end.Type() != nodeEnd { + t.errorf("unexpected %s in %s", end, context) + } + t.add(treeSet) + t.stopParse() +} + +// itemList: +// textOrAction* +// Terminates at {{end}} or {{else}}, returned separately. +func (t *Tree) itemList() (list *ListNode, next Node) { + list = t.newList(t.peekNonSpace().pos) + for t.peekNonSpace().typ != itemEOF { + n := t.textOrAction() + switch n.Type() { + case nodeEnd, nodeElse: + return list, n + } + list.append(n) + } + t.errorf("unexpected EOF") + return +} + +// textOrAction: +// text | action +func (t *Tree) textOrAction() Node { + switch token := t.nextNonSpace(); token.typ { + case itemElideNewline: + return t.elideNewline() + case itemText: + return t.newText(token.pos, token.val) + case itemLeftDelim: + return t.action() + default: + t.unexpected(token, "input") + } + return nil +} + +// elideNewline: +// Remove newlines trailing rightDelim if \\ is present. +func (t *Tree) elideNewline() Node { + token := t.peek() + if token.typ != itemText { + t.unexpected(token, "input") + return nil + } + + t.next() + stripped := strings.TrimLeft(token.val, "\n\r") + diff := len(token.val) - len(stripped) + if diff > 0 { + // This is a bit nasty. We mutate the token in-place to remove + // preceding newlines. + token.pos += Pos(diff) + token.val = stripped + } + return t.newText(token.pos, token.val) +} + +// Action: +// control +// command ("|" command)* +// Left delim is past. Now get actions. +// First word could be a keyword such as range. +func (t *Tree) action() (n Node) { + switch token := t.nextNonSpace(); token.typ { + case itemElse: + return t.elseControl() + case itemEnd: + return t.endControl() + case itemIf: + return t.ifControl() + case itemRange: + return t.rangeControl() + case itemTemplate: + return t.templateControl() + case itemWith: + return t.withControl() + } + t.backup() + // Do not pop variables; they persist until "end". + return t.newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command")) +} + +// Pipeline: +// declarations? command ('|' command)* +func (t *Tree) pipeline(context string) (pipe *PipeNode) { + var decl []*VariableNode + pos := t.peekNonSpace().pos + // Are there declarations? + for { + if v := t.peekNonSpace(); v.typ == itemVariable { + t.next() + // Since space is a token, we need 3-token look-ahead here in the worst case: + // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an + // argument variable rather than a declaration. So remember the token + // adjacent to the variable so we can push it back if necessary. + tokenAfterVariable := t.peek() + if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") { + t.nextNonSpace() + variable := t.newVariable(v.pos, v.val) + decl = append(decl, variable) + t.vars = append(t.vars, v.val) + if next.typ == itemChar && next.val == "," { + if context == "range" && len(decl) < 2 { + continue + } + t.errorf("too many declarations in %s", context) + } + } else if tokenAfterVariable.typ == itemSpace { + t.backup3(v, tokenAfterVariable) + } else { + t.backup2(v) + } + } + break + } + pipe = t.newPipeline(pos, t.lex.lineNumber(), decl) + for { + switch token := t.nextNonSpace(); token.typ { + case itemRightDelim, itemRightParen: + if len(pipe.Cmds) == 0 { + t.errorf("missing value for %s", context) + } + if token.typ == itemRightParen { + t.backup() + } + return + case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier, + itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen: + t.backup() + pipe.append(t.command()) + default: + t.unexpected(token, context) + } + } +} + +func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { + defer t.popVars(len(t.vars)) + line = t.lex.lineNumber() + pipe = t.pipeline(context) + var next Node + list, next = t.itemList() + switch next.Type() { + case nodeEnd: //done + case nodeElse: + if allowElseIf { + // Special case for "else if". If the "else" is followed immediately by an "if", + // the elseControl will have left the "if" token pending. Treat + // {{if a}}_{{else if b}}_{{end}} + // as + // {{if a}}_{{else}}{{if b}}_{{end}}{{end}}. + // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}} + // is assumed. This technique works even for long if-else-if chains. + // TODO: Should we allow else-if in with and range? + if t.peek().typ == itemIf { + t.next() // Consume the "if" token. + elseList = t.newList(next.Position()) + elseList.append(t.ifControl()) + // Do not consume the next item - only one {{end}} required. + break + } + } + elseList, next = t.itemList() + if next.Type() != nodeEnd { + t.errorf("expected end; found %s", next) + } + } + return pipe.Position(), line, pipe, list, elseList +} + +// If: +// {{if pipeline}} itemList {{end}} +// {{if pipeline}} itemList {{else}} itemList {{end}} +// If keyword is past. +func (t *Tree) ifControl() Node { + return t.newIf(t.parseControl(true, "if")) +} + +// Range: +// {{range pipeline}} itemList {{end}} +// {{range pipeline}} itemList {{else}} itemList {{end}} +// Range keyword is past. +func (t *Tree) rangeControl() Node { + return t.newRange(t.parseControl(false, "range")) +} + +// With: +// {{with pipeline}} itemList {{end}} +// {{with pipeline}} itemList {{else}} itemList {{end}} +// If keyword is past. +func (t *Tree) withControl() Node { + return t.newWith(t.parseControl(false, "with")) +} + +// End: +// {{end}} +// End keyword is past. +func (t *Tree) endControl() Node { + return t.newEnd(t.expect(itemRightDelim, "end").pos) +} + +// Else: +// {{else}} +// Else keyword is past. +func (t *Tree) elseControl() Node { + // Special case for "else if". + peek := t.peekNonSpace() + if peek.typ == itemIf { + // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ". + return t.newElse(peek.pos, t.lex.lineNumber()) + } + return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber()) +} + +// Template: +// {{template stringValue pipeline}} +// Template keyword is past. The name must be something that can evaluate +// to a string. +func (t *Tree) templateControl() Node { + var name string + token := t.nextNonSpace() + switch token.typ { + case itemString, itemRawString: + s, err := strconv.Unquote(token.val) + if err != nil { + t.error(err) + } + name = s + default: + t.unexpected(token, "template invocation") + } + var pipe *PipeNode + if t.nextNonSpace().typ != itemRightDelim { + t.backup() + // Do not pop variables; they persist until "end". + pipe = t.pipeline("template") + } + return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe) +} + +// command: +// operand (space operand)* +// space-separated arguments up to a pipeline character or right delimiter. +// we consume the pipe character but leave the right delim to terminate the action. +func (t *Tree) command() *CommandNode { + cmd := t.newCommand(t.peekNonSpace().pos) + for { + t.peekNonSpace() // skip leading spaces. + operand := t.operand() + if operand != nil { + cmd.append(operand) + } + switch token := t.next(); token.typ { + case itemSpace: + continue + case itemError: + t.errorf("%s", token.val) + case itemRightDelim, itemRightParen: + t.backup() + case itemPipe: + default: + t.errorf("unexpected %s in operand; missing space?", token) + } + break + } + if len(cmd.Args) == 0 { + t.errorf("empty command") + } + return cmd +} + +// operand: +// term .Field* +// An operand is a space-separated component of a command, +// a term possibly followed by field accesses. +// A nil return means the next item is not an operand. +func (t *Tree) operand() Node { + node := t.term() + if node == nil { + return nil + } + if t.peek().typ == itemField { + chain := t.newChain(t.peek().pos, node) + for t.peek().typ == itemField { + chain.Add(t.next().val) + } + // Compatibility with original API: If the term is of type NodeField + // or NodeVariable, just put more fields on the original. + // Otherwise, keep the Chain node. + // TODO: Switch to Chains always when we can. + switch node.Type() { + case NodeField: + node = t.newField(chain.Position(), chain.String()) + case NodeVariable: + node = t.newVariable(chain.Position(), chain.String()) + default: + node = chain + } + } + return node +} + +// term: +// literal (number, string, nil, boolean) +// function (identifier) +// . +// .Field +// $ +// '(' pipeline ')' +// A term is a simple "expression". +// A nil return means the next item is not a term. +func (t *Tree) term() Node { + switch token := t.nextNonSpace(); token.typ { + case itemError: + t.errorf("%s", token.val) + case itemIdentifier: + if !t.hasFunction(token.val) { + t.errorf("function %q not defined", token.val) + } + return NewIdentifier(token.val).SetTree(t).SetPos(token.pos) + case itemDot: + return t.newDot(token.pos) + case itemNil: + return t.newNil(token.pos) + case itemVariable: + return t.useVar(token.pos, token.val) + case itemField: + return t.newField(token.pos, token.val) + case itemBool: + return t.newBool(token.pos, token.val == "true") + case itemCharConstant, itemComplex, itemNumber: + number, err := t.newNumber(token.pos, token.val, token.typ) + if err != nil { + t.error(err) + } + return number + case itemLeftParen: + pipe := t.pipeline("parenthesized pipeline") + if token := t.next(); token.typ != itemRightParen { + t.errorf("unclosed right paren: unexpected %s", token) + } + return pipe + case itemString, itemRawString: + s, err := strconv.Unquote(token.val) + if err != nil { + t.error(err) + } + return t.newString(token.pos, token.val, s) + } + t.backup() + return nil +} + +// hasFunction reports if a function name exists in the Tree's maps. +func (t *Tree) hasFunction(name string) bool { + for _, funcMap := range t.funcs { + if funcMap == nil { + continue + } + if funcMap[name] != nil { + return true + } + } + return false +} + +// popVars trims the variable list to the specified length +func (t *Tree) popVars(n int) { + t.vars = t.vars[:n] +} + +// useVar returns a node for a variable reference. It errors if the +// variable is not defined. +func (t *Tree) useVar(pos Pos, name string) Node { + v := t.newVariable(pos, name) + for _, varName := range t.vars { + if varName == v.Ident[0] { + return v + } + } + t.errorf("undefined variable %q", v.Ident[0]) + return nil +} diff --git a/vendor/github.com/alecthomas/template/parse/parse_test.go b/vendor/github.com/alecthomas/template/parse/parse_test.go new file mode 100644 index 0000000..c73640f --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/parse_test.go @@ -0,0 +1,426 @@ +// 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. + +package parse + +import ( + "flag" + "fmt" + "strings" + "testing" +) + +var debug = flag.Bool("debug", false, "show the errors produced by the main tests") + +type numberTest struct { + text string + isInt bool + isUint bool + isFloat bool + isComplex bool + int64 + uint64 + float64 + complex128 +} + +var numberTests = []numberTest{ + // basics + {"0", true, true, true, false, 0, 0, 0, 0}, + {"-0", true, true, true, false, 0, 0, 0, 0}, // check that -0 is a uint. + {"73", true, true, true, false, 73, 73, 73, 0}, + {"073", true, true, true, false, 073, 073, 073, 0}, + {"0x73", true, true, true, false, 0x73, 0x73, 0x73, 0}, + {"-73", true, false, true, false, -73, 0, -73, 0}, + {"+73", true, false, true, false, 73, 0, 73, 0}, + {"100", true, true, true, false, 100, 100, 100, 0}, + {"1e9", true, true, true, false, 1e9, 1e9, 1e9, 0}, + {"-1e9", true, false, true, false, -1e9, 0, -1e9, 0}, + {"-1.2", false, false, true, false, 0, 0, -1.2, 0}, + {"1e19", false, true, true, false, 0, 1e19, 1e19, 0}, + {"-1e19", false, false, true, false, 0, 0, -1e19, 0}, + {"4i", false, false, false, true, 0, 0, 0, 4i}, + {"-1.2+4.2i", false, false, false, true, 0, 0, 0, -1.2 + 4.2i}, + {"073i", false, false, false, true, 0, 0, 0, 73i}, // not octal! + // complex with 0 imaginary are float (and maybe integer) + {"0i", true, true, true, true, 0, 0, 0, 0}, + {"-1.2+0i", false, false, true, true, 0, 0, -1.2, -1.2}, + {"-12+0i", true, false, true, true, -12, 0, -12, -12}, + {"13+0i", true, true, true, true, 13, 13, 13, 13}, + // funny bases + {"0123", true, true, true, false, 0123, 0123, 0123, 0}, + {"-0x0", true, true, true, false, 0, 0, 0, 0}, + {"0xdeadbeef", true, true, true, false, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0}, + // character constants + {`'a'`, true, true, true, false, 'a', 'a', 'a', 0}, + {`'\n'`, true, true, true, false, '\n', '\n', '\n', 0}, + {`'\\'`, true, true, true, false, '\\', '\\', '\\', 0}, + {`'\''`, true, true, true, false, '\'', '\'', '\'', 0}, + {`'\xFF'`, true, true, true, false, 0xFF, 0xFF, 0xFF, 0}, + {`'パ'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0}, + {`'\u30d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0}, + {`'\U000030d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0}, + // some broken syntax + {text: "+-2"}, + {text: "0x123."}, + {text: "1e."}, + {text: "0xi."}, + {text: "1+2."}, + {text: "'x"}, + {text: "'xx'"}, + // Issue 8622 - 0xe parsed as floating point. Very embarrassing. + {"0xef", true, true, true, false, 0xef, 0xef, 0xef, 0}, +} + +func TestNumberParse(t *testing.T) { + for _, test := range numberTests { + // If fmt.Sscan thinks it's complex, it's complex. We can't trust the output + // because imaginary comes out as a number. + var c complex128 + typ := itemNumber + var tree *Tree + if test.text[0] == '\'' { + typ = itemCharConstant + } else { + _, err := fmt.Sscan(test.text, &c) + if err == nil { + typ = itemComplex + } + } + n, err := tree.newNumber(0, test.text, typ) + ok := test.isInt || test.isUint || test.isFloat || test.isComplex + if ok && err != nil { + t.Errorf("unexpected error for %q: %s", test.text, err) + continue + } + if !ok && err == nil { + t.Errorf("expected error for %q", test.text) + continue + } + if !ok { + if *debug { + fmt.Printf("%s\n\t%s\n", test.text, err) + } + continue + } + if n.IsComplex != test.isComplex { + t.Errorf("complex incorrect for %q; should be %t", test.text, test.isComplex) + } + if test.isInt { + if !n.IsInt { + t.Errorf("expected integer for %q", test.text) + } + if n.Int64 != test.int64 { + t.Errorf("int64 for %q should be %d Is %d", test.text, test.int64, n.Int64) + } + } else if n.IsInt { + t.Errorf("did not expect integer for %q", test.text) + } + if test.isUint { + if !n.IsUint { + t.Errorf("expected unsigned integer for %q", test.text) + } + if n.Uint64 != test.uint64 { + t.Errorf("uint64 for %q should be %d Is %d", test.text, test.uint64, n.Uint64) + } + } else if n.IsUint { + t.Errorf("did not expect unsigned integer for %q", test.text) + } + if test.isFloat { + if !n.IsFloat { + t.Errorf("expected float for %q", test.text) + } + if n.Float64 != test.float64 { + t.Errorf("float64 for %q should be %g Is %g", test.text, test.float64, n.Float64) + } + } else if n.IsFloat { + t.Errorf("did not expect float for %q", test.text) + } + if test.isComplex { + if !n.IsComplex { + t.Errorf("expected complex for %q", test.text) + } + if n.Complex128 != test.complex128 { + t.Errorf("complex128 for %q should be %g Is %g", test.text, test.complex128, n.Complex128) + } + } else if n.IsComplex { + t.Errorf("did not expect complex for %q", test.text) + } + } +} + +type parseTest struct { + name string + input string + ok bool + result string // what the user would see in an error message. +} + +const ( + noError = true + hasError = false +) + +var parseTests = []parseTest{ + {"empty", "", noError, + ``}, + {"comment", "{{/*\n\n\n*/}}", noError, + ``}, + {"spaces", " \t\n", noError, + `" \t\n"`}, + {"text", "some text", noError, + `"some text"`}, + {"emptyAction", "{{}}", hasError, + `{{}}`}, + {"field", "{{.X}}", noError, + `{{.X}}`}, + {"simple command", "{{printf}}", noError, + `{{printf}}`}, + {"$ invocation", "{{$}}", noError, + "{{$}}"}, + {"variable invocation", "{{with $x := 3}}{{$x 23}}{{end}}", noError, + "{{with $x := 3}}{{$x 23}}{{end}}"}, + {"variable with fields", "{{$.I}}", noError, + "{{$.I}}"}, + {"multi-word command", "{{printf `%d` 23}}", noError, + "{{printf `%d` 23}}"}, + {"pipeline", "{{.X|.Y}}", noError, + `{{.X | .Y}}`}, + {"pipeline with decl", "{{$x := .X|.Y}}", noError, + `{{$x := .X | .Y}}`}, + {"nested pipeline", "{{.X (.Y .Z) (.A | .B .C) (.E)}}", noError, + `{{.X (.Y .Z) (.A | .B .C) (.E)}}`}, + {"field applied to parentheses", "{{(.Y .Z).Field}}", noError, + `{{(.Y .Z).Field}}`}, + {"simple if", "{{if .X}}hello{{end}}", noError, + `{{if .X}}"hello"{{end}}`}, + {"if with else", "{{if .X}}true{{else}}false{{end}}", noError, + `{{if .X}}"true"{{else}}"false"{{end}}`}, + {"if with else if", "{{if .X}}true{{else if .Y}}false{{end}}", noError, + `{{if .X}}"true"{{else}}{{if .Y}}"false"{{end}}{{end}}`}, + {"if else chain", "+{{if .X}}X{{else if .Y}}Y{{else if .Z}}Z{{end}}+", noError, + `"+"{{if .X}}"X"{{else}}{{if .Y}}"Y"{{else}}{{if .Z}}"Z"{{end}}{{end}}{{end}}"+"`}, + {"simple range", "{{range .X}}hello{{end}}", noError, + `{{range .X}}"hello"{{end}}`}, + {"chained field range", "{{range .X.Y.Z}}hello{{end}}", noError, + `{{range .X.Y.Z}}"hello"{{end}}`}, + {"nested range", "{{range .X}}hello{{range .Y}}goodbye{{end}}{{end}}", noError, + `{{range .X}}"hello"{{range .Y}}"goodbye"{{end}}{{end}}`}, + {"range with else", "{{range .X}}true{{else}}false{{end}}", noError, + `{{range .X}}"true"{{else}}"false"{{end}}`}, + {"range over pipeline", "{{range .X|.M}}true{{else}}false{{end}}", noError, + `{{range .X | .M}}"true"{{else}}"false"{{end}}`}, + {"range []int", "{{range .SI}}{{.}}{{end}}", noError, + `{{range .SI}}{{.}}{{end}}`}, + {"range 1 var", "{{range $x := .SI}}{{.}}{{end}}", noError, + `{{range $x := .SI}}{{.}}{{end}}`}, + {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError, + `{{range $x, $y := .SI}}{{.}}{{end}}`}, + {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError, + `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`}, + {"template", "{{template `x`}}", noError, + `{{template "x"}}`}, + {"template with arg", "{{template `x` .Y}}", noError, + `{{template "x" .Y}}`}, + {"with", "{{with .X}}hello{{end}}", noError, + `{{with .X}}"hello"{{end}}`}, + {"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError, + `{{with .X}}"hello"{{else}}"goodbye"{{end}}`}, + {"elide newline", "{{true}}\\\n ", noError, + `{{true}}" "`}, + // Errors. + {"unclosed action", "hello{{range", hasError, ""}, + {"unmatched end", "{{end}}", hasError, ""}, + {"missing end", "hello{{range .x}}", hasError, ""}, + {"missing end after else", "hello{{range .x}}{{else}}", hasError, ""}, + {"undefined function", "hello{{undefined}}", hasError, ""}, + {"undefined variable", "{{$x}}", hasError, ""}, + {"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""}, + {"variable undefined in template", "{{template $v}}", hasError, ""}, + {"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""}, + {"template with field ref", "{{template .X}}", hasError, ""}, + {"template with var", "{{template $v}}", hasError, ""}, + {"invalid punctuation", "{{printf 3, 4}}", hasError, ""}, + {"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""}, + {"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""}, + {"dot applied to parentheses", "{{printf (printf .).}}", hasError, ""}, + {"adjacent args", "{{printf 3`x`}}", hasError, ""}, + {"adjacent args with .", "{{printf `x`.}}", hasError, ""}, + {"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", hasError, ""}, + {"invalid newline elision", "{{true}}\\{{true}}", hasError, ""}, + // Equals (and other chars) do not assignments make (yet). + {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"}, + {"bug0b", "{{$x = 1}}{{$x}}", hasError, ""}, + {"bug0c", "{{$x ! 2}}{{$x}}", hasError, ""}, + {"bug0d", "{{$x % 3}}{{$x}}", hasError, ""}, + // Check the parse fails for := rather than comma. + {"bug0e", "{{range $x := $y := 3}}{{end}}", hasError, ""}, + // Another bug: variable read must ignore following punctuation. + {"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""}, // ! is just illegal here. + {"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""}, // $x+2 should not parse as ($x) (+2). + {"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space. +} + +var builtins = map[string]interface{}{ + "printf": fmt.Sprintf, +} + +func testParse(doCopy bool, t *testing.T) { + textFormat = "%q" + defer func() { textFormat = "%s" }() + for _, test := range parseTests { + tmpl, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree), builtins) + switch { + case err == nil && !test.ok: + t.Errorf("%q: expected error; got none", test.name) + continue + case err != nil && test.ok: + t.Errorf("%q: unexpected error: %v", test.name, err) + continue + case err != nil && !test.ok: + // expected error, got one + if *debug { + fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err) + } + continue + } + var result string + if doCopy { + result = tmpl.Root.Copy().String() + } else { + result = tmpl.Root.String() + } + if result != test.result { + t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result) + } + } +} + +func TestParse(t *testing.T) { + testParse(false, t) +} + +// Same as TestParse, but we copy the node first +func TestParseCopy(t *testing.T) { + testParse(true, t) +} + +type isEmptyTest struct { + name string + input string + empty bool +} + +var isEmptyTests = []isEmptyTest{ + {"empty", ``, true}, + {"nonempty", `hello`, false}, + {"spaces only", " \t\n \t\n", true}, + {"definition", `{{define "x"}}something{{end}}`, true}, + {"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true}, + {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n", false}, + {"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false}, +} + +func TestIsEmpty(t *testing.T) { + if !IsEmptyTree(nil) { + t.Errorf("nil tree is not empty") + } + for _, test := range isEmptyTests { + tree, err := New("root").Parse(test.input, "", "", make(map[string]*Tree), nil) + if err != nil { + t.Errorf("%q: unexpected error: %v", test.name, err) + continue + } + if empty := IsEmptyTree(tree.Root); empty != test.empty { + t.Errorf("%q: expected %t got %t", test.name, test.empty, empty) + } + } +} + +func TestErrorContextWithTreeCopy(t *testing.T) { + tree, err := New("root").Parse("{{if true}}{{end}}", "", "", make(map[string]*Tree), nil) + if err != nil { + t.Fatalf("unexpected tree parse failure: %v", err) + } + treeCopy := tree.Copy() + wantLocation, wantContext := tree.ErrorContext(tree.Root.Nodes[0]) + gotLocation, gotContext := treeCopy.ErrorContext(treeCopy.Root.Nodes[0]) + if wantLocation != gotLocation { + t.Errorf("wrong error location want %q got %q", wantLocation, gotLocation) + } + if wantContext != gotContext { + t.Errorf("wrong error location want %q got %q", wantContext, gotContext) + } +} + +// All failures, and the result is a string that must appear in the error message. +var errorTests = []parseTest{ + // Check line numbers are accurate. + {"unclosed1", + "line1\n{{", + hasError, `unclosed1:2: unexpected unclosed action in command`}, + {"unclosed2", + "line1\n{{define `x`}}line2\n{{", + hasError, `unclosed2:3: unexpected unclosed action in command`}, + // Specific errors. + {"function", + "{{foo}}", + hasError, `function "foo" not defined`}, + {"comment", + "{{/*}}", + hasError, `unclosed comment`}, + {"lparen", + "{{.X (1 2 3}}", + hasError, `unclosed left paren`}, + {"rparen", + "{{.X 1 2 3)}}", + hasError, `unexpected ")"`}, + {"space", + "{{`x`3}}", + hasError, `missing space?`}, + {"idchar", + "{{a#}}", + hasError, `'#'`}, + {"charconst", + "{{'a}}", + hasError, `unterminated character constant`}, + {"stringconst", + `{{"a}}`, + hasError, `unterminated quoted string`}, + {"rawstringconst", + "{{`a}}", + hasError, `unterminated raw quoted string`}, + {"number", + "{{0xi}}", + hasError, `number syntax`}, + {"multidefine", + "{{define `a`}}a{{end}}{{define `a`}}b{{end}}", + hasError, `multiple definition of template`}, + {"eof", + "{{range .X}}", + hasError, `unexpected EOF`}, + {"variable", + // Declare $x so it's defined, to avoid that error, and then check we don't parse a declaration. + "{{$x := 23}}{{with $x.y := 3}}{{$x 23}}{{end}}", + hasError, `unexpected ":="`}, + {"multidecl", + "{{$a,$b,$c := 23}}", + hasError, `too many declarations`}, + {"undefvar", + "{{$a}}", + hasError, `undefined variable`}, +} + +func TestErrors(t *testing.T) { + for _, test := range errorTests { + _, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree)) + if err == nil { + t.Errorf("%q: expected error", test.name) + continue + } + if !strings.Contains(err.Error(), test.result) { + t.Errorf("%q: error %q does not contain %q", test.name, err, test.result) + } + } +} diff --git a/vendor/github.com/alecthomas/template/template.go b/vendor/github.com/alecthomas/template/template.go new file mode 100644 index 0000000..447ed2a --- /dev/null +++ b/vendor/github.com/alecthomas/template/template.go @@ -0,0 +1,218 @@ +// 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. + +package template + +import ( + "fmt" + "reflect" + + "github.com/alecthomas/template/parse" +) + +// common holds the information shared by related templates. +type common struct { + tmpl map[string]*Template + // We use two maps, one for parsing and one for execution. + // This separation makes the API cleaner since it doesn't + // expose reflection to the client. + parseFuncs FuncMap + execFuncs map[string]reflect.Value +} + +// Template is the representation of a parsed template. The *parse.Tree +// field is exported only for use by html/template and should be treated +// as unexported by all other clients. +type Template struct { + name string + *parse.Tree + *common + leftDelim string + rightDelim string +} + +// New allocates a new template with the given name. +func New(name string) *Template { + return &Template{ + name: name, + } +} + +// Name returns the name of the template. +func (t *Template) Name() string { + return t.name +} + +// New allocates a new template associated with the given one and with the same +// delimiters. The association, which is transitive, allows one template to +// invoke another with a {{template}} action. +func (t *Template) New(name string) *Template { + t.init() + return &Template{ + name: name, + common: t.common, + leftDelim: t.leftDelim, + rightDelim: t.rightDelim, + } +} + +func (t *Template) init() { + if t.common == nil { + t.common = new(common) + t.tmpl = make(map[string]*Template) + t.parseFuncs = make(FuncMap) + t.execFuncs = make(map[string]reflect.Value) + } +} + +// Clone returns a duplicate of the template, including all associated +// templates. The actual representation is not copied, but the name space of +// associated templates is, so further calls to Parse in the copy will add +// templates to the copy but not to the original. Clone can be used to prepare +// common templates and use them with variant definitions for other templates +// by adding the variants after the clone is made. +func (t *Template) Clone() (*Template, error) { + nt := t.copy(nil) + nt.init() + nt.tmpl[t.name] = nt + for k, v := range t.tmpl { + if k == t.name { // Already installed. + continue + } + // The associated templates share nt's common structure. + tmpl := v.copy(nt.common) + nt.tmpl[k] = tmpl + } + for k, v := range t.parseFuncs { + nt.parseFuncs[k] = v + } + for k, v := range t.execFuncs { + nt.execFuncs[k] = v + } + return nt, nil +} + +// copy returns a shallow copy of t, with common set to the argument. +func (t *Template) copy(c *common) *Template { + nt := New(t.name) + nt.Tree = t.Tree + nt.common = c + nt.leftDelim = t.leftDelim + nt.rightDelim = t.rightDelim + return nt +} + +// AddParseTree creates a new template with the name and parse tree +// and associates it with t. +func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { + if t.common != nil && t.tmpl[name] != nil { + return nil, fmt.Errorf("template: redefinition of template %q", name) + } + nt := t.New(name) + nt.Tree = tree + t.tmpl[name] = nt + return nt, nil +} + +// Templates returns a slice of the templates associated with t, including t +// itself. +func (t *Template) Templates() []*Template { + if t.common == nil { + return nil + } + // Return a slice so we don't expose the map. + m := make([]*Template, 0, len(t.tmpl)) + for _, v := range t.tmpl { + m = append(m, v) + } + return m +} + +// Delims sets the action delimiters to the specified strings, to be used in +// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template +// definitions will inherit the settings. An empty delimiter stands for the +// corresponding default: {{ or }}. +// The return value is the template, so calls can be chained. +func (t *Template) Delims(left, right string) *Template { + t.leftDelim = left + t.rightDelim = right + return t +} + +// Funcs adds the elements of the argument map to the template's function map. +// It panics if a value in the map is not a function with appropriate return +// type. However, it is legal to overwrite elements of the map. The return +// value is the template, so calls can be chained. +func (t *Template) Funcs(funcMap FuncMap) *Template { + t.init() + addValueFuncs(t.execFuncs, funcMap) + addFuncs(t.parseFuncs, funcMap) + return t +} + +// Lookup returns the template with the given name that is associated with t, +// or nil if there is no such template. +func (t *Template) Lookup(name string) *Template { + if t.common == nil { + return nil + } + return t.tmpl[name] +} + +// Parse parses a string into a template. Nested template definitions will be +// associated with the top-level template t. Parse may be called multiple times +// to parse definitions of templates to associate with t. It is an error if a +// resulting template is non-empty (contains content other than template +// definitions) and would replace a non-empty template with the same name. +// (In multiple calls to Parse with the same receiver template, only one call +// can contain text other than space, comments, and template definitions.) +func (t *Template) Parse(text string) (*Template, error) { + t.init() + trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins) + if err != nil { + return nil, err + } + // Add the newly parsed trees, including the one for t, into our common structure. + for name, tree := range trees { + // If the name we parsed is the name of this template, overwrite this template. + // The associate method checks it's not a redefinition. + tmpl := t + if name != t.name { + tmpl = t.New(name) + } + // Even if t == tmpl, we need to install it in the common.tmpl map. + if replace, err := t.associate(tmpl, tree); err != nil { + return nil, err + } else if replace { + tmpl.Tree = tree + } + tmpl.leftDelim = t.leftDelim + tmpl.rightDelim = t.rightDelim + } + return t, nil +} + +// associate installs the new template into the group of templates associated +// with t. It is an error to reuse a name except to overwrite an empty +// template. The two are already known to share the common structure. +// The boolean return value reports wither to store this tree as t.Tree. +func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) { + if new.common != t.common { + panic("internal error: associate not common") + } + name := new.name + if old := t.tmpl[name]; old != nil { + oldIsEmpty := parse.IsEmptyTree(old.Root) + newIsEmpty := parse.IsEmptyTree(tree.Root) + if newIsEmpty { + // Whether old is empty or not, new is empty; no reason to replace old. + return false, nil + } + if !oldIsEmpty { + return false, fmt.Errorf("template: redefinition of template %q", name) + } + } + t.tmpl[name] = new + return true, nil +} diff --git a/vendor/github.com/alecthomas/units/COPYING b/vendor/github.com/alecthomas/units/COPYING new file mode 100644 index 0000000..2993ec0 --- /dev/null +++ b/vendor/github.com/alecthomas/units/COPYING @@ -0,0 +1,19 @@ +Copyright (C) 2014 Alec Thomas + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/alecthomas/units/README.md b/vendor/github.com/alecthomas/units/README.md new file mode 100644 index 0000000..bee884e --- /dev/null +++ b/vendor/github.com/alecthomas/units/README.md @@ -0,0 +1,11 @@ +# Units - Helpful unit multipliers and functions for Go + +The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package. + +It allows for code like this: + +```go +n, err := ParseBase2Bytes("1KB") +// n == 1024 +n = units.Mebibyte * 512 +``` diff --git a/vendor/github.com/alecthomas/units/bytes.go b/vendor/github.com/alecthomas/units/bytes.go new file mode 100644 index 0000000..eaadeb8 --- /dev/null +++ b/vendor/github.com/alecthomas/units/bytes.go @@ -0,0 +1,83 @@ +package units + +// Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte, +// etc.). +type Base2Bytes int64 + +// Base-2 byte units. +const ( + Kibibyte Base2Bytes = 1024 + KiB = Kibibyte + Mebibyte = Kibibyte * 1024 + MiB = Mebibyte + Gibibyte = Mebibyte * 1024 + GiB = Gibibyte + Tebibyte = Gibibyte * 1024 + TiB = Tebibyte + Pebibyte = Tebibyte * 1024 + PiB = Pebibyte + Exbibyte = Pebibyte * 1024 + EiB = Exbibyte +) + +var ( + bytesUnitMap = MakeUnitMap("iB", "B", 1024) + oldBytesUnitMap = MakeUnitMap("B", "B", 1024) +) + +// ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB +// and KiB are both 1024. +func ParseBase2Bytes(s string) (Base2Bytes, error) { + n, err := ParseUnit(s, bytesUnitMap) + if err != nil { + n, err = ParseUnit(s, oldBytesUnitMap) + } + return Base2Bytes(n), err +} + +func (b Base2Bytes) String() string { + return ToString(int64(b), 1024, "iB", "B") +} + +var ( + metricBytesUnitMap = MakeUnitMap("B", "B", 1000) +) + +// MetricBytes are SI byte units (1000 bytes in a kilobyte). +type MetricBytes SI + +// SI base-10 byte units. +const ( + Kilobyte MetricBytes = 1000 + KB = Kilobyte + Megabyte = Kilobyte * 1000 + MB = Megabyte + Gigabyte = Megabyte * 1000 + GB = Gigabyte + Terabyte = Gigabyte * 1000 + TB = Terabyte + Petabyte = Terabyte * 1000 + PB = Petabyte + Exabyte = Petabyte * 1000 + EB = Exabyte +) + +// ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes. +func ParseMetricBytes(s string) (MetricBytes, error) { + n, err := ParseUnit(s, metricBytesUnitMap) + return MetricBytes(n), err +} + +func (m MetricBytes) String() string { + return ToString(int64(m), 1000, "B", "B") +} + +// ParseStrictBytes supports both iB and B suffixes for base 2 and metric, +// respectively. That is, KiB represents 1024 and KB represents 1000. +func ParseStrictBytes(s string) (int64, error) { + n, err := ParseUnit(s, bytesUnitMap) + if err != nil { + n, err = ParseUnit(s, metricBytesUnitMap) + } + return int64(n), err +} diff --git a/vendor/github.com/alecthomas/units/bytes_test.go b/vendor/github.com/alecthomas/units/bytes_test.go new file mode 100644 index 0000000..6cbc79d --- /dev/null +++ b/vendor/github.com/alecthomas/units/bytes_test.go @@ -0,0 +1,49 @@ +package units + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBase2BytesString(t *testing.T) { + assert.Equal(t, Base2Bytes(0).String(), "0B") + assert.Equal(t, Base2Bytes(1025).String(), "1KiB1B") + assert.Equal(t, Base2Bytes(1048577).String(), "1MiB1B") +} + +func TestParseBase2Bytes(t *testing.T) { + n, err := ParseBase2Bytes("0B") + assert.NoError(t, err) + assert.Equal(t, 0, int(n)) + n, err = ParseBase2Bytes("1KB") + assert.NoError(t, err) + assert.Equal(t, 1024, int(n)) + n, err = ParseBase2Bytes("1MB1KB25B") + assert.NoError(t, err) + assert.Equal(t, 1049625, int(n)) + n, err = ParseBase2Bytes("1.5MB") + assert.NoError(t, err) + assert.Equal(t, 1572864, int(n)) +} + +func TestMetricBytesString(t *testing.T) { + assert.Equal(t, MetricBytes(0).String(), "0B") + assert.Equal(t, MetricBytes(1001).String(), "1KB1B") + assert.Equal(t, MetricBytes(1001025).String(), "1MB1KB25B") +} + +func TestParseMetricBytes(t *testing.T) { + n, err := ParseMetricBytes("0B") + assert.NoError(t, err) + assert.Equal(t, 0, int(n)) + n, err = ParseMetricBytes("1KB1B") + assert.NoError(t, err) + assert.Equal(t, 1001, int(n)) + n, err = ParseMetricBytes("1MB1KB25B") + assert.NoError(t, err) + assert.Equal(t, 1001025, int(n)) + n, err = ParseMetricBytes("1.5MB") + assert.NoError(t, err) + assert.Equal(t, 1500000, int(n)) +} diff --git a/vendor/github.com/alecthomas/units/doc.go b/vendor/github.com/alecthomas/units/doc.go new file mode 100644 index 0000000..156ae38 --- /dev/null +++ b/vendor/github.com/alecthomas/units/doc.go @@ -0,0 +1,13 @@ +// Package units provides helpful unit multipliers and functions for Go. +// +// The goal of this package is to have functionality similar to the time [1] package. +// +// +// [1] http://golang.org/pkg/time/ +// +// It allows for code like this: +// +// n, err := ParseBase2Bytes("1KB") +// // n == 1024 +// n = units.Mebibyte * 512 +package units diff --git a/vendor/github.com/alecthomas/units/si.go b/vendor/github.com/alecthomas/units/si.go new file mode 100644 index 0000000..8234a9d --- /dev/null +++ b/vendor/github.com/alecthomas/units/si.go @@ -0,0 +1,26 @@ +package units + +// SI units. +type SI int64 + +// SI unit multiples. +const ( + Kilo SI = 1000 + Mega = Kilo * 1000 + Giga = Mega * 1000 + Tera = Giga * 1000 + Peta = Tera * 1000 + Exa = Peta * 1000 +) + +func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 { + return map[string]float64{ + shortSuffix: 1, + "K" + suffix: float64(scale), + "M" + suffix: float64(scale * scale), + "G" + suffix: float64(scale * scale * scale), + "T" + suffix: float64(scale * scale * scale * scale), + "P" + suffix: float64(scale * scale * scale * scale * scale), + "E" + suffix: float64(scale * scale * scale * scale * scale * scale), + } +} diff --git a/vendor/github.com/alecthomas/units/util.go b/vendor/github.com/alecthomas/units/util.go new file mode 100644 index 0000000..6527e92 --- /dev/null +++ b/vendor/github.com/alecthomas/units/util.go @@ -0,0 +1,138 @@ +package units + +import ( + "errors" + "fmt" + "strings" +) + +var ( + siUnits = []string{"", "K", "M", "G", "T", "P", "E"} +) + +func ToString(n int64, scale int64, suffix, baseSuffix string) string { + mn := len(siUnits) + out := make([]string, mn) + for i, m := range siUnits { + if n%scale != 0 || i == 0 && n == 0 { + s := suffix + if i == 0 { + s = baseSuffix + } + out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s) + } + n /= scale + if n == 0 { + break + } + } + return strings.Join(out, "") +} + +// Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123 +var errLeadingInt = errors.New("units: bad [0-9]*") // never printed + +// leadingInt consumes the leading [0-9]* from s. +func leadingInt(s string) (x int64, rem string, err error) { + i := 0 + for ; i < len(s); i++ { + c := s[i] + if c < '0' || c > '9' { + break + } + if x >= (1<<63-10)/10 { + // overflow + return 0, "", errLeadingInt + } + x = x*10 + int64(c) - '0' + } + return x, s[i:], nil +} + +func ParseUnit(s string, unitMap map[string]float64) (int64, error) { + // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ + orig := s + f := float64(0) + neg := false + + // Consume [-+]? + if s != "" { + c := s[0] + if c == '-' || c == '+' { + neg = c == '-' + s = s[1:] + } + } + // Special case: if all that is left is "0", this is zero. + if s == "0" { + return 0, nil + } + if s == "" { + return 0, errors.New("units: invalid " + orig) + } + for s != "" { + g := float64(0) // this element of the sequence + + var x int64 + var err error + + // The next character must be [0-9.] + if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) { + return 0, errors.New("units: invalid " + orig) + } + // Consume [0-9]* + pl := len(s) + x, s, err = leadingInt(s) + if err != nil { + return 0, errors.New("units: invalid " + orig) + } + g = float64(x) + pre := pl != len(s) // whether we consumed anything before a period + + // Consume (\.[0-9]*)? + post := false + if s != "" && s[0] == '.' { + s = s[1:] + pl := len(s) + x, s, err = leadingInt(s) + if err != nil { + return 0, errors.New("units: invalid " + orig) + } + scale := 1.0 + for n := pl - len(s); n > 0; n-- { + scale *= 10 + } + g += float64(x) / scale + post = pl != len(s) + } + if !pre && !post { + // no digits (e.g. ".s" or "-.s") + return 0, errors.New("units: invalid " + orig) + } + + // Consume unit. + i := 0 + for ; i < len(s); i++ { + c := s[i] + if c == '.' || ('0' <= c && c <= '9') { + break + } + } + u := s[:i] + s = s[i:] + unit, ok := unitMap[u] + if !ok { + return 0, errors.New("units: unknown unit " + u + " in " + orig) + } + + f += g * unit + } + + if neg { + f = -f + } + if f < float64(-1<<63) || f > float64(1<<63-1) { + return 0, errors.New("units: overflow parsing unit") + } + return int64(f), nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/.gitignore b/vendor/github.com/aws/aws-sdk-go/.gitignore new file mode 100644 index 0000000..fb11cec --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/.gitignore @@ -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 diff --git a/vendor/github.com/aws/aws-sdk-go/.godoc_config b/vendor/github.com/aws/aws-sdk-go/.godoc_config new file mode 100644 index 0000000..395878d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/.godoc_config @@ -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 + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/.travis.yml b/vendor/github.com/aws/aws-sdk-go/.travis.yml new file mode 100644 index 0000000..4b86136 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/.travis.yml @@ -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 diff --git a/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md new file mode 100644 index 0000000..8275fd8 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md @@ -0,0 +1,2472 @@ +Release v1.12.46 (2017-12-12) +=== + +### Service Client Updates +* `service/workmail`: Adds new service + * Today, Amazon WorkMail released an administrative SDK and enabled AWS CloudTrail integration. With the administrative SDK, you can natively integrate WorkMail with your existing services. The SDK enables programmatic user, resource, and group management through API calls. This means your existing IT tools and workflows can now automate WorkMail management, and third party applications can streamline WorkMail migrations and account actions. + +Release v1.12.45 (2017-12-11) +=== + +### Service Client Updates +* `service/cognito-idp`: Updates service API and documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/lex-models`: Updates service API and documentation +* `service/sagemaker`: Updates service API + * CreateModel API Update: The request parameter 'ExecutionRoleArn' has changed from optional to required. + +Release v1.12.44 (2017-12-08) +=== + +### Service Client Updates +* `service/appstream`: Updates service API and documentation + * This API update is to support the feature that allows customers to automatically consume the latest Amazon AppStream 2.0 agent as and when published by AWS. +* `service/ecs`: Updates service documentation + * Documentation updates for Windows containers. +* `service/monitoring`: Updates service API and documentation + * With this launch, you can now create a CloudWatch alarm that alerts you when M out of N datapoints of a metric are breaching your predefined threshold, such as three out of five times in any given five minutes interval or two out of six times in a thirty minutes interval. When M out of N datapoints are not breaching your threshold in an interval, the alarm will be in OK state. Please note that the M datapoints out of N datapoints in an interval can be of any order and does not need to be consecutive. Consequently, you can now get alerted even when the spikes in your metrics are intermittent over an interval. + +Release v1.12.43 (2017-12-07) +=== + +### Service Client Updates +* `service/email`: Updates service API, documentation, and paginators + * Customers can customize the emails that Amazon SES sends when verifying new identities. This feature is helpful for developers whose applications send email through Amazon SES on behalf of their customers. +* `service/es`: Updates service API and documentation + * Added support for encryption of data at rest on Amazon Elasticsearch Service using AWS KMS + +### SDK Bugs +* `models/apis` Fixes removes colliding sagemaker models folders ([#1686](https://github.com/aws/aws-sdk-go/pull/1686)) + * Fixes Release v1.12.42's SageMaker vs sagemaker model folders. +Release v1.12.42 (2017-12-06) +=== + +### Service Client Updates +* `service/clouddirectory`: Updates service API and documentation + * Amazon Cloud Directory makes it easier for you to apply schema changes across your directories with in-place schema upgrades. Your directories now remain available while backward-compatible schema changes are being applied, such as the addition of new fields. You also can view the history of your schema changes in Cloud Directory by using both major and minor version identifiers, which can help you track and audit schema versions across directories. +* `service/elasticbeanstalk`: Updates service documentation + * Documentation updates for AWS Elastic Beanstalk. +* `service/sagemaker`: Adds new service + * Initial waiters for common SageMaker workflows. + +Release v1.12.41 (2017-12-05) +=== + +### Service Client Updates +* `service/iot`: Updates service API and documentation + * Add error action API for RulesEngine. +* `service/servicecatalog`: Updates service API and documentation + * ServiceCatalog has two distinct personas for its use, an "admin" persona (who creates sets of products with different versions and prescribes who has access to them) and an "end-user" persona (who can launch cloud resources based on the configuration data their admins have given them access to). This API update will allow admin users to deactivate/activate product versions, end-user will only be able to access and launch active product versions. +* `service/servicediscovery`: Adds new service + * Amazon Route 53 Auto Naming lets you configure public or private namespaces that your microservice applications run in. When instances of the service become available, you can call the Auto Naming API to register the instance, and Amazon Route 53 automatically creates up to five DNS records and an optional health check. Clients that submit DNS queries for the service receive an answer that contains up to eight healthy records. + +Release v1.12.40 (2017-12-04) +=== + +### Service Client Updates +* `service/budgets`: Updates service API and documentation + * Add additional costTypes to support finer control for different charges included in a cost budget. +* `service/ecs`: Updates service documentation + * Documentation updates for ecs + +Release v1.12.39 (2017-12-01) +=== + +### Service Client Updates +* `service/SageMaker`: Updates service waiters + +Release v1.12.38 (2017-11-30) +=== + +### Service Client Updates +* `service/AWSMoneypenny`: Adds new service +* `service/Cloud9`: Adds new service +* `service/Serverless Registry`: Adds new service +* `service/apigateway`: Updates service API, documentation, and paginators + * Added support Private Integration and VPC Link features in API Gateway. This allows to create an API with the API Gateway private integration, thus providing clients access to HTTP/HTTPS resources in an Amazon VPC from outside of the VPC through a VpcLink resource. +* `service/ec2`: Updates service API and documentation + * Adds the following updates: 1. Spread Placement ensures that instances are placed on distinct hardware in order to reduce correlated failures. 2. Inter-region VPC Peering allows customers to peer VPCs across different AWS regions without requiring additional gateways, VPN connections or physical hardware +* `service/lambda`: Updates service API and documentation + * AWS Lambda now supports the ability to set the concurrency limits for individual functions, and increasing memory to 3008 MB. + +Release v1.12.37 (2017-11-30) +=== + +### Service Client Updates +* `service/Ardi`: Adds new service +* `service/autoscaling`: Updates service API and documentation + * You can now use Auto Scaling with EC2 Launch Templates via the CreateAutoScalingGroup and UpdateAutoScalingGroup APIs. +* `service/ec2`: Updates service API and documentation + * Adds the following updates: 1. T2 Unlimited enables high CPU performance for any period of time whenever required 2. You are now able to create and launch EC2 m5 and h1 instances +* `service/lightsail`: Updates service API and documentation + * This release adds support for load balancer and TLS/SSL certificate management. This set of APIs allows customers to create, manage, and scale secure load balanced applications on Lightsail infrastructure. To provide support for customers who manage their DNS on Lightsail, we've added the ability create an Alias A type record which can point to a load balancer DNS name via the CreateDomainEntry API http://docs.aws.amazon.com/lightsail/2016-11-28/api-reference/API_CreateDomainEntry.html. +* `service/ssm`: Updates service API and documentation + * This release updates AWS Systems Manager APIs to enable executing automations at controlled rate, target resources in a resource groups and execute entire automation at once or single step at a time. It is now also possible to use YAML, in addition to JSON, when creating Systems Manager documents. +* `service/waf`: Updates service API and documentation + * This release adds support for rule group and managed rule group. Rule group is a container of rules that customers can create, put rules in it and associate the rule group to a WebACL. All rules in a rule group will function identically as they would if each rule was individually associated to the WebACL. Managed rule group is a pre-configured rule group composed by our security partners and made available via the AWS Marketplace. Customers can subscribe to these managed rule groups, associate the managed rule group to their WebACL and start using them immediately to protect their resources. +* `service/waf-regional`: Updates service API and documentation + +Release v1.12.36 (2017-11-29) +=== + +### Service Client Updates +* `service/DeepInsight`: Adds new service +* `service/IronmanRuntime`: Adds new service +* `service/Orchestra - Laser`: Adds new service +* `service/SageMaker`: Adds new service +* `service/Shine`: Adds new service +* `service/archived.kinesisvideo`: Adds new service +* `service/data.kinesisvideo`: Adds new service +* `service/dynamodb`: Updates service API and documentation + * Amazon DynamoDB now supports the following features: Global Table and On-Demand Backup. Global Table is a fully-managed, multi-region, multi-master database. DynamoDB customers can now write anywhere and read anywhere with single-digit millisecond latency by performing database operations closest to where end users reside. Global Table also enables customers to disaster-proof their applications, keeping them running and data accessible even in the face of natural disasters or region disruptions. Customers can set up Global Table with just a few clicks in the AWS Management Console-no application rewrites required. On-Demand Backup capability is to protect data from loss due to application errors, and meet customers' archival needs for compliance and regulatory reasons. Customers can backup and restore their DynamoDB table data anytime, with a single-click in the AWS management console or a single API call. Backup and restore actions execute with zero impact on table performance or availability. For more information, see the Amazon DynamoDB Developer Guide. +* `service/ecs`: Updates service API and documentation + * Amazon Elastic Container Service (Amazon ECS) released a new launch type for running containers on a serverless infrastructure. The Fargate launch type allows you to run your containerized applications without the need to provision and manage the backend infrastructure. Just register your task definition and Fargate launches the container for you. +* `service/glacier`: Updates service API and documentation + * This release includes support for Glacier Select, a new feature that allows you to filter and analyze your Glacier archives and store the results in a user-specified S3 location. +* `service/greengrass`: Updates service API and documentation + * Greengrass OTA feature allows updating Greengrass Core and Greengrass OTA Agent. Local Resource Access feature allows Greengrass Lambdas to access local resources such as peripheral devices and volumes. +* `service/iot`: Updates service API and documentation + * This release adds support for a number of new IoT features, including AWS IoT Device Management (Jobs, Fleet Index and Thing Registration), Thing Groups, Policies on Thing Groups, Registry & Job Events, JSON Logs, Fine-Grained Logging Controls, Custom Authorization and AWS Service Authentication Using X.509 Certificates. +* `service/kinesisvideo`: Adds new service + * Announcing Amazon Kinesis Video Streams, a fully managed video ingestion and storage service. Kinesis Video Streams makes it easy to securely stream video from connected devices to AWS for machine learning, analytics, and processing. You can also stream other time-encoded data like RADAR and LIDAR signals using Kinesis Video Streams. +* `service/rekognition`: Updates service API, documentation, and paginators + * This release introduces Amazon Rekognition support for video analysis. +* `service/s3`: Updates service API and documentation + * This release includes support for Glacier Select, a new feature that allows you to filter and analyze your Glacier storage class objects and store the results in a user-specified S3 location. + +Release v1.12.35 (2017-11-29) +=== + +### Service Client Updates +* `service/AmazonMQ`: Adds new service +* `service/GuardDuty`: Adds new service +* `service/apigateway`: Updates service API and documentation + * Changes related to CanaryReleaseDeployment feature. Enables API developer to create a deployment as canary deployment and test API changes with percentage of customers before promoting changes to all customers. +* `service/batch`: Updates service API and documentation + * Add support for Array Jobs which allow users to easily submit many copies of a job with a single API call. This change also enhances the job dependency model to support N_TO_N and sequential dependency chains. The ListJobs and DescribeJobs APIs now have the ability to list or describe the status of entire Array Jobs or individual elements within the array. +* `service/cognito-idp`: Updates service API and documentation +* `service/deepdish`: Adds new service + * AWS AppSync is an enterprise-level, fully managed GraphQL service with real-time data synchronization and offline programming features. +* `service/ec2`: Updates service API and documentation + * Adds the following updates: 1. You are now able to host a service powered by AWS PrivateLink to provide private connectivity to other VPCs. You are now also able to create endpoints to other services powered by PrivateLink including AWS services, Marketplace Seller services or custom services created by yourself or other AWS VPC customers. 2. You are now able to save launch parameters in a single template that can be used with Auto Scaling, Spot Fleet, Spot, and On Demand instances. 3. You are now able to launch Spot instances via the RunInstances API, using a single additional parameter. RunInstances will response synchronously with an instance ID should capacity be available for your Spot request. 4. A simplified Spot pricing model which delivers low, predictable prices that adjust gradually, based on long-term trends in supply and demand. 5. Amazon EC2 Spot can now hibernate Amazon EBS-backed instances in the event of an interruption, so your workloads pick up from where they left off. Spot can fulfill your request by resuming instances from a hibernated state when capacity is available. +* `service/lambda`: Updates service API and documentation + * Lambda aliases can now shift traffic between two function versions, based on preassigned weights. + +Release v1.12.34 (2017-11-27) +=== + +### Service Client Updates +* `service/data.mediastore`: Adds new service +* `service/mediaconvert`: Adds new service + * AWS Elemental MediaConvert is a file-based video conversion service that transforms media into formats required for traditional broadcast and for internet streaming to multi-screen devices. +* `service/medialive`: Adds new service + * AWS Elemental MediaLive is a video service that lets you easily create live outputs for broadcast and streaming delivery. +* `service/mediapackage`: Adds new service + * AWS Elemental MediaPackage is a just-in-time video packaging and origination service that lets you format highly secure and reliable live outputs for a variety of devices. +* `service/mediastore`: Adds new service + * AWS Elemental MediaStore is an AWS storage service optimized for media. It gives you the performance, consistency, and low latency required to deliver live and on-demand video content. AWS Elemental MediaStore acts as the origin store in your video workflow. + +Release v1.12.33 (2017-11-22) +=== + +### Service Client Updates +* `service/acm`: Updates service API and documentation + * AWS Certificate Manager now supports the ability to import domainless certs and additional Key Types as well as an additional validation method for DNS. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.12.32 (2017-11-22) +=== + +### Service Client Updates +* `service/apigateway`: Updates service API and documentation + * Add support for Access logs and customizable integration timeouts +* `service/cloudformation`: Updates service API and documentation + * 1) Instance-level parameter overrides (CloudFormation-StackSet feature): This feature will allow the customers to override the template parameters on specific stackInstances. Customers will also have ability to update their existing instances with/without parameter-overrides using a new API "UpdateStackInstances" 2) Add support for SSM parameters in CloudFormation - This feature will allow the customers to use Systems Manager parameters in CloudFormation templates. They will be able to see values for these parameters in Describe APIs. +* `service/codebuild`: Updates service API and documentation + * Adding support for accessing Amazon VPC resources from AWS CodeBuild, dependency caching and build badges. +* `service/elasticmapreduce`: Updates service API and documentation + * Enable Kerberos on Amazon EMR. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rekognition`: Updates service API and documentation + * This release includes updates to Amazon Rekognition for the following APIs. The new DetectText API allows you to recognize and extract textual content from images. Face Model Versioning has been added to operations that deal with face detection. +* `service/shield`: Updates service API, documentation, and paginators + * The AWS Shield SDK has been updated in order to support Elastic IP address protections, the addition of AttackProperties objects in DescribeAttack responses, and a new GetSubscriptionState operation. +* `service/storagegateway`: Updates service API and documentation + * AWS Storage Gateway now enables you to get notification when all your files written to your NFS file share have been uploaded to Amazon S3. Storage Gateway also enables guessing of the MIME type for uploaded objects based on file extensions. +* `service/xray`: Updates service API, documentation, and paginators + * Added automatic pagination support for AWS X-Ray APIs in the SDKs that support this feature. + +Release v1.12.31 (2017-11-20) +=== + +### Service Client Updates +* `service/apigateway`: Updates service documentation + * Documentation updates for Apigateway +* `service/codecommit`: Updates service API, documentation, and paginators + * AWS CodeCommit now supports pull requests. You can use pull requests to collaboratively review code changes for minor changes or fixes, major feature additions, or new versions of your released software. +* `service/firehose`: Updates service API and documentation + * This release includes a new Kinesis Firehose feature that supports Splunk as Kinesis Firehose delivery destination. You can now use Kinesis Firehose to ingest real-time data to Splunk in a serverless, reliable, and salable manner. This release also includes a new feature that allows you to configure Lambda buffer size in Kinesis Firehose data transformation feature. You can now customize the data buffer size before invoking Lambda function in Kinesis Firehose for data transformation. This feature allows you to flexibly trade-off processing and delivery latency with cost and efficiency based on your specific use cases and requirements. +* `service/iis`: Adds new service + * The AWS Cost Explorer API gives customers programmatic access to AWS cost and usage information, allowing them to perform adhoc queries and build interactive cost management applications that leverage this dataset. +* `service/kinesis`: Updates service API and documentation + * Customers can now obtain the important characteristics of their stream with DescribeStreamSummary. The response will not include the shard list for the stream but will have the number of open shards, and all the other fields included in the DescribeStream response. +* `service/workdocs`: Updates service API and documentation + * DescribeGroups API and miscellaneous enhancements + +### SDK Bugs +* `aws/client`: Retry delays for throttled exception were not limited to 5 mintues [#1654](https://github.com/aws/aws-sdk-go/pull/1654) + * Fixes [#1653](https://github.com/aws/aws-sdk-go/issues/1653) +Release v1.12.30 (2017-11-17) +=== + +### Service Client Updates +* `service/application-autoscaling`: Updates service API and documentation +* `service/dms`: Updates service API, documentation, and paginators + * Support for migration task assessment. Support for data validation after the migration. +* `service/elasticloadbalancingv2`: Updates service API and documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rds`: Updates service API and documentation + * Amazon RDS now supports importing MySQL databases by using backup files from Amazon S3. +* `service/s3`: Updates service API + * Added ORC to the supported S3 Inventory formats. + +### SDK Bugs +* `private/protocol/restjson`: Define JSONValue marshaling for body and querystring ([#1640](https://github.com/aws/aws-sdk-go/pull/1640)) + * Adds support for APIs which use JSONValue for body and querystring targets. + * Fixes [#1636](https://github.com/aws/aws-sdk-go/issues/1636) +Release v1.12.29 (2017-11-16) +=== + +### Service Client Updates +* `service/application-autoscaling`: Updates service API and documentation +* `service/ec2`: Updates service API + * You are now able to create and launch EC2 x1e smaller instance sizes +* `service/glue`: Updates service API and documentation + * API update for AWS Glue. New crawler configuration attribute enables customers to specify crawler behavior. New XML classifier enables classification of XML data. +* `service/opsworkscm`: Updates service API, documentation, and waiters + * Documentation updates for OpsWorks-cm: a new feature, OpsWorks for Puppet Enterprise, that allows users to create and manage OpsWorks-hosted Puppet Enterprise servers. +* `service/organizations`: Updates service API, documentation, and paginators + * This release adds APIs that you can use to enable and disable integration with AWS services designed to work with AWS Organizations. This integration allows the AWS service to perform operations on your behalf on all of the accounts in your organization. Although you can use these APIs yourself, we recommend that you instead use the commands provided in the other AWS service to enable integration with AWS Organizations. +* `service/route53`: Updates service API and documentation + * You can use Route 53's GetAccountLimit/GetHostedZoneLimit/GetReusableDelegationSetLimit APIs to view your current limits (including custom set limits) on Route 53 resources such as hosted zones and health checks. These APIs also return the number of each resource you're currently using to enable comparison against your current limits. + +Release v1.12.28 (2017-11-15) +=== + +### Service Client Updates +* `service/apigateway`: Updates service API and documentation + * 1. Extended GetDocumentationParts operation to support retrieving documentation parts resources without contents. 2. Added hosted zone ID in the custom domain response. +* `service/email`: Updates service API, documentation, and examples + * SES launches Configuration Set Reputation Metrics and Email Pausing Today, two features that build upon the capabilities of the reputation dashboard. The first is the ability to export reputation metrics for individual configuration sets. The second is the ability to temporarily pause email sending, either at the configuration set level, or across your entire Amazon SES account. +* `service/polly`: Updates service API + * Amazon Polly adds Korean language support with new female voice - "Seoyeon" and new Indian English female voice - "Aditi" +* `service/states`: Updates service API and documentation + * You can now use the UpdateStateMachine API to update your state machine definition and role ARN. Existing executions will continue to use the previous definition and role ARN. You can use the DescribeStateMachineForExecution API to determine which state machine definition and role ARN is associated with an execution + +Release v1.12.27 (2017-11-14) +=== + +### Service Client Updates +* `service/ecs`: Updates service API and documentation + * Added new mode for Task Networking in ECS, called awsvpc mode. Mode configuration parameters to be passed in via awsvpcConfiguration. Updated APIs now use/show this new mode - RegisterTaskDefinition, CreateService, UpdateService, RunTask, StartTask. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/lightsail`: Updates service API and documentation + * Lightsail now supports attached block storage, which allows you to scale your applications and protect application data with additional SSD-backed storage disks. This feature allows Lightsail customers to attach secure storage disks to their Lightsail instances and manage their attached disks, including creating and deleting disks, attaching and detaching disks from instances, and backing up disks via snapshot. +* `service/route53`: Updates service API and documentation + * When a Route 53 health check or hosted zone is created by a linked AWS service, the object now includes information about the service that created it. Hosted zones or health checks that are created by a linked service can't be updated or deleted using Route 53. +* `service/ssm`: Updates service API and documentation + * EC2 Systems Manager GetInventory API adds support for aggregation. + +### SDK Enhancements +* `aws/request`: Remove default port from HTTP host header ([#1618](https://github.com/aws/aws-sdk-go/pull/1618)) + * Updates the SDK to automatically remove default ports based on the URL's scheme when setting the HTTP Host header's value. + * Fixes [#1537](https://github.com/aws/aws-sdk-go/issues/1537) + +Release v1.12.26 (2017-11-09) +=== + +### Service Client Updates +* `service/ec2`: Updates service API and documentation + * Introduces the following features: 1. Create a default subnet in an Availability Zone if no default subnet exists. 2. Spot Fleet integrates with Elastic Load Balancing to enable you to attach one or more load balancers to a Spot Fleet request. When you attach the load balancer, it automatically registers the instance in the Spot Fleet to the load balancers which distributes incoming traffic across the instances. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.12.25 (2017-11-08) +=== + +### Service Client Updates +* `service/application-autoscaling`: Updates service API and documentation +* `service/batch`: Updates service documentation + * Documentation updates for AWS Batch. +* `service/ec2`: Updates service API and documentation + * AWS PrivateLink for Amazon Services - Customers can now privately access Amazon services from their Amazon Virtual Private Cloud (VPC), without using public IPs, and without requiring the traffic to traverse across the Internet. +* `service/elasticache`: Updates service API and documentation + * This release adds online resharding for ElastiCache for Redis offering, providing the ability to add and remove shards from a running cluster. Developers can now dynamically scale-out or scale-in their Redis cluster workloads to adapt to changes in demand. ElastiCache will resize the cluster by adding or removing shards and redistribute hash slots uniformly across the new shard configuration, all while the cluster continues to stay online and serves requests. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.12.24 (2017-11-07) +=== + +### Service Client Updates +* `service/elasticloadbalancingv2`: Updates service documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rds`: Updates service API and documentation + * DescribeOrderableDBInstanceOptions now returns the minimum and maximum allowed values for storage size, total provisioned IOPS, and provisioned IOPS per GiB for a DB instance. +* `service/s3`: Updates service API, documentation, and examples + * This releases adds support for 4 features: 1. Default encryption for S3 Bucket, 2. Encryption status in inventory and Encryption support for inventory. 3. Cross region replication of KMS-encrypted objects, and 4. ownership overwrite for CRR. + +Release v1.12.23 (2017-11-07) +=== + +### Service Client Updates +* `service/api.pricing`: Adds new service +* `service/ec2`: Updates service API + * You are now able to create and launch EC2 C5 instances, the next generation of EC2's compute-optimized instances, in us-east-1, us-west-2 and eu-west-1. C5 instances offer up to 72 vCPUs, 144 GiB of DDR4 instance memory, 25 Gbps in Network bandwidth and improved EBS and Networking bandwidth on smaller instance sizes to deliver improved performance for compute-intensive workloads. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/kms`: Updates service API, documentation, and examples + * Documentation updates for AWS KMS. +* `service/organizations`: Updates service documentation + * This release updates permission statements for several API operations, and corrects some other minor errors. +* `service/states`: Updates service API, documentation, and paginators + * Documentation update. + +Release v1.12.22 (2017-11-03) +=== + +### Service Client Updates +* `service/ecs`: Updates service API and documentation + * Amazon ECS users can now add devices to their containers and enable init process in containers through the use of docker's 'devices' and 'init' features. These fields can be specified under linuxParameters in ContainerDefinition in the Task Definition Template. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.12.21 (2017-11-02) +=== + +### Service Client Updates +* `service/apigateway`: Updates service API and documentation + * This release supports creating and managing Regional and Edge-Optimized API endpoints. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +### SDK Bugs +* `aws/request`: Fix bug in request presign creating invalide URL ([#1624](https://github.com/aws/aws-sdk-go/pull/1624)) + * Fixes a bug the Request Presign and PresignRequest methods that would allow a invalid expire duration as input. A expire time of 0 would be interpreted by the SDK to generate a normal request signature, not a presigned URL. This caused the returned URL unusable. + * Fixes [#1617](https://github.com/aws/aws-sdk-go/issues/1617) +Release v1.12.20 (2017-11-01) +=== + +### Service Client Updates +* `service/acm`: Updates service documentation + * Documentation updates for ACM +* `service/cloudhsmv2`: Updates service documentation + * Minor documentation update for AWS CloudHSM (cloudhsmv2). +* `service/directconnect`: Updates service API and documentation + * AWS DirectConnect now provides support for Global Access for Virtual Private Cloud (VPC) via a new feature called Direct Connect Gateway. A Direct Connect Gateway will allow you to group multiple Direct Connect Private Virtual Interfaces (DX-VIF) and Private Virtual Gateways (VGW) from different AWS regions (but belonging to the same AWS Account) and pass traffic from any DX-VIF to any VPC in the grouping. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +### SDK Enhancements +* `aws/client`: Adding status code 429 to throttlable status codes in default retryer (#1621) + +Release v1.12.19 (2017-10-26) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.12.18 (2017-10-26) +=== + +### Service Client Updates +* `service/cloudfront`: Updates service API and documentation + * You can now specify additional options for MinimumProtocolVersion, which controls the SSL/TLS protocol that CloudFront uses to communicate with viewers. The minimum protocol version that you choose also determines the ciphers that CloudFront uses to encrypt the content that it returns to viewers. +* `service/ec2`: Updates service API + * You are now able to create and launch EC2 P3 instance, next generation GPU instances, optimized for machine learning and high performance computing applications. With up to eight NVIDIA Tesla V100 GPUs, P3 instances provide up to one petaflop of mixed-precision, 125 teraflops of single-precision, and 62 teraflops of double-precision floating point performance, as well as a 300 GB/s second-generation NVLink interconnect that enables high-speed, low-latency GPU-to-GPU communication. P3 instances also feature up to 64 vCPUs based on custom Intel Xeon E5 (Broadwell) processors, 488 GB of DRAM, and 25 Gbps of dedicated aggregate network bandwidth using the Elastic Network Adapter (ENA). +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.12.17 (2017-10-24) +=== + +### Service Client Updates +* `service/config`: Updates service API +* `service/elasticache`: Updates service API, documentation, and examples + * Amazon ElastiCache for Redis today announced support for data encryption both for data in-transit and data at-rest. The new encryption in-transit functionality enables ElastiCache for Redis customers to encrypt data for all communication between clients and Redis engine, and all intra-cluster Redis communication. The encryption at-rest functionality allows customers to encrypt their S3 based backups. Customers can begin using the new functionality by simply enabling this functionality via AWS console, and a small configuration change in their Redis clients. The ElastiCache for Redis service automatically manages life cycle of the certificates required for encryption, including the issuance, renewal and expiration of certificates. Additionally, as part of this launch, customers will gain the ability to start using the Redis AUTH command that provides an added level of authentication. +* `service/glue`: Adds new service + * AWS Glue: Adding a new API, BatchStopJobRun, to stop one or more job runs for a specified Job. +* `service/pinpoint`: Updates service API and documentation + * Added support for APNs VoIP messages. Added support for collapsible IDs, message priority, and TTL for APNs and FCM/GCM. + +Release v1.12.16 (2017-10-23) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/organizations`: Updates service API and documentation + * This release supports integrating other AWS services with AWS Organizations through the use of an IAM service-linked role called AWSServiceRoleForOrganizations. Certain operations automatically create that role if it does not already exist. + +Release v1.12.15 (2017-10-20) +=== + +### Service Client Updates +* `service/ec2`: Updates service API and documentation + * Adding pagination support for DescribeSecurityGroups for EC2 Classic and VPC Security Groups + +Release v1.12.14 (2017-10-19) +=== + +### Service Client Updates +* `service/sqs`: Updates service API and documentation + * Added support for tracking cost allocation by adding, updating, removing, and listing the metadata tags of Amazon SQS queues. +* `service/ssm`: Updates service API and documentation + * EC2 Systems Manager versioning support for Parameter Store. Also support for referencing parameter versions in SSM Documents. + +Release v1.12.13 (2017-10-18) +=== + +### Service Client Updates +* `service/lightsail`: Updates service API and documentation + * This release adds support for Windows Server-based Lightsail instances. The GetInstanceAccessDetails API now returns the password of your Windows Server-based instance when using the default key pair. GetInstanceAccessDetails also returns a PasswordData object for Windows Server instances containing the ciphertext and keyPairName. The Blueprint data type now includes a list of platform values (LINUX_UNIX or WINDOWS). The Bundle data type now includes a list of SupportedPlatforms values (LINUX_UNIX or WINDOWS). + +Release v1.12.12 (2017-10-17) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/es`: Updates service API and documentation + * This release adds support for VPC access to Amazon Elasticsearch Service. + * This release adds support for VPC access to Amazon Elasticsearch Service. + +Release v1.12.11 (2017-10-16) +=== + +### Service Client Updates +* `service/cloudhsm`: Updates service API and documentation + * Documentation updates for AWS CloudHSM Classic. +* `service/ec2`: Updates service API and documentation + * You can now change the tenancy of your VPC from dedicated to default with a single API operation. For more details refer to the documentation for changing VPC tenancy. +* `service/es`: Updates service API and documentation + * AWS Elasticsearch adds support for enabling slow log publishing. Using slow log publishing options customers can configure and enable index/query slow log publishing of their domain to preferred AWS Cloudwatch log group. +* `service/rds`: Updates service API and waiters + * Adds waiters for DBSnapshotAvailable and DBSnapshotDeleted. +* `service/waf`: Updates service API and documentation + * This release adds support for regular expressions as match conditions in rules, and support for geographical location by country of request IP address as a match condition in rules. +* `service/waf-regional`: Updates service API and documentation + +Release v1.12.10 (2017-10-12) +=== + +### Service Client Updates +* `service/codecommit`: Updates service API and documentation + * This release includes the DeleteBranch API and a change to the contents of a Commit object. +* `service/dms`: Updates service API and documentation + * This change includes addition of new optional parameter to an existing API +* `service/elasticbeanstalk`: Updates service API and documentation + * Added the ability to add, delete or update Tags +* `service/polly`: Updates service API + * Amazon Polly exposes two new voices: "Matthew" (US English) and "Takumi" (Japanese) +* `service/rds`: Updates service API and documentation + * You can now call DescribeValidDBInstanceModifications to learn what modifications you can make to your DB instance. You can use this information when you call ModifyDBInstance. + +Release v1.12.9 (2017-10-11) +=== + +### Service Client Updates +* `service/ecr`: Updates service API, documentation, and paginators + * Adds support for new API set used to manage Amazon ECR repository lifecycle policies. Amazon ECR lifecycle policies enable you to specify the lifecycle management of images in a repository. The configuration is a set of one or more rules, where each rule defines an action for Amazon ECR to apply to an image. This allows the automation of cleaning up unused images, for example expiring images based on age or status. A lifecycle policy preview API is provided as well, which allows you to see the impact of a lifecycle policy on an image repository before you execute it +* `service/email`: Updates service API and documentation + * Added content related to email template management and templated email sending operations. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.12.8 (2017-10-10) +=== + +### Service Client Updates +* `service/ec2`: Updates service API and documentation + * This release includes updates to AWS Virtual Private Gateway. +* `service/elasticloadbalancingv2`: Updates service API and documentation +* `service/opsworkscm`: Updates service API and documentation + * Provide engine specific information for node associations. + +Release v1.12.7 (2017-10-06) +=== + +### Service Client Updates +* `service/sqs`: Updates service documentation + * Documentation updates regarding availability of FIFO queues and miscellaneous corrections. + +Release v1.12.6 (2017-10-05) +=== + +### Service Client Updates +* `service/redshift`: Updates service API and documentation + * DescribeEventSubscriptions API supports tag keys and tag values as request parameters. + +Release v1.12.5 (2017-10-04) +=== + +### Service Client Updates +* `service/kinesisanalytics`: Updates service API and documentation + * Kinesis Analytics now supports schema discovery on objects in S3. Additionally, Kinesis Analytics now supports input data preprocessing through Lambda. +* `service/route53domains`: Updates service API and documentation + * Added a new API that checks whether a domain name can be transferred to Amazon Route 53. + +### SDK Bugs +* `service/s3/s3crypto`: Correct PutObjectRequest documentation ([#1568](https://github.com/aws/aws-sdk-go/pull/1568)) + * s3Crypto's PutObjectRequest docstring example was using an incorrect value. Corrected the type used in the example. +Release v1.12.4 (2017-10-03) +=== + +### Service Client Updates +* `service/ec2`: Updates service API, documentation, and waiters + * This release includes service updates to AWS VPN. +* `service/ssm`: Updates service API and documentation + * EC2 Systems Manager support for tagging SSM Documents. Also support for tag-based permissions to restrict access to SSM Documents based on these tags. + +Release v1.12.3 (2017-10-02) +=== + +### Service Client Updates +* `service/cloudhsm`: Updates service documentation and paginators + * Documentation updates for CloudHSM + +Release v1.12.2 (2017-09-29) +=== + +### Service Client Updates +* `service/appstream`: Updates service API and documentation + * Includes APIs for managing and accessing image builders, and deleting images. +* `service/codebuild`: Updates service API and documentation + * Adding support for Building GitHub Pull Requests in AWS CodeBuild +* `service/mturk-requester`: Updates service API and documentation +* `service/organizations`: Updates service API and documentation + * This release flags the HandshakeParty structure's Type and Id fields as 'required'. They effectively were required in the past, as you received an error if you did not include them. This is now reflected at the API definition level. +* `service/route53`: Updates service API and documentation + * This change allows customers to reset elements of health check. + +### SDK Bugs +* `private/protocol/query`: Fix query protocol handling of nested byte slices ([#1557](https://github.com/aws/aws-sdk-go/issues/1557)) + * Fixes the query protocol to correctly marshal nested []byte values of API operations. +* `service/s3`: Fix PutObject and UploadPart API to include ContentMD5 field ([#1559](https://github.com/aws/aws-sdk-go/pull/1559)) + * Fixes the SDK's S3 PutObject and UploadPart API code generation to correctly render the ContentMD5 field into the associated input types for these two API operations. + * Fixes [#1553](https://github.com/aws/aws-sdk-go/pull/1553) +Release v1.12.1 (2017-09-27) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/pinpoint`: Updates service API and documentation + * Added two new push notification channels: Amazon Device Messaging (ADM) and, for push notification support in China, Baidu Cloud Push. Added support for APNs auth via .p8 key file. Added operation for direct message deliveries to user IDs, enabling you to message an individual user on multiple endpoints. + +Release v1.12.0 (2017-09-26) +=== + +### SDK Bugs +* `API Marshaler`: Revert REST JSON and XML protocol marshaler improvements + * Bug [#1550](https://github.com/aws/aws-sdk-go/issues/1550) identified a missed condition in the Amazon Route 53 RESTXML protocol marshaling causing requests to that service to fail. Reverting the marshaler improvements until the bug can be fixed. + +Release v1.11.0 (2017-09-26) +=== + +### Service Client Updates +* `service/cloudformation`: Updates service API and documentation + * You can now prevent a stack from being accidentally deleted by enabling termination protection on the stack. If you attempt to delete a stack with termination protection enabled, the deletion fails and the stack, including its status, remains unchanged. You can enable termination protection on a stack when you create it. Termination protection on stacks is disabled by default. After creation, you can set termination protection on a stack whose status is CREATE_COMPLETE, UPDATE_COMPLETE, or UPDATE_ROLLBACK_COMPLETE. + +### SDK Features +* Add dep Go dependency management metadata files (#1544) + * Adds the Go `dep` dependency management metadata files to the SDK. + * Fixes [#1451](https://github.com/aws/aws-sdk-go/issues/1451) + * Fixes [#634](https://github.com/aws/aws-sdk-go/issues/634) +* `service/dynamodb/expression`: Add expression building utility for DynamoDB ([#1527](https://github.com/aws/aws-sdk-go/pull/1527)) + * Adds a new package, expression, to the SDK providing builder utilities to create DynamoDB expressions safely taking advantage of type safety. +* `API Marshaler`: Add generated marshalers for RESTXML protocol ([#1409](https://github.com/aws/aws-sdk-go/pull/1409)) + * Updates the RESTXML protocol marshaler to use generated code instead of reflection for REST XML based services. +* `API Marshaler`: Add generated marshalers for RESTJSON protocol ([#1547](https://github.com/aws/aws-sdk-go/pull/1547)) + * Updates the RESTJSON protocol marshaler to use generated code instead of reflection for REST JSON based services. + +### SDK Enhancements +* `private/protocol`: Update format of REST JSON and XMl benchmarks ([#1546](https://github.com/aws/aws-sdk-go/pull/1546)) + * Updates the format of the REST JSON and XML benchmarks to be readable. RESTJSON benchmarks were updated to more accurately bench building of the protocol. + +Release v1.10.51 (2017-09-22) +=== + +### Service Client Updates +* `service/config`: Updates service API and documentation +* `service/ecs`: Updates service API and documentation + * Amazon ECS users can now add and drop Linux capabilities to their containers through the use of docker's cap-add and cap-drop features. Customers can specify the capabilities they wish to add or drop for each container in their task definition. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rds`: Updates service documentation + * Documentation updates for rds + +Release v1.10.50 (2017-09-21) +=== + +### Service Client Updates +* `service/budgets`: Updates service API + * Including "DuplicateRecordException" in UpdateNotification and UpdateSubscriber. +* `service/ec2`: Updates service API and documentation + * Add EC2 APIs to copy Amazon FPGA Images (AFIs) within the same region and across multiple regions, delete AFIs, and modify AFI attributes. AFI attributes include name, description and granting/denying other AWS accounts to load the AFI. +* `service/logs`: Updates service API and documentation + * Adds support for associating LogGroups with KMS Keys. + +### SDK Bugs +* Fix greengrass service model being duplicated with different casing. ([#1541](https://github.com/aws/aws-sdk-go/pull/1541)) + * Fixes [#1540](https://github.com/aws/aws-sdk-go/issues/1540) + * Fixes [#1539](https://github.com/aws/aws-sdk-go/issues/1539) +Release v1.10.49 (2017-09-20) +=== + +### Service Client Updates +* `service/Greengrass`: Adds new service +* `service/appstream`: Updates service API and documentation + * API updates for supporting On-Demand fleets. +* `service/codepipeline`: Updates service API and documentation + * This change includes a PipelineMetadata object that is part of the output from the GetPipeline API that includes the Pipeline ARN, created, and updated timestamp. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rds`: Updates service API and documentation + * Introduces the --option-group-name parameter to the ModifyDBSnapshot CLI command. You can specify this parameter when you upgrade an Oracle DB snapshot. The same option group considerations apply when upgrading a DB snapshot as when upgrading a DB instance. For more information, see http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Oracle.html#USER_UpgradeDBInstance.Oracle.OGPG.OG +* `service/runtime.lex`: Updates service API and documentation + +Release v1.10.48 (2017-09-19) +=== + +### Service Client Updates +* `service/ec2`: Updates service API + * Fixed bug in EC2 clients preventing ElasticGpuSet from being set. + +### SDK Enhancements +* `aws/credentials`: Add EnvProviderName constant. ([#1531](https://github.com/aws/aws-sdk-go/issues/1531)) + * Adds the "EnvConfigCredentials" string literal as EnvProviderName constant. + * Fixes [#1444](https://github.com/aws/aws-sdk-go/issues/1444) + +Release v1.10.47 (2017-09-18) +=== + +### Service Client Updates +* `service/ec2`: Updates service API and documentation + * Amazon EC2 now lets you opt for Spot instances to be stopped in the event of an interruption instead of being terminated. Your Spot request can be fulfilled again by restarting instances from a previously stopped state, subject to availability of capacity at or below your preferred price. When you submit a persistent Spot request, you can choose from "terminate" or "stop" as the instance interruption behavior. Choosing "stop" will shutdown your Spot instances so you can continue from this stopped state later on. This feature is only available for instances with Amazon EBS volume as their root device. +* `service/email`: Updates service API and documentation + * Amazon Simple Email Service (Amazon SES) now lets you customize the domains used for tracking open and click events. Previously, open and click tracking links referred to destinations hosted on domains operated by Amazon SES. With this feature, you can use your own branded domains for capturing open and click events. +* `service/iam`: Updates service API and documentation + * A new API, DeleteServiceLinkedRole, submits a service-linked role deletion request and returns a DeletionTaskId, which you can use to check the status of the deletion. + +Release v1.10.46 (2017-09-15) +=== + +### Service Client Updates +* `service/apigateway`: Updates service API and documentation + * Add a new enum "REQUEST" to '--type ' field in the current create-authorizer API, and make "identitySource" optional. + +Release v1.10.45 (2017-09-14) +=== + +### Service Client Updates +* `service/codebuild`: Updates service API and documentation + * Supporting Parameter Store in environment variables for AWS CodeBuild +* `service/organizations`: Updates service documentation + * Documentation updates for AWS Organizations +* `service/servicecatalog`: Updates service API, documentation, and paginators + * This release of Service Catalog adds API support to copy products. + +Release v1.10.44 (2017-09-13) +=== + +### Service Client Updates +* `service/autoscaling`: Updates service API and documentation + * Customers can create Life Cycle Hooks at the time of creating Auto Scaling Groups through the CreateAutoScalingGroup API +* `service/batch`: Updates service documentation and examples + * Documentation updates for batch +* `service/ec2`: Updates service API + * You are now able to create and launch EC2 x1e.32xlarge instance, a new EC2 instance in the X1 family, in us-east-1, us-west-2, eu-west-1, and ap-northeast-1. x1e.32xlarge offers 128 vCPUs, 3,904 GiB of DDR4 instance memory, high memory bandwidth, large L3 caches, and leading reliability capabilities to boost the performance and reliability of in-memory applications. +* `service/events`: Updates service API and documentation + * Exposes ConcurrentModificationException as one of the valid exceptions for PutPermission and RemovePermission operation. + +### SDK Enhancements +* `service/autoscaling`: Fix documentation for PutScalingPolicy.AutoScalingGroupName [#1522](https://github.com/aws/aws-sdk-go/pull/1522) +* `service/s3/s3manager`: Clarify S3 Upload manager Concurrency config [#1521](https://github.com/aws/aws-sdk-go/pull/1521) + * Fixes [#1458](https://github.com/aws/aws-sdk-go/issues/1458) +* `service/dynamodb/dynamodbattribute`: Add support for time alias. [#1520](https://github.com/aws/aws-sdk-go/pull/1520) + * Related to [#1505](https://github.com/aws/aws-sdk-go/pull/1505) + +Release v1.10.43 (2017-09-12) +=== + +### Service Client Updates +* `service/ec2`: Updates service API + * Fixed bug in EC2 clients preventing HostOfferingSet from being set +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.10.42 (2017-09-12) +=== + +### Service Client Updates +* `service/devicefarm`: Updates service API and documentation + * DeviceFarm has added support for two features - RemoteDebugging and Customer Artifacts. Customers can now do remote Debugging on their Private Devices and can now retrieve custom files generated by their tests on the device and the device host (execution environment) on both public and private devices. + +Release v1.10.41 (2017-09-08) +=== + +### Service Client Updates +* `service/logs`: Updates service API and documentation + * Adds support for the PutResourcePolicy, DescribeResourcePolicy and DeleteResourcePolicy APIs. + +Release v1.10.40 (2017-09-07) +=== + +### Service Client Updates +* `service/application-autoscaling`: Updates service documentation +* `service/ec2`: Updates service API and documentation + * With Tagging support, you can add Key and Value metadata to search, filter and organize your NAT Gateways according to your organization's needs. +* `service/elasticloadbalancingv2`: Updates service API and documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/lex-models`: Updates service API and documentation +* `service/route53`: Updates service API and documentation + * You can configure Amazon Route 53 to log information about the DNS queries that Amazon Route 53 receives for your domains and subdomains. When you configure query logging, Amazon Route 53 starts to send logs to CloudWatch Logs. You can use various tools, including the AWS console, to access the query logs. + +Release v1.10.39 (2017-09-06) +=== + +### Service Client Updates +* `service/budgets`: Updates service API and documentation + * Add an optional "thresholdType" to notifications to support percentage or absolute value thresholds. + +Release v1.10.38 (2017-09-05) +=== + +### Service Client Updates +* `service/codestar`: Updates service API and documentation + * Added support to tag CodeStar projects. Tags can be used to organize and find CodeStar projects on key-value pairs that you can choose. For example, you could add a tag with a key of "Release" and a value of "Beta" to projects your organization is working on for an upcoming beta release. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.10.37 (2017-09-01) +=== + +### Service Client Updates +* `service/MobileHub`: Adds new service +* `service/gamelift`: Updates service API and documentation + * GameLift VPC resources can be peered with any other AWS VPC. R4 memory-optimized instances now available to deploy. +* `service/ssm`: Updates service API and documentation + * Adding KMS encryption support to SSM Inventory Resource Data Sync. Exposes the ClientToken parameter on SSM StartAutomationExecution to provide idempotent execution requests. + +Release v1.10.36 (2017-08-31) +=== + +### Service Client Updates +* `service/codebuild`: Updates service API, documentation, and examples + * The AWS CodeBuild HTTP API now provides the BatchDeleteBuilds operation, which enables you to delete existing builds. +* `service/ec2`: Updates service API and documentation + * Descriptions for Security Group Rules enables customers to be able to define a description for ingress and egress security group rules . The Descriptions for Security Group Rules feature supports one description field per Security Group rule for both ingress and egress rules . Descriptions for Security Group Rules provides a simple way to describe the purpose or function of a Security Group Rule allowing for easier customer identification of configuration elements . Prior to the release of Descriptions for Security Group Rules , customers had to maintain a separate system outside of AWS if they wanted to track Security Group Rule mapping and their purpose for being implemented. If a security group rule has already been created and you would like to update or change your description for that security group rule you can use the UpdateSecurityGroupRuleDescription API. +* `service/elasticloadbalancingv2`: Updates service API and documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/lex-models`: Updates service API and documentation + +### SDK Bugs +* `aws/signer/v4`: Revert [#1491](https://github.com/aws/aws-sdk-go/issues/1491) as change conflicts with an undocumented AWS v4 signature test case. + * Related to: [#1495](https://github.com/aws/aws-sdk-go/issues/1495). +Release v1.10.35 (2017-08-30) +=== + +### Service Client Updates +* `service/application-autoscaling`: Updates service API and documentation +* `service/organizations`: Updates service API and documentation + * The exception ConstraintViolationException now contains a new reason subcode MASTERACCOUNT_MISSING_CONTACT_INFO to make it easier to understand why attempting to remove an account from an Organization can fail. We also improved several other of the text descriptions and examples. + +Release v1.10.34 (2017-08-29) +=== + +### Service Client Updates +* `service/config`: Updates service API and documentation +* `service/ec2`: Updates service API and documentation + * Provides capability to add secondary CIDR blocks to a VPC. + +### SDK Bugs +* `aws/signer/v4`: Fix Signing Unordered Multi Value Query Parameters ([#1491](https://github.com/aws/aws-sdk-go/pull/1491)) + * Removes sorting of query string values when calculating v4 signing as this is not part of the spec. The spec only requires the keys, not values, to be sorted which is achieved by Query.Encode(). +Release v1.10.33 (2017-08-25) +=== + +### Service Client Updates +* `service/cloudformation`: Updates service API and documentation + * Rollback triggers enable you to have AWS CloudFormation monitor the state of your application during stack creation and updating, and to roll back that operation if the application breaches the threshold of any of the alarms you've specified. +* `service/gamelift`: Updates service API + * Update spelling of MatchmakingTicket status values for internal consistency. +* `service/rds`: Updates service API and documentation + * Option group options now contain additional properties that identify requirements for certain options. Check these properties to determine if your DB instance must be in a VPC or have auto minor upgrade turned on before you can use an option. Check to see if you can downgrade the version of an option after you have installed it. + +### SDK Enhancements +* `example/service/ec2`: Add EC2 list instances example ([#1492](https://github.com/aws/aws-sdk-go/pull/1492)) + +Release v1.10.32 (2017-08-25) +=== + +### Service Client Updates +* `service/rekognition`: Updates service API, documentation, and examples + * Update the enum value of LandmarkType and GenderType to be consistent with service response + +Release v1.10.31 (2017-08-23) +=== + +### Service Client Updates +* `service/appstream`: Updates service documentation + * Documentation updates for appstream +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.10.30 (2017-08-22) +=== + +### Service Client Updates +* `service/ssm`: Updates service API and documentation + * Changes to associations in Systems Manager State Manager can now be recorded. Previously, when you edited associations, you could not go back and review older association settings. Now, associations are versioned, and can be named using human-readable strings, allowing you to see a trail of association changes. You can also perform rate-based scheduling, which allows you to schedule associations more granularly. + +Release v1.10.29 (2017-08-21) +=== + +### Service Client Updates +* `service/firehose`: Updates service API, documentation, and paginators + * This change will allow customers to attach a Firehose delivery stream to an existing Kinesis stream directly. You no longer need a forwarder to move data from a Kinesis stream to a Firehose delivery stream. You can now run your streaming applications on your Kinesis stream and easily attach a Firehose delivery stream to it for data delivery to S3, Redshift, or Elasticsearch concurrently. +* `service/route53`: Updates service API and documentation + * Amazon Route 53 now supports CAA resource record type. A CAA record controls which certificate authorities are allowed to issue certificates for the domain or subdomain. + +Release v1.10.28 (2017-08-18) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.10.27 (2017-08-16) +=== + +### Service Client Updates +* `service/gamelift`: Updates service API and documentation + * The Matchmaking Grouping Service is a new feature that groups player match requests for a given game together into game sessions based on developer configured rules. + +### SDK Enhancements +* `aws/arn`: aws/arn: Package for parsing and producing ARNs ([#1463](https://github.com/aws/aws-sdk-go/pull/1463)) + * Adds the `arn` package for AWS ARN parsing and building. Use this package to build AWS ARNs for services such as outlined in the [documentation](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). + +### SDK Bugs +* `aws/signer/v4`: Correct V4 presign signature to include content sha25 in URL ([#1469](https://github.com/aws/aws-sdk-go/pull/1469)) + * Updates the V4 signer so that when a Presign is generated the `X-Amz-Content-Sha256` header is added to the query string instead of being required to be in the header. This allows you to generate presigned URLs for GET requests, e.g S3.GetObject that do not require additional headers to be set by the downstream users of the presigned URL. + * Related To: [#1467](https://github.com/aws/aws-sdk-go/issues/1467) + +Release v1.10.26 (2017-08-15) +=== + +### Service Client Updates +* `service/ec2`: Updates service API + * Fixed bug in EC2 clients preventing HostReservation from being set +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.10.25 (2017-08-14) +=== + +### Service Client Updates +* `service/AWS Glue`: Adds new service +* `service/batch`: Updates service API and documentation + * This release enhances the DescribeJobs API to include the CloudWatch logStreamName attribute in ContainerDetail and ContainerDetailAttempt +* `service/cloudhsmv2`: Adds new service + * CloudHSM provides hardware security modules for protecting sensitive data and cryptographic keys within an EC2 VPC, and enable the customer to maintain control over key access and use. This is a second-generation of the service that will improve security, lower cost and provide better customer usability. +* `service/elasticfilesystem`: Updates service API, documentation, and paginators + * Customers can create encrypted EFS file systems and specify a KMS master key to encrypt it with. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/mgh`: Adds new service + * AWS Migration Hub provides a single location to track migrations across multiple AWS and partner solutions. Using Migration Hub allows you to choose the AWS and partner migration tools that best fit your needs, while providing visibility into the status of your entire migration portfolio. Migration Hub also provides key metrics and progress for individual applications, regardless of which tools are being used to migrate them. For example, you might use AWS Database Migration Service, AWS Server Migration Service, and partner migration tools to migrate an application comprised of a database, virtualized web servers, and a bare metal server. Using Migration Hub will provide you with a single screen that shows the migration progress of all the resources in the application. This allows you to quickly get progress updates across all of your migrations, easily identify and troubleshoot any issues, and reduce the overall time and effort spent on your migration projects. Migration Hub is available to all AWS customers at no additional charge. You only pay for the cost of the migration tools you use, and any resources being consumed on AWS. +* `service/ssm`: Updates service API and documentation + * Systems Manager Maintenance Windows include the following changes or enhancements: New task options using Systems Manager Automation, AWS Lambda, and AWS Step Functions; enhanced ability to edit the targets of a Maintenance Window, including specifying a target name and description, and ability to edit the owner field; enhanced ability to edits tasks; enhanced support for Run Command parameters; and you can now use a --safe flag when attempting to deregister a target. If this flag is enabled when you attempt to deregister a target, the system returns an error if the target is referenced by any task. Also, Systems Manager now includes Configuration Compliance to scan your fleet of managed instances for patch compliance and configuration inconsistencies. You can collect and aggregate data from multiple AWS accounts and Regions, and then drill down into specific resources that aren't compliant. +* `service/storagegateway`: Updates service API and documentation + * Add optional field ForceDelete to DeleteFileShare api. + +Release v1.10.24 (2017-08-11) +=== + +### Service Client Updates +* `service/codedeploy`: Updates service API and documentation + * Adds support for specifying Application Load Balancers in deployment groups, for both in-place and blue/green deployments. +* `service/cognito-idp`: Updates service API and documentation +* `service/ec2`: Updates service API and documentation + * Provides customers an opportunity to recover an EIP that was released + +Release v1.10.23 (2017-08-10) +=== + +### Service Client Updates +* `service/clouddirectory`: Updates service API and documentation + * Enable BatchDetachPolicy +* `service/codebuild`: Updates service API + * Supporting Bitbucket as source type in AWS CodeBuild. + +Release v1.10.22 (2017-08-09) +=== + +### Service Client Updates +* `service/rds`: Updates service documentation + * Documentation updates for RDS. + +Release v1.10.21 (2017-08-09) +=== + +### Service Client Updates +* `service/elasticbeanstalk`: Updates service API and documentation + * Add support for paginating the result of DescribeEnvironments Include the ARN of described environments in DescribeEnvironments output + +### SDK Enhancements +* `aws`: Add pointer conversion utilities to transform int64 to time.Time [#1433](https://github.com/aws/aws-sdk-go/pull/1433) + * Adds `SecondsTimeValue` and `MillisecondsTimeValue` utilities. + +Release v1.10.20 (2017-08-01) +=== + +### Service Client Updates +* `service/codedeploy`: Updates service API and documentation + * AWS CodeDeploy now supports the use of multiple tag groups in a single deployment group (an intersection of tags) to identify the instances for a deployment. When you create or update a deployment group, use the new ec2TagSet and onPremisesTagSet structures to specify up to three groups of tags. Only instances that are identified by at least one tag in each of the tag groups are included in the deployment group. +* `service/config`: Updates service API and documentation +* `service/ec2`: Updates service waiters + * Ec2 SpotInstanceRequestFulfilled waiter update +* `service/elasticloadbalancingv2`: Updates service waiters +* `service/email`: Updates service API, documentation, paginators, and examples + * This update adds information about publishing email open and click events. This update also adds information about publishing email events to Amazon Simple Notification Service (Amazon SNS). +* `service/pinpoint`: Updates service API and documentation + * This release of the Pinpoint SDK enables App management - create, delete, update operations, Raw Content delivery for APNs and GCM campaign messages and From Address override. + +Release v1.10.19 (2017-08-01) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/inspector`: Updates service API, documentation, and paginators + * Inspector's StopAssessmentRun API has been updated with a new input option - stopAction. This request parameter can be set to either START_EVALUATION or SKIP_EVALUATION. START_EVALUATION (the default value, and the previous behavior) stops the AWS agent data collection and begins the results evaluation for findings generation based on the data collected so far. SKIP_EVALUATION cancels the assessment run immediately, after which no findings are generated. +* `service/ssm`: Updates service API and documentation + * Adds a SendAutomationSignal API to SSM Service. This API is used to send a signal to an automation execution to change the current behavior or status of the execution. + +Release v1.10.18 (2017-07-27) +=== + +### Service Client Updates +* `service/ec2`: Updates service API and documentation + * The CreateDefaultVPC API enables you to create a new default VPC . You no longer need to contact AWS support, if your default VPC has been deleted. +* `service/kinesisanalytics`: Updates service API and documentation + * Added additional exception types and clarified documentation. + +Release v1.10.17 (2017-07-27) +=== + +### Service Client Updates +* `service/dynamodb`: Updates service documentation and examples + * Corrected a typo. +* `service/ec2`: Updates service API and documentation + * Amazon EC2 Elastic GPUs allow you to easily attach low-cost graphics acceleration to current generation EC2 instances. With Amazon EC2 Elastic GPUs, you can configure the right amount of graphics acceleration to your particular workload without being constrained by fixed hardware configurations and limited GPU selection. +* `service/monitoring`: Updates service documentation + * This release adds high resolution features to CloudWatch, with support for Custom Metrics down to 1 second and Alarms down to 10 seconds. + +Release v1.10.16 (2017-07-26) +=== + +### Service Client Updates +* `service/clouddirectory`: Updates service API and documentation + * Cloud Directory adds support for additional batch operations. +* `service/cloudformation`: Updates service API and documentation + * AWS CloudFormation StackSets enables you to manage stacks across multiple accounts and regions. + +### SDK Enhancements +* `aws/signer/v4`: Optimize V4 signer's header duplicate space stripping. [#1417](https://github.com/aws/aws-sdk-go/pull/1417) + +Release v1.10.15 (2017-07-24) +=== + +### Service Client Updates +* `service/appstream`: Updates service API, documentation, and waiters + * Amazon AppStream 2.0 image builders and fleets can now access applications and network resources that rely on Microsoft Active Directory (AD) for authentication and permissions. This new feature allows you to join your streaming instances to your AD, so you can use your existing AD user management tools. +* `service/ec2`: Updates service API and documentation + * Spot Fleet tagging capability allows customers to automatically tag instances launched by Spot Fleet. You can use this feature to label or distinguish instances created by distinct Spot Fleets. Tagging your EC2 instances also enables you to see instance cost allocation by tag in your AWS bill. + +### SDK Bugs +* `aws/signer/v4`: Fix out of bounds panic in stripExcessSpaces [#1412](https://github.com/aws/aws-sdk-go/pull/1412) + * Fixes the out of bands panic in stripExcessSpaces caused by an incorrect calculation of the stripToIdx value. Simplified to code also. + * Fixes [#1411](https://github.com/aws/aws-sdk-go/issues/1411) +Release v1.10.14 (2017-07-20) +=== + +### Service Client Updates +* `service/elasticmapreduce`: Updates service API and documentation + * Amazon EMR now includes the ability to use a custom Amazon Linux AMI and adjustable root volume size when launching a cluster. + +Release v1.10.13 (2017-07-19) +=== + +### Service Client Updates +* `service/budgets`: Updates service API and documentation + * Update budget Management API's to list/create/update RI_UTILIZATION type budget. Update budget Management API's to support DAILY timeUnit for RI_UTILIZATION type budget. + +### SDK Enhancements +* `service/s3`: Use interfaces assertions instead of ValuesAtPath for S3 field lookups. [#1401](https://github.com/aws/aws-sdk-go/pull/1401) + * Improves the performance across the board for all S3 API calls by removing the usage of `ValuesAtPath` being used for every S3 API call. + +### SDK Bugs +* `aws/request`: waiter test bug + * waiters_test.go file would sometimes fail due to travis hiccups. This occurs because a test would sometimes fail the cancel check and succeed the timeout. However, the timeout check should never occur in that test. This fix introduces a new field that dictates how waiters will sleep. +Release v1.10.12 (2017-07-17) +=== + +### Service Client Updates +* `service/cognito-idp`: Updates service API and documentation +* `service/lambda`: Updates service API and documentation + * Lambda@Edge lets you run code closer to your end users without provisioning or managing servers. With Lambda@Edge, your code runs in AWS edge locations, allowing you to respond to your end users at the lowest latency. Your code is triggered by Amazon CloudFront events, such as requests to and from origin servers and viewers, and it is ready to execute at every AWS edge location whenever a request for content is received. You just upload your Node.js code to AWS Lambda and Lambda takes care of everything required to run and scale your code with high availability. You only pay for the compute time you consume - there is no charge when your code is not running. + +Release v1.10.11 (2017-07-14) +=== + +### Service Client Updates +* `service/discovery`: Updates service API and documentation + * Adding feature to the Export API for Discovery Service to allow filters for the export task to allow export based on per agent id. +* `service/ec2`: Updates service API + * New EC2 GPU Graphics instance +* `service/marketplacecommerceanalytics`: Updates service documentation + * Update to Documentation Model For New Report Cadence / Reformat of Docs + +Release v1.10.10 (2017-07-13) +=== + +### Service Client Updates +* `service/apigateway`: Updates service API and documentation + * Adds support for management of gateway responses. +* `service/ec2`: Updates service API and documentation + * X-ENI (or Cross-Account ENI) is a new feature that allows the attachment or association of Elastic Network Interfaces (ENI) between VPCs in different AWS accounts located in the same availability zone. With this new capability, service providers and partners can deliver managed solutions in a variety of new architectural patterns where the provider and consumer of the service are in different AWS accounts. +* `service/lex-models`: Updates service documentation + +Release v1.10.9 (2017-07-12) +=== + +### Service Client Updates +* `service/autoscaling`: Updates service API and documentation + * Auto Scaling now supports a new type of scaling policy called target tracking scaling policies that you can use to set up dynamic scaling for your application. +* `service/swf`: Updates service API, documentation, paginators, and examples + * Added support for attaching control data to Lambda tasks. Control data lets you attach arbitrary strings to your decisions and history events. + +Release v1.10.8 (2017-07-06) +=== + +### Service Client Updates +* `service/ds`: Updates service API, documentation, and paginators + * You can now improve the resilience and performance of your Microsoft AD directory by deploying additional domain controllers. Added UpdateNumberofDomainControllers API that allows you to update the number of domain controllers you want for your directory, and DescribeDomainControllers API that allows you to describe the detailed information of each domain controller of your directory. Also added the 'DesiredNumberOfDomainControllers' field to the DescribeDirectories API output for Microsoft AD. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/kinesis`: Updates service API and documentation + * You can now encrypt your data at rest within an Amazon Kinesis Stream using server-side encryption. Server-side encryption via AWS KMS makes it easy for customers to meet strict data management requirements by encrypting their data at rest within the Amazon Kinesis Streams, a fully managed real-time data processing service. +* `service/kms`: Updates service API and documentation + * This release of AWS Key Management Service introduces the ability to determine whether a key is AWS managed or customer managed. +* `service/ssm`: Updates service API and documentation + * Amazon EC2 Systems Manager now expands Patching support to Amazon Linux, Red Hat and Ubuntu in addition to the already supported Windows Server. + +Release v1.10.7 (2017-07-05) +=== + +### Service Client Updates +* `service/monitoring`: Updates service API and documentation + * We are excited to announce the availability of APIs and CloudFormation support for CloudWatch Dashboards. You can use the new dashboard APIs or CloudFormation templates to dynamically build and maintain dashboards to monitor your infrastructure and applications. There are four new dashboard APIs - PutDashboard, GetDashboard, DeleteDashboards, and ListDashboards APIs. PutDashboard is used to create a new dashboard or modify an existing one whereas GetDashboard is the API to get the details of a specific dashboard. ListDashboards and DeleteDashboards are used to get the names or delete multiple dashboards respectively. Getting started with dashboard APIs is similar to any other AWS APIs. The APIs can be accessed through AWS SDK or through CLI tools. +* `service/route53`: Updates service API and documentation + * Bug fix for InvalidChangeBatch exception. + +### SDK Enhancements +* `service/s3/s3manager`: adding cleanup function to batch objects [#1375](https://github.com/aws/aws-sdk-go/issues/1375) + * This enhancement will add an After field that will be called after each iteration of the batch operation. + +Release v1.10.6 (2017-06-30) +=== + +### Service Client Updates +* `service/marketplacecommerceanalytics`: Updates service documentation + * Documentation updates for AWS Marketplace Commerce Analytics. +* `service/s3`: Updates service API and documentation + * API Update for S3: Adding Object Tagging Header to MultipartUpload Initialization + +Release v1.10.5 (2017-06-29) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/events`: Updates service API and documentation + * CloudWatch Events now allows different AWS accounts to share events with each other through a new resource called event bus. Event buses accept events from AWS services, other AWS accounts and PutEvents API calls. Currently all AWS accounts have one default event bus. To send events to another account, customers simply write rules to match the events of interest and attach an event bus in the receiving account as the target to the rule. The PutTargets API has been updated to allow adding cross account event buses as targets. In addition, we have released two new APIs - PutPermission and RemovePermission - that enables customers to add/remove permissions to their default event bus. +* `service/gamelift`: Updates service API and documentation + * Allow developers to download GameLift fleet creation logs to assist with debugging. +* `service/ssm`: Updates service API and documentation + * Adding Resource Data Sync support to SSM Inventory. New APIs: * CreateResourceDataSync - creates a new resource data sync configuration, * ListResourceDataSync - lists existing resource data sync configurations, * DeleteResourceDataSync - deletes an existing resource data sync configuration. + +Release v1.10.4 (2017-06-27) +=== + +### Service Client Updates +* `service/servicecatalog`: Updates service API, documentation, and paginators + * Proper tagging of resources is critical to post-launch operations such as billing, cost allocation, and resource management. By using Service Catalog's TagOption Library, administrators can define a library of re-usable TagOptions that conform to company standards, and associate these with Service Catalog portfolios and products. Learn how to move your current tags to the new library, create new TagOptions, and view and associate your library items with portfolios and products. Understand how to ensure that the right tags are created on products launched through Service Catalog and how to provide users with defined selectable tags. + +### SDK Bugs +* `aws/signer/v4`: checking length on `stripExcessSpaces` [#1372](https://github.com/aws/aws-sdk-go/issues/1372) + * Fixes a bug where `stripExcessSpaces` did not check length against the slice. + * Fixes: [#1371](https://github.com/aws/aws-sdk-go/issues/1371) +Release v1.10.3 (2017-06-23) +=== + +### Service Client Updates +* `service/lambda`: Updates service API and documentation + * The Lambda Invoke API will now throw new exception InvalidRuntimeException (status code 502) for invokes with deprecated runtimes. + +Release v1.10.2 (2017-06-22) +=== + +### Service Client Updates +* `service/codepipeline`: Updates service API, documentation, and paginators + * A new API, ListPipelineExecutions, enables you to retrieve summary information about the most recent executions in a pipeline, including pipeline execution ID, status, start time, and last updated time. You can request information for a maximum of 100 executions. Pipeline execution data is available for the most recent 12 months of activity. +* `service/dms`: Updates service API and documentation + * Added tagging for DMS certificates. +* `service/elasticloadbalancing`: Updates service waiters +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/lightsail`: Updates service API and documentation + * This release adds a new nextPageToken property to the result of the GetOperationsForResource API. Developers can now get the next set of items in a list by making subsequent calls to GetOperationsForResource API with the token from the previous call. This release also deprecates the nextPageCount property, which previously returned null (use the nextPageToken property instead). This release also deprecates the customImageName property on the CreateInstancesRequest class, which was previously ignored by the API. +* `service/route53`: Updates service API and documentation + * This release reintroduces the HealthCheckInUse exception. + +Release v1.10.1 (2017-06-21) +=== + +### Service Client Updates +* `service/dax`: Adds new service + * Amazon DynamoDB Accelerator (DAX) is a fully managed, highly available, in-memory cache for DynamoDB that delivers up to a 10x performance improvement - from milliseconds to microseconds - even at millions of requests per second. DAX does all the heavy lifting required to add in-memory acceleration to your DynamoDB tables, without requiring developers to manage cache invalidation, data population, or cluster management. +* `service/route53`: Updates service API and documentation + * Amazon Route 53 now supports multivalue answers in response to DNS queries, which lets you route traffic approximately randomly to multiple resources, such as web servers. Create one multivalue answer record for each resource and, optionally, associate an Amazon Route 53 health check with each record, and Amazon Route 53 responds to DNS queries with up to eight healthy records. +* `service/ssm`: Updates service API, documentation, and paginators + * Adding hierarchy support to the SSM Parameter Store API. Added support tor tagging. New APIs: GetParameter - retrieves one parameter, DeleteParameters - deletes multiple parameters (max number 10), GetParametersByPath - retrieves parameters located in the hierarchy. Updated APIs: PutParameter - added ability to enforce parameter value by applying regex (AllowedPattern), DescribeParameters - modified to support Tag filtering. +* `service/waf`: Updates service API and documentation + * You can now create, edit, update, and delete a new type of WAF rule with a rate tracking component. +* `service/waf-regional`: Updates service API and documentation + +Release v1.10.0 (2017-06-20) +=== + +### Service Client Updates +* `service/workdocs`: Updates service API and documentation + * This release provides a new API to retrieve the activities performed by WorkDocs users. + +### SDK Features +* `aws/credentials/plugincreds`: Add support for Go plugin for credentials [#1320](https://github.com/aws/aws-sdk-go/pull/1320) + * Adds support for using plugins to retrieve credentials for API requests. This change adds a new package plugincreds under aws/credentials. See the `example/aws/credentials/plugincreds` folder in the SDK for example usage. + +Release v1.9.00 (2017-06-19) +=== + +### Service Client Updates +* `service/organizations`: Updates service API and documentation + * Improvements to Exception Modeling + +### SDK Features +* `service/s3/s3manager`: Adds batch operations to s3manager [#1333](https://github.com/aws/aws-sdk-go/pull/1333) + * Allows for batch upload, download, and delete of objects. Also adds the interface pattern to allow for easy traversal of objects. E.G `DownloadWithIterator`, `UploadWithIterator`, and `BatchDelete`. `BatchDelete` also contains a utility iterator using the `ListObjects` API to easily delete a list of objects. + +Release v1.8.44 (2017-06-16) +=== + +### Service Client Updates +* `service/xray`: Updates service API, documentation, and paginators + * Add a response time histogram to the services in response of GetServiceGraph API. + +Release v1.8.43 (2017-06-15) +=== + +### Service Client Updates +* `service/ec2`: Updates service API and documentation + * Adds API to describe Amazon FPGA Images (AFIs) available to customers, which includes public AFIs, private AFIs that you own, and AFIs owned by other AWS accounts for which you have load permissions. +* `service/ecs`: Updates service API and documentation + * Added support for cpu, memory, and memory reservation container overrides on the RunTask and StartTask APIs. +* `service/iot`: Updates service API and documentation + * Revert the last release: remove CertificatePem from DescribeCertificate API. +* `service/servicecatalog`: Updates service API, documentation, and paginators + * Added ProvisioningArtifactSummaries to DescribeProductAsAdmin's output to show the provisioning artifacts belong to the product. Allow filtering by SourceProductId in SearchProductsAsAdmin for AWS Marketplace products. Added a verbose option to DescribeProvisioningArtifact to display the CloudFormation template used to create the provisioning artifact.Added DescribeProvisionedProduct API. Changed the type of ProvisionedProduct's Status to be distinct from Record's Status. New ProvisionedProduct's Status are AVAILABLE, UNDER_CHANGE, TAINTED, ERROR. Changed Record's Status set of values to CREATED, IN_PROGRESS, IN_PROGRESS_IN_ERROR, SUCCEEDED, FAILED. + +### SDK Bugs +* `private/model/api`: Fix RESTXML support for XML Namespace [#1343](https://github.com/aws/aws-sdk-go/pull/1343) + * Fixes a bug with the SDK's generation of services using the REST XML protocol not annotating shape references with the XML Namespace attribute. + * Fixes [#1334](https://github.com/aws/aws-sdk-go/pull/1334) +Release v1.8.42 (2017-06-14) +=== + +### Service Client Updates +* `service/applicationautoscaling`: Updates service API and documentation +* `service/clouddirectory`: Updates service documentation + * Documentation update for Cloud Directory + +Release v1.8.41 (2017-06-13) +=== + +### Service Client Updates +* `service/configservice`: Updates service API + +Release v1.8.40 (2017-06-13) +=== + +### Service Client Updates +* `service/rds`: Updates service API and documentation + * API Update for RDS: this update enables copy-on-write, a new Aurora MySQL Compatible Edition feature that allows users to restore their database, and support copy of TDE enabled snapshot cross region. + +### SDK Bugs +* `aws/request`: Fix NewErrParamMinLen to use correct ParamMinLenErrCode [#1336](https://github.com/aws/aws-sdk-go/issues/1336) + * Fixes the `NewErrParamMinLen` function returning the wrong error code. `ParamMinLenErrCode` should be returned not `ParamMinValueErrCode`. + * Fixes [#1335](https://github.com/aws/aws-sdk-go/issues/1335) +Release v1.8.39 (2017-06-09) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/opsworks`: Updates service API and documentation + * Tagging Support for AWS OpsWorks Stacks + +Release v1.8.38 (2017-06-08) +=== + +### Service Client Updates +* `service/iot`: Updates service API and documentation + * In addition to using certificate ID, AWS IoT customers can now obtain the description of a certificate with the certificate PEM. +* `service/pinpoint`: Updates service API and documentation + * Starting today Amazon Pinpoint adds SMS Text and Email Messaging support in addition to Mobile Push Notifications, providing developers, product managers and marketers with multi-channel messaging capabilities to drive user engagement in their applications. Pinpoint also enables backend services and applications to message users directly and provides advanced user and app analytics to understand user behavior and messaging performance. +* `service/rekognition`: Updates service API and documentation + * API Update for AmazonRekognition: Adding RecognizeCelebrities API + +Release v1.8.37 (2017-06-07) +=== + +### Service Client Updates +* `service/codebuild`: Updates service API and documentation + * Add support to APIs for privileged containers. This change would allow performing privileged operations like starting the Docker daemon inside builds possible in custom docker images. +* `service/greengrass`: Adds new service + * AWS Greengrass is software that lets you run local compute, messaging, and device state synchronization for connected devices in a secure way. With AWS Greengrass, connected devices can run AWS Lambda functions, keep device data in sync, and communicate with other devices securely even when not connected to the Internet. Using AWS Lambda, Greengrass ensures your IoT devices can respond quickly to local events, operate with intermittent connections, and minimize the cost of transmitting IoT data to the cloud. + +Release v1.8.36 (2017-06-06) +=== + +### Service Client Updates +* `service/acm`: Updates service documentation + * Documentation update for AWS Certificate Manager. +* `service/cloudfront`: Updates service documentation + * Doc update to fix incorrect prefix in S3OriginConfig +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/iot`: Updates service API + * Update client side validation for SalesForce action. + +Release v1.8.35 (2017-06-05) +=== + +### Service Client Updates +* `service/appstream`: Updates service API and documentation + * AppStream 2.0 Custom Security Groups allows you to easily control what network resources your streaming instances and images have access to. You can assign up to 5 security groups per Fleet to control the inbound and outbound network access to your streaming instances to specific IP ranges, network protocols, or ports. +* `service/iot`: Updates service API, documentation, paginators, and examples + * Added Salesforce action to IoT Rules Engine. + +Release v1.8.34 (2017-06-02) +=== + +### Service Client Updates +* `service/kinesisanalytics`: Updates service API, documentation, and paginators + * Kinesis Analytics publishes error messages CloudWatch logs in case of application misconfigurations +* `service/workdocs`: Updates service API and documentation + * This release includes new APIs to manage tags and custom metadata on resources and also new APIs to add and retrieve comments at the document level. + +Release v1.8.33 (2017-06-01) +=== + +### Service Client Updates +* `service/codedeploy`: Updates service API and documentation + * AWS CodeDeploy has improved how it manages connections to GitHub accounts and repositories. You can now create and store up to 25 connections to GitHub accounts in order to associate AWS CodeDeploy applications with GitHub repositories. Each connection can support multiple repositories. You can create connections to up to 25 different GitHub accounts, or create more than one connection to a single account. The ListGitHubAccountTokenNames command has been introduced to retrieve the names of stored connections to GitHub accounts that you have created. The name of the connection to GitHub used for an AWS CodeDeploy application is also included in the ApplicationInfo structure. Two new fields, lastAttemptedDeployment and lastSuccessfulDeployment, have been added to DeploymentGroupInfo to improve the handling of deployment group information in the AWS CodeDeploy console. Information about these latest deployments can also be retrieved using the GetDeploymentGroup and BatchGetDeployment group requests. Also includes a region update (us-gov-west-1). +* `service/cognitoidentityprovider`: Updates service API, documentation, and paginators +* `service/elbv2`: Updates service API and documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/lexmodelbuildingservice`: Updates service documentation and examples + +### SDK Enhancements +* `aws/defaults`: Exports shared credentials and config default filenames used by the SDK. [#1308](https://github.com/aws/aws-sdk-go/pull/1308) + * Adds SharedCredentialsFilename and SharedConfigFilename functions to defaults package. + +### SDK Bugs +* `aws/credentials`: Fixes shared credential provider's default filename on Windows. [#1308](https://github.com/aws/aws-sdk-go/pull/1308) + * The shared credentials provider would attempt to use the wrong filename on Windows if the `HOME` environment variable was defined. +* `service/s3/s3manager`: service/s3/s3manager: Fix Downloader ignoring Range get parameter [#1311](https://github.com/aws/aws-sdk-go/pull/1311) + * Fixes the S3 Download Manager ignoring the GetObjectInput's Range parameter. If this parameter is provided it will force the downloader to fallback to a single GetObject request disabling concurrency and automatic part size gets. + * Fixes [#1296](https://github.com/aws/aws-sdk-go/issues/1296) +Release v1.8.32 (2017-05-31) +=== + +### Service Client Updates +* `service/rds`: Updates service API and documentation + * Amazon RDS customers can now easily and quickly stop and start their DB instances. + +Release v1.8.31 (2017-05-30) +=== + +### Service Client Updates +* `service/clouddirectory`: Updates service API, documentation, and paginators + * Cloud Directory has launched support for Typed Links, enabling customers to create object-to-object relationships that are not hierarchical in nature. Typed Links enable customers to quickly query for data along these relationships. Customers can also enforce referential integrity using Typed Links, ensuring data in use is not inadvertently deleted. +* `service/s3`: Updates service paginators and examples + * New example snippets for Amazon S3. + +Release v1.8.30 (2017-05-25) +=== + +### Service Client Updates +* `service/appstream`: Updates service API and documentation + * Support added for persistent user storage, backed by S3. +* `service/rekognition`: Updates service API and documentation + * Updated the CompareFaces API response to include orientation information, unmatched faces, landmarks, pose, and quality of the compared faces. + +Release v1.8.29 (2017-05-24) +=== + +### Service Client Updates +* `service/iam`: Updates service API + * The unique ID and access key lengths were extended from 32 to 128 +* `service/storagegateway`: Updates service API and documentation + * Two Storage Gateway data types, Tape and TapeArchive, each have a new response element, TapeUsedInBytes. This element helps you manage your virtual tapes. By using TapeUsedInBytes, you can see the amount of data written to each virtual tape. +* `service/sts`: Updates service API, documentation, and paginators + * The unique ID and access key lengths were extended from 32 to 128. + +Release v1.8.28 (2017-05-23) +=== + +### Service Client Updates +* `service/databasemigrationservice`: Updates service API, documentation, paginators, and examples + * This release adds support for using Amazon S3 and Amazon DynamoDB as targets for database migration, and using MongoDB as a source for database migration. For more information, see the AWS Database Migration Service documentation. + +Release v1.8.27 (2017-05-22) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/resourcegroupstaggingapi`: Updates service API, documentation, and paginators + * You can now specify the number of resources returned per page in GetResources operation, as an optional parameter, to easily manage the list of resources returned by your queries. + +### SDK Bugs +* `aws/request`: Add support for PUT temporary redirects (307) [#1283](https://github.com/aws/aws-sdk-go/issues/1283) + * Adds support for Go 1.8's GetBody function allowing the SDK's http request using PUT and POST methods to be redirected with temporary redirects with 307 status code. + * Fixes: [#1267](https://github.com/aws/aws-sdk-go/issues/1267) +* `aws/request`: Add handling for retrying temporary errors during unmarshal [#1289](https://github.com/aws/aws-sdk-go/issues/1289) + * Adds support for retrying temporary errors that occur during unmarshaling of a request's response body. + * Fixes: [#1275](https://github.com/aws/aws-sdk-go/issues/1275) +Release v1.8.26 (2017-05-18) +=== + +### Service Client Updates +* `service/athena`: Adds new service + * This release adds support for Amazon Athena. Amazon Athena is an interactive query service that makes it easy to analyze data in Amazon S3 using standard SQL. Athena is serverless, so there is no infrastructure to manage, and you pay only for the queries that you run. +* `service/lightsail`: Updates service API, documentation, and paginators + * This release adds new APIs that make it easier to set network port configurations on Lightsail instances. Developers can now make a single request to both open and close public ports on an instance using the PutInstancePublicPorts operation. + +### SDK Bugs +* `aws/request`: Fix logging from reporting wrong retry request errors #1281 + * Fixes the SDK's retry request logging to report the the actual error that occurred, not a stubbed Unknown error message. + * Fixes the SDK's response logger to not output the response log multiple times per retry. +Release v1.8.25 (2017-05-17) +=== + +### Service Client Updates +* `service/autoscaling`: Updates service documentation, paginators, and examples + * Various Auto Scaling documentation updates +* `service/cloudwatchevents`: Updates service documentation + * Various CloudWatch Events documentation updates. +* `service/cloudwatchlogs`: Updates service documentation and paginators + * Various CloudWatch Logs documentation updates. +* `service/polly`: Updates service API + * Amazon Polly adds new German voice "Vicki" + +Release v1.8.24 (2017-05-16) +=== + +### Service Client Updates +* `service/codedeploy`: Updates service API and documentation + * This release introduces the previousRevision field in the responses to the GetDeployment and BatchGetDeployments actions. previousRevision provides information about the application revision that was deployed to the deployment group before the most recent successful deployment. Also, the fileExistsBehavior parameter has been added for CreateDeployment action requests. In the past, if the AWS CodeDeploy agent detected files in a target location that weren't part of the application revision from the most recent successful deployment, it would fail the current deployment by default. This new parameter provides options for how the agent handles these files: fail the deployment, retain the content, or overwrite the content. +* `service/gamelift`: Updates service API and documentation + * Allow developers to specify how metrics are grouped in CloudWatch for their GameLift fleets. Developers can also specify how many concurrent game sessions activate on a per-instance basis. +* `service/inspector`: Updates service API, documentation, paginators, and examples + * Adds ability to produce an assessment report that includes detailed and comprehensive results of a specified assessment run. +* `service/kms`: Updates service documentation + * Update documentation for KMS. + +Release v1.8.23 (2017-05-15) +=== + +### Service Client Updates +* `service/ssm`: Updates service API and documentation + * UpdateAssociation API now supports updating document name and targets of an association. GetAutomationExecution API can return FailureDetails as an optional field to the StepExecution Object, which contains failure type, failure stage as well as other failure related information for a failed step. + +### SDK Enhancements +* `aws/session`: SDK should be able to load multiple custom shared config files. [#1258](https://github.com/aws/aws-sdk-go/issues/1258) + * This change adds a `SharedConfigFiles` field to the `session.Options` type that allows you to specify the files, and their order, the SDK will use for loading shared configuration and credentials from when the `Session` is created. Use the `NewSessionWithOptions` Session constructor to specify these options. You'll also most likely want to enable support for the shared configuration file's additional attributes by setting `session.Option`'s `SharedConfigState` to `session.SharedConfigEnabled`. + +Release v1.8.22 (2017-05-11) +=== + +### Service Client Updates +* `service/elb`: Updates service API, documentation, and paginators +* `service/elbv2`: Updates service API and documentation +* `service/lexmodelbuildingservice`: Updates service API and documentation +* `service/organizations`: Updates service API, documentation, paginators, and examples + * AWS Organizations APIs that return an Account object now include the email address associated with the account’s root user. + +Release v1.8.21 (2017-05-09) +=== + +### Service Client Updates +* `service/codestar`: Updates service documentation + * Updated documentation for AWS CodeStar. +* `service/workspaces`: Updates service API, documentation, and paginators + * Doc-only Update for WorkSpaces + +Release v1.8.20 (2017-05-04) +=== + +### Service Client Updates +* `service/ecs`: Updates service API, documentation, and paginators + * Exposes container instance registration time in ECS:DescribeContainerInstances. +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/marketplaceentitlementservice`: Adds new service +* `service/lambda`: Updates service API and documentation + * Support for UpdateFunctionCode DryRun option + +Release v1.8.19 (2017-04-28) +=== + +### Service Client Updates +* `service/cloudformation`: Updates service waiters and paginators + * Adding back the removed waiters and paginators. + +Release v1.8.18 (2017-04-28) +=== + +### Service Client Updates +* `service/cloudformation`: Updates service API, documentation, waiters, paginators, and examples + * API update for CloudFormation: New optional parameter ClientRequestToken which can be used as an idempotency token to safely retry certain operations as well as tagging StackEvents. +* `service/rds`: Updates service API, documentation, and examples + * The DescribeDBClusterSnapshots API now returns a SourceDBClusterSnapshotArn field which identifies the source DB cluster snapshot of a copied snapshot. +* `service/rekognition`: Updates service API + * Fix for missing file type check +* `service/snowball`: Updates service API, documentation, and paginators + * The Snowball API has a new exception that can be thrown for list operation requests. +* `service/sqs`: Updates service API, documentation, and paginators + * Adding server-side encryption (SSE) support to SQS by integrating with AWS KMS; adding new queue attributes to SQS CreateQueue, SetQueueAttributes and GetQueueAttributes APIs to support SSE. + +Release v1.8.17 (2017-04-26) +=== + +### Service Client Updates +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rds`: Updates service API and documentation + * With Amazon Relational Database Service (Amazon RDS) running MySQL or Amazon Aurora, you can now authenticate to your DB instance using IAM database authentication. + +Release v1.8.16 (2017-04-21) +=== + +### Service Client Updates +* `service/appstream`: Updates service API, documentation, and paginators + * The new feature named "Default Internet Access" will enable Internet access from AppStream 2.0 instances - image builders and fleet instances. Admins will check a flag either through AWS management console for AppStream 2.0 or through API while creating an image builder or while creating/updating a fleet. +* `service/kinesis`: Updates service API, documentation, waiters, and paginators + * Adds a new waiter, StreamNotExists, to Kinesis. + +### SDK Enhancements +* `aws/endpoints`: Add utilities improving endpoints lookup (#1218) + * Adds several utilities to the endpoints packages to make looking up partitions, regions, and services easier. + * Fixes #994 + +### SDK Bugs +* `private/protocol/xml/xmlutil`: Fix unmarshaling dropping errors (#1219) + * The XML unmarshaler would drop any serialization or body read error that occurred on the floor effectively hiding any errors that would occur. + * Fixes #1205 +Release v1.8.15 (2017-04-20) +=== + +### Service Client Updates +* `service/devicefarm`: Updates service API and documentation + * API Update for AWS Device Farm: Support for Deals and Promotions +* `service/directconnect`: Updates service documentation + * Documentation updates for AWS Direct Connect. +* `service/elbv2`: Updates service waiters +* `service/kms`: Updates service documentation and examples + * Doc-only update for Key Management Service (KMS): Update docs for GrantConstraints and GenerateRandom +* `service/route53`: Updates service documentation + * Release notes: SDK documentation now includes examples for ChangeResourceRecordSets for all types of resource record set, such as weighted, alias, and failover. +* `service/route53domains`: Updates service API, documentation, and paginators + * Adding examples and other documentation updates. + +### SDK Enhancements +* `service/s3`: Add utilities to make getting a bucket's region easier (#1207) + * Adds two features which make it easier to get a bucket's region, `s3.NormalizeBucketLocation` and `s3manager.GetBucketRegion`. + +### SDK Bugs +* `service/s3`: Fix HeadObject's incorrect documented error codes (#1213) + * The HeadObject's model incorrectly states that the operation can return the NoSuchKey error code. + * Fixes #1208 + +Release v1.8.14 (2017-04-19) +=== + +### Service Client Updates +* `service/apigateway`: Updates service API and documentation + * Add support for "embed" property. +* `service/codestar`: Adds new service + * AWS CodeStar is a cloud-based service for creating, managing, and working with software development projects on AWS. An AWS CodeStar project creates and integrates AWS services for your project development toolchain. AWS CodeStar also manages the permissions required for project users. +* `service/ec2`: Updates service API and documentation + * Adds support for creating an Amazon FPGA Image (AFI) from a specified design checkpoint (DCP). +* `service/iam`: Updates service API and documentation + * This changes introduces a new IAM role type, Service Linked Role, which works like a normal role but must be managed via services' control. +* `service/lambda`: Updates service API and documentation + * Lambda integration with CloudDebugger service to enable customers to enable tracing for the Lambda functions and send trace information to the CloudDebugger service. +* `service/lexmodelbuildingservice`: Adds new service +* `service/polly`: Updates service API, documentation, and paginators + * API Update for Amazon Polly: Add support for speech marks +* `service/rekognition`: Updates service API and documentation + * Given an image, the API detects explicit or suggestive adult content in the image and returns a list of corresponding labels with confidence scores, as well as a taxonomy (parent-child relation) for each label. + +Release v1.8.13 (2017-04-18) +=== + +### Service Client Updates +* `service/lambda`: Updates service API and documentation + * You can use tags to group and filter your Lambda functions, making it easier to analyze them for billing allocation purposes. For more information, see Tagging Lambda Functions. You can now write or upgrade your Lambda functions using Python version 3.6. For more information, see Programming Model for Authoring Lambda Functions in Python. Note: Features will be rolled out in the US regions on 4/19. + +### SDK Enhancements +* `aws/request`: add support for appengine's custom standard library (#1190) + * Remove syscall error checking on appengine platforms. + +Release v1.8.12 (2017-04-11) +=== + +### Service Client Updates +* `service/apigateway`: Updates service API and documentation + * API Gateway request validators +* `service/batch`: Updates service API and documentation + * API Update for AWS Batch: Customer provided AMI for MANAGED Compute Environment +* `service/gamelift`: Updates service API and documentation + * Allows developers to utilize an improved workflow when calling our Queues API and introduces a new feature that allows developers to specify a maximum allowable latency per Queue. +* `service/opsworks`: Updates service API, documentation, and paginators + * Cloudwatch Logs agent configuration can now be attached to OpsWorks Layers using CreateLayer and UpdateLayer. OpsWorks will then automatically install and manage the CloudWatch Logs agent on the instances part of the OpsWorks Layer. + +### SDK Bugs +* `aws/client`: Fix clients polluting handler list (#1197) + * Fixes the clients potentially polluting the passed in handler list with the client's customizations. This change ensures every client always works with a clean copy of the request handlers and it cannot pollute the handlers back upstream. + * Fixes #1184 +* `aws/request`: Fix waiter error match condition (#1195) + * Fixes the waiters's matching overwriting the request's err, effectively ignoring the error condition. This broke waiters with the FailureWaiterState matcher state. +Release v1.8.11 (2017-04-07) +=== + +### Service Client Updates +* `service/redshift`: Updates service API, documentation, and paginators + * This update adds the GetClusterCredentials API which is used to get temporary login credentials to the cluster. AccountWithRestoreAccess now has a new member AccountAlias, this is the identifier of the AWS support account authorized to restore the specified snapshot. This is added to support the feature where the customer can share their snapshot with the Amazon Redshift Support Account without having to manually specify the AWS Redshift Service account ID on the AWS Console/API. + +Release v1.8.10 (2017-04-06) +=== + +### Service Client Updates +* `service/elbv2`: Updates service documentation + +Release v1.8.9 (2017-04-05) +=== + +### Service Client Updates +* `service/elasticache`: Updates service API, documentation, paginators, and examples + * ElastiCache added support for testing the Elasticache Multi-AZ feature with Automatic Failover. + +Release v1.8.8 (2017-04-04) +=== + +### Service Client Updates +* `service/cloudwatch`: Updates service API, documentation, and paginators + * Amazon Web Services announced the immediate availability of two additional alarm configuration rules for Amazon CloudWatch Alarms. The first rule is for configuring missing data treatment. Customers have the options to treat missing data as alarm threshold breached, alarm threshold not breached, maintain alarm state and the current default treatment. The second rule is for alarms based on percentiles metrics that can trigger unnecassarily if the percentile is calculated from a small number of samples. The new rule can treat percentiles with low sample counts as same as missing data. If the first rule is enabled, the same treatment will be applied when an alarm encounters a percentile with low sample counts. + +Release v1.8.7 (2017-04-03) +=== + +### Service Client Updates +* `service/lexruntimeservice`: Updates service API and documentation + * Adds support to PostContent for speech input + +### SDK Enhancements +* `aws/request`: Improve handler copy, push back, push front performance (#1171) + * Minor optimization to the handler list's handling of copying and pushing request handlers to the handler list. +* Update codegen header to use Go std wording (#1172) + * Go recently accepted the proposal for standard generated file header wording in, https://golang.org/s/generatedcode. + +### SDK Bugs +* `service/dynamodb`: Fix DynamoDB using custom retryer (#1170) + * Fixes (#1139) the DynamoDB service client clobbering any custom retryer that was passed into the service client or Session's config. +Release v1.8.6 (2017-04-01) +=== + +### Service Client Updates +* `service/clouddirectory`: Updates service API and documentation + * ListObjectAttributes now supports filtering by facet. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.8.5 (2017-03-30) +=== + +### Service Client Updates +* `service/cloudformation`: Updates service waiters and paginators + * Adding paginators for ListExports and ListImports +* `service/cloudfront`: Adds new service + * Amazon CloudFront now supports user configurable HTTP Read and Keep-Alive Idle Timeouts for your Custom Origin Servers +* `service/configservice`: Updates service documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/resourcegroupstaggingapi`: Adds new service +* `service/storagegateway`: Updates service API and documentation + * File gateway mode in AWS Storage gateway provides access to objects in S3 as files on a Network File System (NFS) mount point. Once a file share is created, any changes made externally to the S3 bucket will not be reflected by the gateway. Using the cache refresh feature in this update, the customer can trigger an on-demand scan of the keys in their S3 bucket and refresh the file namespace cached on the gateway. It takes as an input the fileShare ARN and refreshes the cache for only that file share. Additionally there is new functionality on file gateway that allows you configure what squash options they would like on their file share, this allows a customer to configure their gateway to not squash root permissions. This can be done by setting options in NfsOptions for CreateNfsFileShare and UpdateNfsFileShare APIs. + +Release v1.8.4 (2017-03-28) +=== + +### Service Client Updates +* `service/batch`: Updates service API, documentation, and paginators + * Customers can now provide a retryStrategy as part of the RegisterJobDefinition and SubmitJob API calls. The retryStrategy object has a number value for attempts. This is the number of non successful executions before a job is considered FAILED. In addition, the JobDetail object now has an attempts field and shows all execution attempts. +* `service/ec2`: Updates service API and documentation + * Customers can now tag their Amazon EC2 Instances and Amazon EBS Volumes at + the time of their creation. You can do this from the EC2 Instance launch + wizard or through the RunInstances or CreateVolume APIs. By tagging + resources at the time of creation, you can eliminate the need to run custom + tagging scripts after resource creation. In addition, you can now set + resource-level permissions on the CreateVolume, CreateTags, DeleteTags, and + the RunInstances APIs. This allows you to implement stronger security + policies by giving you more granular control over which users and groups + have access to these APIs. You can also enforce the use of tagging and + control what tag keys and values are set on your resources. When you combine + tag usage and resource-level IAM policies together, you can ensure your + instances and volumes are properly secured upon creation and achieve more + accurate cost allocation reporting. These new features are provided at no + additional cost. + +### SDK Enhancements +* `aws/request`: Add retry support for RequestTimeoutException (#1158) + * Adds support for retrying RequestTimeoutException error code that is returned by some services. + +### SDK Bugs +* `private/model/api`: Fix Waiter and Paginators panic on nil param inputs (#1157) + * Corrects the code generation for Paginators and waiters that caused a panic if nil input parameters were used with the operations. +Release v1.8.3 (2017-03-27) +=== + +## Service Client Updates +* `service/ssm`: Updates service API, documentation, and paginators + * Updated validation rules for SendCommand and RegisterTaskWithMaintenanceWindow APIs. +Release v1.8.2 (2017-03-24) +=== + +Service Client Updates +--- +* `service/applicationautoscaling`: Updates service API, documentation, and paginators + * Application AutoScaling is launching support for a new target resource (AppStream 2.0 Fleets) as a scalable target. +* `service/cloudtrail`: Updates service API and documentation + * Doc-only Update for CloudTrail: Add required parameters for GetEventSelectors and PutEventSelectors + +Release v1.8.1 (2017-03-23) +=== + +Service Client Updates +--- +* `service/applicationdiscoveryservice`: Updates service API, documentation, and paginators + * Adds export configuration options to the AWS Discovery Service API. +* `service/elbv2`: Updates waiters +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/lambda`: Updates service API and paginators + * Adds support for new runtime Node.js v6.10 for AWS Lambda service + +Release v1.8.0 (2017-03-22) +=== + +Service Client Updates +--- +* `service/codebuild`: Updates service documentation +* `service/directconnect`: Updates service API + * Deprecated DescribeConnectionLoa, DescribeInterconnectLoa, AllocateConnectionOnInterconnect and DescribeConnectionsOnInterconnect operations in favor of DescribeLoa, DescribeLoa, AllocateHostedConnection and DescribeHostedConnections respectively. +* `service/marketplacecommerceanalytics`: Updates service API, documentation, and paginators + * This update adds a new data set, us_sales_and_use_tax_records, which enables AWS Marketplace sellers to programmatically access to their U.S. Sales and Use Tax report data. +* `service/pinpoint`: Updates service API and documentation + * Amazon Pinpoint User Segmentation + * Added ability to segment endpoints by user attributes in addition to endpoint attributes. Amazon Pinpoint Event Stream Preview + * Added functionality to publish raw app analytics and campaign events data as events streams to Kinesis and Kinesis Firehose + * The feature provides developers with increased flexibility of exporting raw events to S3, Redshift, Elasticsearch using a Kinesis Firehose stream or enable real time event processing use cases using a Kinesis stream +* `service/rekognition`: Updates service documentation. + +SDK Features +--- +* `aws/request`: Add support for context.Context to SDK API operation requests (#1132) + * Adds support for context.Context to the SDK by adding `WithContext` methods for each API operation, Paginators and Waiters. e.g `PutObjectWithContext`. This change also adds the ability to provide request functional options to the method calls instead of requiring you to use the `Request` API operation method (e.g `PutObjectRequest`). + * Adds a `Complete` Request handler list that will be called ever time a request is completed. This includes both success and failure. Complete will only be called once per API operation request. + * `private/waiter` package moved from the private group to `aws/request/waiter` and made publicly available. + * Adds Context support to all API operations, Waiters(WaitUntil) and Paginators(Pages) methods. + * Adds Context support for s3manager and s3crypto clients. + +SDK Enhancements +--- +* `aws/signer/v4`: Adds support for unsigned payload signer config (#1130) + * Adds configuration option to the v4.Signer to specify the request's body should not be signed. This will only correclty function on services that support unsigned payload. e.g. S3, Glacier. + +SDK Bug Fixes +--- +* `service/s3`: Fix S3 HostID to be available in S3 request error message (#1131) + * Adds a new type s3.RequestFailure which exposes the S3 HostID value from a S3 API operation response. This is helpful when you have an error with S3, and need to contact support. Both RequestID and HostID are needed. +* `private/model/api`: Do not return a link if uid is empty (#1133) + * Fixes SDK's doc generation to not generate API reference doc links if the SDK us unable to create a valid link. +* `aws/request`: Optimization to handler list copy to prevent multiple alloc calls. (#1134) +Release v1.7.9 (2017-03-13) +=== + +Service Client Updates +--- +* `service/devicefarm`: Updates service API, documentation, paginators, and examples + * Network shaping allows users to simulate network connections and conditions while testing their Android, iOS, and web apps with AWS Device Farm. +* `service/cloudwatchevents`: Updates service API, documentation, and examples + +SDK Enhancement +=== +* `aws/session`: Add support for side loaded CA bundles (#1117) + * Adds supports for side loading Certificate Authority bundle files to the SDK using AWS_CA_BUNDLE environment variable or CustomCABundle session option. +* `service/s3/s3crypto`: Add support for AES/CBC/PKCS5Padding (#1124) + +SDK Bug +=== +* `service/rds`: Fixing issue when not providing `SourceRegion` on cross +region operations (#1127) +* `service/rds`: Enables cross region for `CopyDBClusterSnapshot` and +`CreateDBCluster` (#1128) + +Release v1.7.8 (2017-03-10) +=== + +Service Client Updates +--- +* `service/codedeploy`: Updates service paginators + * Add paginators for Codedeploy +* `service/emr`: Updates service API, documentation, and paginators + * This release includes support for instance fleets in Amazon EMR. + +Release v1.7.7 (2017-03-09) +=== + +Service Client Updates +--- +* `service/apigateway`: Updates service API, documentation, and paginators + * API Gateway has added support for ACM certificates on custom domain names. Both Amazon-issued certificates and uploaded third-part certificates are supported. +* `service/clouddirectory`: Updates service API, documentation, and paginators + * Introduces a new Cloud Directory API that enables you to retrieve all available parent paths for any type of object (a node, leaf node, policy node, and index node) in a hierarchy. + +Release v1.7.6 (2017-03-09) +=== + +Service Client Updates +--- +* `service/organizations`: Updates service documentation and examples + * Doc-only Update for Organizations: Add SDK Code Snippets +* `service/workdocs`: Adds new service + * The Administrative SDKs for Amazon WorkDocs provides full administrator level access to WorkDocs site resources, allowing developers to integrate their applications to manage WorkDocs users, content and permissions programmatically + +Release v1.7.5 (2017-03-08) +=== + +Service Client Updates +--- +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rds`: Updates service API and documentation + * Add support to using encrypted clusters as cross-region replication masters. Update CopyDBClusterSnapshot API to support encrypted cross region copy of Aurora cluster snapshots. + +Release v1.7.4 (2017-03-06) +=== + +Service Client Updates +--- +* `service/budgets`: Updates service API and paginators + * When creating or editing a budget via the AWS Budgets API you can define notifications that are sent to subscribers when the actual or forecasted value for cost or usage exceeds the notificationThreshold associated with the budget notification object. Starting today, the maximum allowed value for the notificationThreshold was raised from 100 to 300. This change was made to give you more flexibility when setting budget notifications. +* `service/cloudtrail`: Updates service documentation and paginators + * Doc-only update for AWSCloudTrail: Updated links/descriptions +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/opsworkscm`: Updates service API, documentation, and paginators + * OpsWorks for Chef Automate has added a new field "AssociatePublicIpAddress" to the CreateServer request, "CloudFormationStackArn" to the Server model and "TERMINATED" server state. + + +Release v1.7.3 (2017-02-28) +=== + +Service Client Updates +--- +* `service/mturk`: Renaming service + * service/mechanicalturkrequesterservice was renamed to service/mturk. Be sure to change any references of the old client to the new. + +Release v1.7.2 (2017-02-28) +=== + +Service Client Updates +--- +* `service/dynamodb`: Updates service API and documentation + * Release notes: Time to Live (TTL) is a feature that allows you to define when items in a table expire and can be purged from the database, so that you don't have to track expired data and delete it manually. With TTL enabled on a DynamoDB table, you can set a timestamp for deletion on a per-item basis, allowing you to limit storage usage to only those records that are relevant. +* `service/iam`: Updates service API, documentation, and paginators + * This release adds support for AWS Organizations service control policies (SCPs) to SimulatePrincipalPolicy operation. If there are SCPs associated with the simulated user's account, their effect on the result is captured in the OrganizationDecisionDetail element in the EvaluationResult. +* `service/mechanicalturkrequesterservice`: Adds new service + * Amazon Mechanical Turk is a web service that provides an on-demand, scalable, human workforce to complete jobs that humans can do better than computers, for example, recognizing objects in photos. +* `service/organizations`: Adds new service + * AWS Organizations is a web service that enables you to consolidate your multiple AWS accounts into an organization and centrally manage your accounts and their resources. +* `service/dynamodbstreams`: Updates service API, documentation, and paginators +* `service/waf`: Updates service API, documentation, and paginators + * Aws WAF - For GetSampledRequests action, changed max number of samples from 100 to 500. +* `service/wafregional`: Updates service API, documentation, and paginators + +Release v1.7.1 (2017-02-24) +=== + +Service Client Updates +--- +* `service/elasticsearchservice`: Updates service API, documentation, paginators, and examples + * Added three new API calls to existing Amazon Elasticsearch service to expose Amazon Elasticsearch imposed limits to customers. + +Release v1.7.0 (2017-02-23) +=== + +Service Client Updates +--- +* `service/ec2`: Updates service API + * New EC2 I3 instance type + +SDK Bug +--- +* `service/s3/s3manager`: Adding support for SSE (#1097) + * Fixes SSE fields not being applied to a part during multi part upload. + +SDK Feature +--- +* `aws/session`: Add support for AssumeRoles with MFA (#1088) + * Adds support for assuming IAM roles with MFA enabled. A TokenProvider func was added to stscreds.AssumeRoleProvider that will be called each time the role's credentials need to be refreshed. A basic token provider that sources the MFA token from stdin as stscreds.StdinTokenProvider. +* `aws/session`: Update SDK examples and docs to use session.Must (#1099) + * Updates the SDK's example and docs to use session.Must where possible to highlight its usage as apposed to session error checking that is most cases errors will be terminal to the application anyways. +Release v1.6.27 (2017-02-22) +=== + +Service Client Updates +--- +* `service/clouddirectory`: Updates service documentation + * ListObjectAttributes documentation updated based on forum feedback +* `service/elasticbeanstalk`: Updates service API, documentation, and paginators + * Elastic Beanstalk adds support for creating and managing custom platform. +* `service/gamelift`: Updates service API, documentation, and paginators + * Allow developers to configure global queues for creating GameSessions. Allow PlayerData on PlayerSessions to store player-specific data. +* `service/route53`: Updates service API, documentation, and examples + * Added support for operations CreateVPCAssociationAuthorization and DeleteVPCAssociationAuthorization to throw a ConcurrentModification error when a conflicting modification occurs in parallel to the authorizations in place for a given hosted zone. + +Release v1.6.26 (2017-02-21) +=== + +Service Client Updates +--- +* `service/ec2`: Updates service API and documentation + * Added the billingProduct parameter to the RegisterImage API. + +Release v1.6.25 (2017-02-17) +=== + +Service Client Updates +--- +* `service/directconnect`: Updates service API, documentation, and paginators + * This update will introduce the ability for Direct Connect customers to take advantage of Link Aggregation (LAG). This allows you to bundle many individual physical interfaces into a single logical interface, referred to as a LAG. This makes administration much simpler as the majority of configuration is done on the LAG while you are free to add or remove physical interfaces from the bundle as bandwidth demand increases or decreases. A concrete example of the simplification added by LAG is that customers need only a single BGP session as opposed to one session per physical connection. + +Release v1.6.24 (2017-02-16) +=== + +Service Client Updates +--- +* `service/cognitoidentity`: Updates service API, documentation, and paginators + * Allow createIdentityPool and updateIdentityPool API to set server side token check value on identity pool +* `service/configservice`: Updates service API and documentation + * AWS Config now supports a new test mode for the PutEvaluations API. Set the TestMode parameter to true in your custom rule to verify whether your AWS Lambda function will deliver evaluation results to AWS Config. No updates occur to your existing evaluations, and evaluation results are not sent to AWS Config. + +Release v1.6.23 (2017-02-15) +=== + +Service Client Updates +--- +* `service/kms`: Updates service API, documentation, paginators, and examples + * his release of AWS Key Management Service introduces the ability to tag keys. Tagging keys can help you organize your keys and track your KMS costs in the cost allocation report. This release also increases the maximum length of a key ID to accommodate ARNs that include a long key alias. + +Release v1.6.22 (2017-02-14) +=== + +Service Client Updates +--- +* `service/ec2`: Updates service API, documentation, and paginators + * Adds support for the new Modify Volumes apis. + +Release v1.6.21 (2017-02-11) +=== + +Service Client Updates +--- +* `service/storagegateway`: Updates service API, documentation, and paginators + * File gateway mode in AWS Storage gateway provides access to objects in S3 as files on a Network File System (NFS) mount point. This is done by creating Nfs file shares using existing APIs CreateNfsFileShare. Using the feature in this update, the customer can restrict the clients that have read/write access to the gateway by specifying the list of clients as a list of IP addresses or CIDR blocks. This list can be specified using the API CreateNfsFileShare while creating new file shares, or UpdateNfsFileShare while update existing file shares. To find out the list of clients that have access, the existing API DescribeNfsFileShare will now output the list of clients that have access. + +Release v1.6.20 (2017-02-09) +=== + +Service Client Updates +--- +* `service/ec2`: Updates service API and documentation + * This feature allows customers to associate an IAM profile to running instances that do not have any. +* `service/rekognition`: Updates service API and documentation + * DetectFaces and IndexFaces operations now return an estimate of the age of the face as an age range. + +SDK Features +--- +* `aws/endpoints`: Add option to resolve unknown endpoints (#1074) +Release v1.6.19 (2017-02-08) +=== + +Service Client Updates +--- +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/glacier`: Updates service examples + * Doc Update +* `service/lexruntimeservice`: Adds new service + * Preview release + +SDK Bug Fixes +--- +* `private/protocol/json`: Fixes json to throw an error if a float number is (+/-)Inf and NaN (#1068) +* `private/model/api`: Fix documentation error listing (#1067) + +SDK Features +--- +* `private/model`: Add service response error code generation (#1061) + +Release v1.6.18 (2017-01-27) +=== + +Service Client Updates +--- +* `service/clouddirectory`: Adds new service + * Amazon Cloud Directory is a highly scalable, high performance, multi-tenant directory service in the cloud. Its web-based directories make it easy for you to organize and manage application resources such as users, groups, locations, devices, policies, and the rich relationships between them. +* `service/codedeploy`: Updates service API, documentation, and paginators + * This release of AWS CodeDeploy introduces support for blue/green deployments. In a blue/green deployment, the current set of instances in a deployment group is replaced by new instances that have the latest application revision installed on them. After traffic is rerouted behind a load balancer to the replacement instances, the original instances can be terminated automatically or kept running for other uses. +* `service/ec2`: Updates service API and documentation + * Adds instance health check functionality to replace unhealthy EC2 Spot fleet instances with fresh ones. +* `service/rds`: Updates service API and documentation + * Snapshot Engine Version Upgrade + +Release v1.6.17 (2017-01-25) +=== + +Service Client Updates +--- +* `service/elbv2`: Updates service API, documentation, and paginators + * Application Load Balancers now support native Internet Protocol version 6 (IPv6) in an Amazon Virtual Private Cloud (VPC). With this ability, clients can now connect to the Application Load Balancer in a dual-stack mode via either IPv4 or IPv6. +* `service/rds`: Updates service API and documentation + * Cross Region Read Replica Copying (CreateDBInstanceReadReplica) + +Release v1.6.16 (2017-01-24) +=== + +Service Client Updates +--- +* `service/codebuild`: Updates service documentation and paginators + * Documentation updates +* `service/codecommit`: Updates service API, documentation, and paginators + * AWS CodeCommit now includes the option to view the differences between a commit and its parent commit from within the console. You can view the differences inline (Unified view) or side by side (Split view). To view information about the differences between a commit and something other than its parent, you can use the AWS CLI and the get-differences and get-blob commands, or you can use the GetDifferences and GetBlob APIs. +* `service/ecs`: Updates service API and documentation + * Amazon ECS now supports a state for container instances that can be used to drain a container instance in preparation for maintenance or cluster scale down. + +Release v1.6.15 (2017-01-20) +=== + +Service Client Updates +--- +* `service/acm`: Updates service API, documentation, and paginators + * Update for AWS Certificate Manager: Updated response elements for DescribeCertificate API in support of managed renewal +* `service/health`: Updates service documentation + +Release v1.6.14 (2017-01-19) +=== + +Service Client Updates +--- +* `service/ec2`: Updates service API, documentation, and paginators + * Amazon EC2 Spot instances now support dedicated tenancy, providing the ability to run Spot instances single-tenant manner on physically isolated hardware within a VPC to satisfy security, privacy, or other compliance requirements. Dedicated Spot instances can be requested using RequestSpotInstances and RequestSpotFleet. + +Release v1.6.13 (2017-01-18) +=== + +Service Client Updates +--- +* `service/rds`: Updates service API, documentation, and paginators + +Release v1.6.12 (2017-01-17) +=== + +Service Client Updates +--- +* `service/dynamodb`: Updates service API, documentation, and paginators + * Tagging Support for Amazon DynamoDB Tables and Indexes +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/glacier`: Updates service API, paginators, and examples + * Doc-only Update for Glacier: Added code snippets +* `service/polly`: Updates service documentation and examples + * Doc-only update for Amazon Polly -- added snippets +* `service/rekognition`: Updates service documentation and paginators + * Added code samples to Rekognition reference topics. +* `service/route53`: Updates service API and paginators + * Add ca-central-1 and eu-west-2 enum values to CloudWatchRegion enum + +Release v1.6.11 (2017-01-16) +=== + +Service Client Updates +--- +* `service/configservice`: Updates service API, documentation, and paginators +* `service/costandusagereportservice`: Adds new service + * The AWS Cost and Usage Report Service API allows you to enable and disable the Cost & Usage report, as well as modify the report name, the data granularity, and the delivery preferences. +* `service/dynamodb`: Updates service API, documentation, and examples + * Snippets for the DynamoDB API. +* `service/elasticache`: Updates service API, documentation, and examples + * Adds new code examples. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.6.10 (2017-01-04) +=== + +Service Client Updates +--- +* `service/configservice`: Updates service API and documentation + * AWSConfig is planning to add support for OversizedConfigurationItemChangeNotification message type in putConfigRule. After this release customers can use/write rules based on OversizedConfigurationItemChangeNotification mesage type. +* `service/efs`: Updates service API, documentation, and examples + * Doc-only Update for EFS: Added code snippets +* `service/iam`: Updates service documentation and examples +* `service/lambda`: Updates service documentation and examples + * Doc only updates for Lambda: Added code snippets +* `service/marketplacecommerceanalytics`: Updates service API and documentation + * Added support for data set disbursed_amount_by_instance_hours, with historical data available starting 2012-09-04. New data is published to this data set every 30 days. +* `service/rds`: Updates service documentation + * Updated documentation for CopyDBSnapshot. +* `service/rekognition`: Updates service documentation and examples + * Doc-only Update for Rekognition: Added code snippets +* `service/snowball`: Updates service examples +* `service/dynamodbstreams`: Updates service API and examples + * Doc-only Update for DynamoDB Streams: Added code snippets + +SDK Feature +--- +* `private/model/api`: Increasing the readability of code generated files. (#1024) +Release v1.6.9 (2016-12-30) +=== + +Service Client Updates +--- +* `service/codedeploy`: Updates service API and documentation + * CodeDeploy will support Iam Session Arns in addition to Iam User Arns for on premise host authentication. +* `service/ecs`: Updates service API and documentation + * Amazon EC2 Container Service (ECS) now supports the ability to customize the placement of tasks on container instances. +* `aws/endpoints`: Updated Regions and Endpoints metadata. + +Release v1.6.8 (2016-12-22) +=== + +Service Client Updates +--- +* `service/apigateway`: Updates service API and documentation + * Amazon API Gateway is adding support for generating SDKs in more languages. This update introduces two new operations used to dynamically discover these SDK types and what configuration each type accepts. +* `service/directoryservice`: Updates service documentation + * Added code snippets for the DS SDKs +* `service/elasticbeanstalk`: Updates service API and documentation +* `service/iam`: Updates service API and documentation + * Adds service-specific credentials to IAM service to make it easier to onboard CodeCommit customers. These are username/password credentials that work with a single service. +* `service/kms`: Updates service API, documentation, and examples + * Update docs and add SDK examples + +Release v1.6.7 (2016-12-22) +=== + +Service Client Updates +--- +* `service/ecr`: Updates service API and documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/rds`: Updates service API and documentation + * Cross Region Encrypted Snapshot Copying (CopyDBSnapshot) + +Release v1.6.6 (2016-12-20) +=== + +Service Client Updates +--- +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/firehose`: Updates service API, documentation, and examples + * Processing feature enables users to process and modify records before Amazon Firehose delivers them to destinations. +* `service/route53`: Updates service API and documentation + * Enum updates for eu-west-2 and ca-central-1 +* `service/storagegateway`: Updates service API, documentation, and examples + * File gateway is a new mode in the AWS Storage Gateway that support a file interface into S3, alongside the current block-based volume and VTL storage. File gateway combines a service and virtual software appliance, enabling you to store and retrieve objects in Amazon S3 using industry standard file protocols such as NFS. The software appliance, or gateway, is deployed into your on-premises environment as a virtual machine (VM) running on VMware ESXi. The gateway provides access to objects in S3 as files on a Network File System (NFS) mount point. + +Release v1.6.5 (2016-12-19) +=== + +Service Client Updates +--- +* `service/cloudformation`: Updates service documentation + * Minor doc update for CloudFormation. +* `service/cloudtrail`: Updates service paginators +* `service/cognitoidentity`: Updates service API and documentation + * We are adding Groups to Cognito user pools. Developers can perform CRUD operations on groups, add and remove users from groups, list users in groups, etc. We are adding fine-grained role-based access control for Cognito identity pools. Developers can configure an identity pool to get the IAM role from an authenticated user's token, or they can configure rules that will map a user to a different role +* `service/applicationdiscoveryservice`: Updates service API and documentation + * Adds new APIs to group discovered servers into Applications with get summary and neighbors. Includes additional filters for ListConfigurations and DescribeAgents API. +* `service/inspector`: Updates service API, documentation, and examples + * Doc-only Update for Inspector: Adding SDK code snippets for Inspector +* `service/sqs`: Updates service documentation + +SDK Bug Fixes +--- +* `aws/request`: Add PriorRequestNotComplete to throttle retry codes (#1011) + * Fixes: Not retrying when PriorRequestNotComplete #1009 + +SDK Feature +--- +* `private/model/api`: Adds crosslinking to service documentation (#1010) + +Release v1.6.4 (2016-12-15) +=== + +Service Client Updates +--- +* `service/cognitoidentityprovider`: Updates service API and documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/ssm`: Updates service API and documentation + * This will provide customers with access to the Patch Baseline and Patch Compliance APIs. + +SDK Bug Fixes +--- +* `service/route53`: Fix URL path cleaning for Route53 API requests (#1006) + * Fixes: SerializationError when using Route53 ChangeResourceRecordSets #1005 +* `aws/request`: Add PriorRequestNotComplete to throttle retry codes (#1002) + * Fixes: Not retrying when PriorRequestNotComplete #1001 + +Release v1.6.3 (2016-12-14) +=== + +Service Client Updates +--- +* `service/batch`: Adds new service + * AWS Batch is a batch computing service that lets customers define queues and compute environments and then submit work as batch jobs. +* `service/databasemigrationservice`: Updates service API and documentation + * Adds support for SSL enabled Oracle endpoints and task modification. +* `service/elasticbeanstalk`: Updates service documentation +* `aws/endpoints`: Updated Regions and Endpoints metadata. +* `service/cloudwatchlogs`: Updates service API and documentation + * Add support for associating LogGroups with AWSTagris tags +* `service/marketplacecommerceanalytics`: Updates service API and documentation + * Add new enum to DataSetType: sales_compensation_billed_revenue +* `service/rds`: Updates service documentation + * Doc-only Update for RDS: New versions available in CreateDBInstance +* `service/sts`: Updates service documentation + * Adding Code Snippet Examples for SDKs for STS + +SDK Bug Fixes +--- +* `aws/request`: Fix retrying timeout requests (#981) + * Fixes: Requests Retrying is broken if the error was caused due to a client timeout #947 +* `aws/request`: Fix for Go 1.8 request incorrectly sent with body (#991) + * Fixes: service/route53: ListHostedZones hangs and then fails with go1.8 #984 +* private/protocol/rest: Use RawPath instead of Opaque (#993) + * Fixes: HTTP2 request failing with REST protocol services, e.g AWS X-Ray +* private/model/api: Generate REST-JSON JSONVersion correctly (#998) + * Fixes: REST-JSON protocol service code missing JSONVersion metadata. + +Release v1.6.2 (2016-12-08) +=== + +Service Client Updates +--- +* `service/cloudfront`: Add lambda function associations to cache behaviors +* `service/codepipeline`: This is a doc-only update request to incorporate some recent minor revisions to the doc content. +* `service/rds`: Updates service API and documentation +* `service/wafregional`: With this new feature, customers can use AWS WAF directly on Application Load Balancers in a VPC within available regions to protect their websites and web services from malicious attacks such as SQL injection, Cross Site Scripting, bad bots, etc. + +Release v1.6.1 (2016-12-07) +=== + +Service Client Updates +--- +* `service/config`: Updates service API +* `service/s3`: Updates service API +* `service/sqs`: Updates service API and documentation + +Release v1.6.0 (2016-12-06) +=== + +Service Client Updates +--- +* `service/config`: Updates service API and documentation +* `service/ec2`: Updates service API +* `service/sts`: Updates service API, documentation, and examples + +SDK Bug Fixes +--- +* private/protocol/xml/xmlutil: Fix SDK XML unmarshaler #975 + * Fixes GetBucketACL Grantee required type always nil. #916 + +SDK Feature +--- +* aws/endpoints: Add endpoint metadata to SDK #961 + * Adds Region and Endpoint metadata to the SDK. This allows you to enumerate regions and endpoint metadata based on a defined model embedded in the SDK. + +Release v1.5.13 (2016-12-01) +=== + +Service Client Updates +--- +* `service/apigateway`: Updates service API and documentation +* `service/appstream`: Adds new service +* `service/codebuild`: Adds new service +* `service/directconnect`: Updates service API and documentation +* `service/ec2`: Adds new service +* `service/elasticbeanstalk`: Updates service API and documentation +* `service/health`: Adds new service +* `service/lambda`: Updates service API and documentation +* `service/opsworkscm`: Adds new service +* `service/pinpoint`: Adds new service +* `service/shield`: Adds new service +* `service/ssm`: Updates service API and documentation +* `service/states`: Adds new service +* `service/xray`: Adds new service + +Release v1.5.12 (2016-11-30) +=== + +Service Client Updates +--- +* `service/lightsail`: Adds new service +* `service/polly`: Adds new service +* `service/rekognition`: Adds new service +* `service/snowball`: Updates service API and documentation + +Release v1.5.11 (2016-11-29) +=== + +Service Client Updates +--- +`service/s3`: Updates service API and documentation + +Release v1.5.10 (2016-11-22) +=== + +Service Client Updates +--- +* `service/cloudformation`: Updates service API and documentation +* `service/glacier`: Updates service API, documentation, and examples +* `service/route53`: Updates service API and documentation +* `service/s3`: Updates service API and documentation + +SDK Bug Fixes +--- +* `private/protocol/xml/xmlutil`: Fixes xml marshaler to unmarshal properly +into tagged fields +[#916](https://github.com/aws/aws-sdk-go/issues/916) + +Release v1.5.9 (2016-11-22) +=== + +Service Client Updates +--- +* `service/cloudtrail`: Updates service API and documentation +* `service/ecs`: Updates service API and documentation + +Release v1.5.8 (2016-11-18) +=== + +Service Client Updates +--- +* `service/application-autoscaling`: Updates service API and documentation +* `service/elasticmapreduce`: Updates service API and documentation +* `service/elastictranscoder`: Updates service API, documentation, and examples +* `service/gamelift`: Updates service API and documentation +* `service/lambda`: Updates service API and documentation + +Release v1.5.7 (2016-11-18) +=== + +Service Client Updates +--- +* `service/apigateway`: Updates service API and documentation +* `service/meteringmarketplace`: Updates service API and documentation +* `service/monitoring`: Updates service API and documentation +* `service/sqs`: Updates service API, documentation, and examples + +Release v1.5.6 (2016-11-16) +=== + +Service Client Updates +--- +`service/route53`: Updates service API and documentation +`service/servicecatalog`: Updates service API and documentation + +Release v1.5.5 (2016-11-15) +=== + +Service Client Updates +--- +* `service/ds`: Updates service API and documentation +* `service/elasticache`: Updates service API and documentation +* `service/kinesis`: Updates service API and documentation + +Release v1.5.4 (2016-11-15) +=== + +Service Client Updates +--- +* `service/cognito-idp`: Updates service API and documentation + +Release v1.5.3 (2016-11-11) +=== + +Service Client Updates +--- +* `service/cloudformation`: Updates service documentation and examples +* `service/logs`: Updates service API and documentation + +Release v1.5.2 (2016-11-03) +=== + +Service Client Updates +--- +* `service/directconnect`: Updates service API and documentation + +Release v1.5.1 (2016-11-02) +=== + +Service Client Updates +--- +* `service/email`: Updates service API and documentation + +Release v1.5.0 (2016-11-01) +=== + +Service Client Updates +--- +* `service/cloudformation`: Updates service API and documentation +* `service/ecr`: Updates service paginators + +SDK Feature Updates +--- +* `private/model/api`: Add generated setters for API parameters (#918) + * Adds setters to the SDK's API parameter types, and are a convenience method that reduce the need to use `aws.String` and like utility. + +Release v1.4.22 (2016-10-25) +=== + +Service Client Updates +--- +* `service/elasticloadbalancingv2`: Updates service documentation. +* `service/autoscaling`: Updates service documentation. + +Release v1.4.21 (2016-10-24) +=== + +Service Client Updates +--- +* `service/sms`: AWS Server Migration Service (SMS) is an agentless service which makes it easier and faster for you to migrate thousands of on-premises workloads to AWS. AWS SMS allows you to automate, schedule, and track incremental replications of live server volumes, making it easier for you to coordinate large-scale server migrations. +* `service/ecs`: Updates documentation. + +SDK Feature Updates +--- +* `private/models/api`: Improve code generation of documentation. + +Release v1.4.20 (2016-10-20) +=== + +Service Client Updates +--- +* `service/budgets`: Adds new service, AWS Budgets. +* `service/waf`: Updates service documentation. + +Release v1.4.19 (2016-10-18) +=== + +Service Client Updates +--- +* `service/cloudfront`: Updates service API and documentation. + * Ability to use Amazon CloudFront to deliver your content both via IPv6 and IPv4 using HTTP/HTTPS. +* `service/configservice`: Update service API and documentation. +* `service/iot`: Updates service API and documentation. +* `service/kinesisanalytics`: Updates service API and documentation. + * Whenever Amazon Kinesis Analytics is not able to detect schema for the given streaming source on DiscoverInputSchema API, we would return the raw records that was sampled to detect the schema. +* `service/rds`: Updates service API and documentation. + * Amazon Aurora integrates with other AWS services to allow you to extend your Aurora DB cluster to utilize other capabilities in the AWS cloud. Permission to access other AWS services is granted by creating an IAM role with the necessary permissions, and then associating the role with your DB cluster. + +SDK Feature Updates +--- +* `service/dynamodb/dynamodbattribute`: Add UnmarshalListOfMaps #897 + * Adds support for unmarshaling a list of maps. This is useful for unmarshaling the DynamoDB AttributeValue list of maps returned by APIs like Query and Scan. + +Release v1.4.18 (2016-10-17) +=== + +Service Model Updates +--- +* `service/route53`: Updates service API and documentation. + +Release v1.4.17 +=== + +Service Model Updates +--- +* `service/acm`: Update service API, and documentation. + * This change allows users to import third-party SSL/TLS certificates into ACM. +* `service/elasticbeanstalk`: Update service API, documentation, and pagination. + * Elastic Beanstalk DescribeApplicationVersions API is being updated to support pagination. +* `service/gamelift`: Update service API, and documentation. + * New APIs to protect game developer resource (builds, alias, fleets, instances, game sessions and player sessions) against abuse. + +SDK Features +--- +* `service/s3`: Add support for accelerate with dualstack [#887](https://github.com/aws/aws-sdk-go/issues/887) + +Release v1.4.16 (2016-10-13) +=== + +Service Model Updates +--- +* `service/ecr`: Update Amazon EC2 Container Registry service model + * DescribeImages is a new api used to expose image metadata which today includes image size and image creation timestamp. +* `service/elasticache`: Update Amazon ElastiCache service model + * Elasticache is launching a new major engine release of Redis, 3.2 (providing stability updates and new command sets over 2.8), as well as ElasticSupport for enabling Redis Cluster in 3.2, which provides support for multiple node groups to horizontally scale data, as well as superior engine failover capabilities + +SDK Bug Fixes +--- +* `aws/session`: Skip shared config on read errors [#883](https://github.com/aws/aws-sdk-go/issues/883) +* `aws/signer/v4`: Add support for URL.EscapedPath to signer [#885](https://github.com/aws/aws-sdk-go/issues/885) + +SDK Features +--- +* `private/model/api`: Add docs for errors to API operations [#881](https://github.com/aws/aws-sdk-go/issues/881) +* `private/model/api`: Improve field and waiter doc strings [#879](https://github.com/aws/aws-sdk-go/issues/879) +* `service/dynamodb/dynamodbattribute`: Allow multiple struct tag elements [#886](https://github.com/aws/aws-sdk-go/issues/886) +* Add build tags to internal SDK tools [#880](https://github.com/aws/aws-sdk-go/issues/880) + +Release v1.4.15 (2016-10-06) +=== + +Service Model Updates +--- +* `service/cognitoidentityprovider`: Update Amazon Cognito Identity Provider service model +* `service/devicefarm`: Update AWS Device Farm documentation +* `service/opsworks`: Update AWS OpsWorks service model +* `service/s3`: Update Amazon Simple Storage Service model +* `service/waf`: Update AWS WAF service model + +SDK Bug Fixes +--- +* `aws/request`: Fix HTTP Request Body race condition [#874](https://github.com/aws/aws-sdk-go/issues/874) + +SDK Feature Updates +--- +* `aws/ec2metadata`: Add support for EC2 User Data [#872](https://github.com/aws/aws-sdk-go/issues/872) +* `aws/signer/v4`: Remove logic determining if request needs to be resigned [#876](https://github.com/aws/aws-sdk-go/issues/876) + +Release v1.4.14 (2016-09-29) +=== +* `service/ec2`: api, documentation, and paginators updates. +* `service/s3`: api and documentation updates. + +Release v1.4.13 (2016-09-27) +=== +* `service/codepipeline`: documentation updates. +* `service/cloudformation`: api and documentation updates. +* `service/kms`: documentation updates. +* `service/elasticfilesystem`: documentation updates. +* `service/snowball`: documentation updates. diff --git a/vendor/github.com/aws/aws-sdk-go/CHANGELOG_PENDING.md b/vendor/github.com/aws/aws-sdk-go/CHANGELOG_PENDING.md new file mode 100644 index 0000000..8a1927a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/CHANGELOG_PENDING.md @@ -0,0 +1,5 @@ +### SDK Features + +### SDK Enhancements + +### SDK Bugs diff --git a/vendor/github.com/aws/aws-sdk-go/CONTRIBUTING.md b/vendor/github.com/aws/aws-sdk-go/CONTRIBUTING.md new file mode 100644 index 0000000..6f422a9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/CONTRIBUTING.md @@ -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 + diff --git a/vendor/github.com/aws/aws-sdk-go/Gopkg.lock b/vendor/github.com/aws/aws-sdk-go/Gopkg.lock new file mode 100644 index 0000000..854c94f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/Gopkg.lock @@ -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 diff --git a/vendor/github.com/aws/aws-sdk-go/Gopkg.toml b/vendor/github.com/aws/aws-sdk-go/Gopkg.toml new file mode 100644 index 0000000..664fc59 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/Gopkg.toml @@ -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" diff --git a/vendor/github.com/aws/aws-sdk-go/LICENSE.txt b/vendor/github.com/aws/aws-sdk-go/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/aws/aws-sdk-go/Makefile b/vendor/github.com/aws/aws-sdk-go/Makefile new file mode 100644 index 0000000..83ccc1e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/Makefile @@ -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 ' where 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 diff --git a/vendor/github.com/aws/aws-sdk-go/NOTICE.txt b/vendor/github.com/aws/aws-sdk-go/NOTICE.txt new file mode 100644 index 0000000..5f14d11 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/NOTICE.txt @@ -0,0 +1,3 @@ +AWS SDK for Go +Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2014-2015 Stripe, Inc. diff --git a/vendor/github.com/aws/aws-sdk-go/README.md b/vendor/github.com/aws/aws-sdk-go/README.md new file mode 100644 index 0000000..46da966 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/README.md @@ -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.Int64Value(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. diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go b/vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go new file mode 100644 index 0000000..56fdfc2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go @@ -0,0 +1,145 @@ +// Package awserr represents API error interface accessors for the SDK. +package awserr + +// An Error wraps lower level errors with code, message and an original error. +// The underlying concrete error type may also satisfy other interfaces which +// can be to used to obtain more specific information about the error. +// +// Calling Error() or String() will always include the full information about +// an error based on its underlying type. +// +// Example: +// +// output, err := s3manage.Upload(svc, input, opts) +// if err != nil { +// if awsErr, ok := err.(awserr.Error); ok { +// // Get error details +// log.Println("Error:", awsErr.Code(), awsErr.Message()) +// +// // Prints out full error message, including original error if there was one. +// log.Println("Error:", awsErr.Error()) +// +// // Get original error +// if origErr := awsErr.OrigErr(); origErr != nil { +// // operate on original error. +// } +// } else { +// fmt.Println(err.Error()) +// } +// } +// +type Error interface { + // Satisfy the generic error interface. + error + + // Returns the short phrase depicting the classification of the error. + Code() string + + // Returns the error details message. + Message() string + + // Returns the original error if one was set. Nil is returned if not set. + OrigErr() error +} + +// 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. +// +// If origErr satisfies the Error interface it will not be wrapped within a new +// Error object and will instead be returned. +func New(code, message string, origErr error) Error { + var errs []error + if origErr != nil { + errs = append(errs, 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 +// an Error such as the request ID of the failed request returned by a service. +// RequestFailures may not always have a requestID value if the request failed +// prior to reaching the service such as a connection error. +// +// Example: +// +// output, err := s3manage.Upload(svc, input, opts) +// if err != nil { +// if reqerr, ok := err.(RequestFailure); ok { +// log.Println("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID()) +// } else { +// log.Println("Error:", err.Error()) +// } +// } +// +// Combined with awserr.Error: +// +// output, err := s3manage.Upload(svc, input, opts) +// if err != nil { +// if awsErr, ok := err.(awserr.Error); ok { +// // Generic AWS Error with Code, Message, and original error (if any) +// fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr()) +// +// if reqErr, ok := err.(awserr.RequestFailure); ok { +// // A service error occurred +// fmt.Println(reqErr.StatusCode(), reqErr.RequestID()) +// } +// } else { +// fmt.Println(err.Error()) +// } +// } +// +type RequestFailure interface { + Error + + // The status code of the HTTP response. + StatusCode() int + + // The request ID returned by the service for a request failure. This will + // be empty if no request ID is available such as the request failed due + // to a connection error. + RequestID() string +} + +// NewRequestFailure returns a new request error wrapper for the given Error +// provided. +func NewRequestFailure(err Error, statusCode int, reqID string) RequestFailure { + return newRequestError(err, statusCode, reqID) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go b/vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go new file mode 100644 index 0000000..0202a00 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go @@ -0,0 +1,194 @@ +package awserr + +import "fmt" + +// SprintError returns a string of the formatted error code. +// +// Both extra and origErr are optional. If they are included their lines +// will be added, but if they are not included their lines will be ignored. +func SprintError(code, message, extra string, origErr error) string { + msg := fmt.Sprintf("%s: %s", code, message) + if extra != "" { + msg = fmt.Sprintf("%s\n\t%s", msg, extra) + } + if origErr != nil { + msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error()) + } + return msg +} + +// A baseError wraps the code and message which defines an error. It also +// can be used to wrap an original error object. +// +// Should be used as the root for errors satisfying the awserr.Error. Also +// for any error which does not fit into a specific error wrapper type. +type baseError struct { + // Classification of error + code string + + // Detailed information about error + message string + + // Optional original error this error is based off of. Allows building + // chained errors. + errs []error +} + +// newBaseError returns an error object for the code, message, and errors. +// +// code is a short no whitespace phrase depicting the classification of +// the error that is being created. +// +// message is the free flow string containing detailed information about the +// error. +// +// origErrs is the error objects which will be nested under the new errors to +// be returned. +func newBaseError(code, message string, origErrs []error) *baseError { + b := &baseError{ + code: code, + message: message, + errs: origErrs, + } + + return b +} + +// Error returns the string representation of the error. +// +// See ErrorWithExtra for formatting. +// +// Satisfies the error interface. +func (b baseError) Error() string { + 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. +// Alias for Error to satisfy the stringer interface. +func (b baseError) String() string { + return b.Error() +} + +// Code returns the short phrase depicting the classification of the error. +func (b baseError) Code() string { + return b.code +} + +// Message returns the error details message. +func (b baseError) Message() string { + return b.message +} + +// OrigErr returns the original error if one was set. Nil is returned if no +// error was set. This only returns the first element in the list. If the full +// list is needed, use BatchedErrors. +func (b baseError) OrigErr() error { + 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 +// in the requestError struct and not conflict with the error.Error() method. +type awsError Error + +// A requestError wraps a request or service error. +// +// Composed of baseError for code, message, and original error. +type requestError struct { + awsError + statusCode int + requestID string +} + +// newRequestError returns a wrapped error with additional information for +// request status code, and service requestID. +// +// Should be used to wrap all request which involve service requests. Even if +// the request failed without a service response, but had an HTTP status code +// that may be meaningful. +// +// Also wraps original errors via the baseError. +func newRequestError(err Error, statusCode int, requestID string) *requestError { + return &requestError{ + awsError: err, + statusCode: statusCode, + requestID: requestID, + } +} + +// Error returns the string representation of the error. +// Satisfies the error interface. +func (r requestError) Error() string { + extra := fmt.Sprintf("status code: %d, request id: %s", + r.statusCode, r.requestID) + return SprintError(r.Code(), r.Message(), extra, r.OrigErr()) +} + +// String returns the string representation of the error. +// Alias for Error to satisfy the stringer interface. +func (r requestError) String() string { + return r.Error() +} + +// StatusCode returns the wrapped status code for the error +func (r requestError) StatusCode() int { + return r.statusCode +} + +// RequestID returns the wrapped requestID +func (r requestError) RequestID() string { + return r.requestID +} + +// 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 +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go new file mode 100644 index 0000000..1a3d106 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go @@ -0,0 +1,108 @@ +package awsutil + +import ( + "io" + "reflect" + "time" +) + +// Copy deeply copies a src structure to dst. Useful for copying request and +// response structures. +// +// Can copy between structs of different type, but will only copy fields which +// are assignable, and exist in both structs. Fields which are not assignable, +// or do not exist in both structs are ignored. +func Copy(dst, src interface{}) { + dstval := reflect.ValueOf(dst) + if !dstval.IsValid() { + panic("Copy dst cannot be nil") + } + + rcopy(dstval, reflect.ValueOf(src), true) +} + +// CopyOf returns a copy of src while also allocating the memory for dst. +// src must be a pointer type or this operation will fail. +func CopyOf(src interface{}) (dst interface{}) { + dsti := reflect.New(reflect.TypeOf(src).Elem()) + dst = dsti.Interface() + rcopy(dsti, reflect.ValueOf(src), true) + return +} + +// rcopy performs a recursive copy of values from the source to destination. +// +// root is used to skip certain aspects of the copy which are not valid +// for the root node of a object. +func rcopy(dst, src reflect.Value, root bool) { + if !src.IsValid() { + return + } + + switch src.Kind() { + case reflect.Ptr: + if _, ok := src.Interface().(io.Reader); ok { + if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() { + dst.Elem().Set(src) + } else if dst.CanSet() { + dst.Set(src) + } + } else { + e := src.Type().Elem() + if dst.CanSet() && !src.IsNil() { + 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() { + // Keep the current root state since the depth hasn't changed + rcopy(dst.Elem(), src.Elem(), root) + } + } + case reflect.Struct: + t := dst.Type() + for i := 0; i < t.NumField(); i++ { + name := t.Field(i).Name + srcVal := src.FieldByName(name) + dstVal := dst.FieldByName(name) + if srcVal.IsValid() && dstVal.CanSet() { + rcopy(dstVal, srcVal, false) + } + } + case reflect.Slice: + if src.IsNil() { + break + } + + s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) + dst.Set(s) + for i := 0; i < src.Len(); i++ { + rcopy(dst.Index(i), src.Index(i), false) + } + case reflect.Map: + if src.IsNil() { + break + } + + s := reflect.MakeMap(src.Type()) + dst.Set(s) + for _, k := range src.MapKeys() { + v := src.MapIndex(k) + v2 := reflect.New(v.Type()).Elem() + rcopy(v2, v, false) + dst.SetMapIndex(k, v2) + } + default: + // Assign the value if possible. If its not assignable, the value would + // need to be converted and the impact of that may be unexpected, or is + // not compatible with the dst type. + if src.Type().AssignableTo(dst.Type()) { + dst.Set(src) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go new file mode 100644 index 0000000..007b37b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go @@ -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"] + // } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go new file mode 100644 index 0000000..59fa4a5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go @@ -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()) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go new file mode 100644 index 0000000..18d3c5b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go new file mode 100644 index 0000000..11c52c3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go @@ -0,0 +1,222 @@ +package awsutil + +import ( + "reflect" + "regexp" + "strconv" + "strings" + + "github.com/jmespath/go-jmespath" +) + +var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`) + +// rValuesAtPath returns a slice of values found in value v. The values +// in v are explored recursively so all nested values are collected. +func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value { + pathparts := strings.Split(path, "||") + if len(pathparts) > 1 { + for _, pathpart := range pathparts { + vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm) + if len(vals) > 0 { + return vals + } + } + return nil + } + + values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))} + components := strings.Split(path, ".") + for len(values) > 0 && len(components) > 0 { + var index *int64 + var indexStar bool + c := strings.TrimSpace(components[0]) + if c == "" { // no actual component, illegal syntax + return nil + } else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] { + // TODO normalize case for user + return nil // don't support unexported fields + } + + // parse this component + if m := indexRe.FindStringSubmatch(c); m != nil { + c = m[1] + if m[2] == "" { + index = nil + indexStar = true + } else { + i, _ := strconv.ParseInt(m[2], 10, 32) + index = &i + indexStar = false + } + } + + nextvals := []reflect.Value{} + for _, value := range values { + // pull component name out of struct member + if value.Kind() != reflect.Struct { + continue + } + + if c == "*" { // pull all members + for i := 0; i < value.NumField(); i++ { + if f := reflect.Indirect(value.Field(i)); f.IsValid() { + nextvals = append(nextvals, f) + } + } + continue + } + + value = value.FieldByNameFunc(func(name string) bool { + if c == name { + return true + } else if !caseSensitive && strings.ToLower(name) == strings.ToLower(c) { + return true + } + return false + }) + + if 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 = value.Elem() + } else { + value = reflect.Indirect(value) + } + + if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { + if !createPath && value.IsNil() { + value = reflect.ValueOf(nil) + } + } + + if value.IsValid() { + nextvals = append(nextvals, value) + } + } + values = nextvals + + if indexStar || index != nil { + nextvals = []reflect.Value{} + for _, valItem := range values { + value := reflect.Indirect(valItem) + if value.Kind() != reflect.Slice { + continue + } + + if indexStar { // grab all indices + for i := 0; i < value.Len(); i++ { + idx := reflect.Indirect(value.Index(i)) + if idx.IsValid() { + nextvals = append(nextvals, idx) + } + } + continue + } + + // pull out index + i := int(*index) + if i >= value.Len() { // check out of bounds + if createPath { + // TODO resize slice + } else { + continue + } + } else if i < 0 { // support negative indexing + i = value.Len() + i + } + value = reflect.Indirect(value.Index(i)) + + if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { + if !createPath && value.IsNil() { + value = reflect.ValueOf(nil) + } + } + + if value.IsValid() { + nextvals = append(nextvals, value) + } + } + values = nextvals + } + + components = components[1:] + } + return values +} + +// ValuesAtPath returns a list of values at the case insensitive lexical +// path inside of a structure. +func ValuesAtPath(i interface{}, path string) ([]interface{}, error) { + result, err := jmespath.Search(path, i) + if err != nil { + return nil, err + } + + 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 +} + +// SetValueAtPath sets a value at the case insensitive lexical path inside +// of a structure. +func SetValueAtPath(i interface{}, path string, v interface{}) { + if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil { + for _, rval := range rvals { + if rval.Kind() == reflect.Ptr && rval.IsNil() { + continue + } + setValue(rval, v) + } + } +} + +func setValue(dstVal reflect.Value, src interface{}) { + if dstVal.Kind() == reflect.Ptr { + dstVal = reflect.Indirect(dstVal) + } + 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) + } + +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go new file mode 100644 index 0000000..58a05d6 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go @@ -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) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go new file mode 100644 index 0000000..710eb43 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go @@ -0,0 +1,113 @@ +package awsutil + +import ( + "bytes" + "fmt" + "io" + "reflect" + "strings" +) + +// Prettify returns the string representation of a value. +func Prettify(i interface{}) string { + var buf bytes.Buffer + prettify(reflect.ValueOf(i), 0, &buf) + return buf.String() +} + +// prettify will recursively walk value v to build a textual +// representation of the value. +func prettify(v reflect.Value, indent int, buf *bytes.Buffer) { + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + + switch v.Kind() { + case reflect.Struct: + strtype := v.Type().String() + if strtype == "time.Time" { + fmt.Fprintf(buf, "%s", v.Interface()) + break + } else if strings.HasPrefix(strtype, "io.") { + buf.WriteString("") + break + } + + buf.WriteString("{\n") + + names := []string{} + for i := 0; i < v.Type().NumField(); i++ { + name := v.Type().Field(i).Name + f := v.Field(i) + if name[0:1] == strings.ToLower(name[0:1]) { + continue // ignore unexported fields + } + if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() { + continue // ignore unset fields + } + names = append(names, name) + } + + for i, n := range names { + val := v.FieldByName(n) + buf.WriteString(strings.Repeat(" ", indent+2)) + buf.WriteString(n + ": ") + prettify(val, indent+2, buf) + + if i < len(names)-1 { + buf.WriteString(",\n") + } + } + + buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") + case reflect.Slice: + strtype := v.Type().String() + if strtype == "[]uint8" { + fmt.Fprintf(buf, " len %d", v.Len()) + break + } + + nl, id, id2 := "", "", "" + if v.Len() > 3 { + nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2) + } + buf.WriteString("[" + nl) + for i := 0; i < v.Len(); i++ { + buf.WriteString(id2) + prettify(v.Index(i), indent+2, buf) + + if i < v.Len()-1 { + buf.WriteString("," + nl) + } + } + + buf.WriteString(nl + id + "]") + case reflect.Map: + buf.WriteString("{\n") + + for i, k := range v.MapKeys() { + buf.WriteString(strings.Repeat(" ", indent+2)) + buf.WriteString(k.String() + ": ") + prettify(v.MapIndex(k), indent+2, buf) + + if i < v.Len()-1 { + buf.WriteString(",\n") + } + } + + buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") + default: + if !v.IsValid() { + fmt.Fprint(buf, "") + return + } + format := "%v" + switch v.Interface().(type) { + case string: + format = "%q" + case io.ReadSeeker, io.Reader: + format = "buffer(%p)" + } + fmt.Fprintf(buf, format, v.Interface()) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go new file mode 100644 index 0000000..b6432f1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go @@ -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()) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/client.go b/vendor/github.com/aws/aws-sdk-go/aws/client/client.go new file mode 100644 index 0000000..788fe6e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/client.go @@ -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}) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/client_test.go b/vendor/github.com/aws/aws-sdk-go/aws/client/client_test.go new file mode 100644 index 0000000..30d3b99 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/client_test.go @@ -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") + } + +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go new file mode 100644 index 0000000..63d2df6 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go @@ -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() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer_test.go b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer_test.go new file mode 100644 index 0000000..fddba4e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/logger.go b/vendor/github.com/aws/aws-sdk-go/aws/client/logger.go new file mode 100644 index 0000000..1f39c91 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/logger.go @@ -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, + }) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/logger_test.go b/vendor/github.com/aws/aws-sdk-go/aws/client/logger_test.go new file mode 100644 index 0000000..b8d600c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/logger_test.go @@ -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()) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go b/vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go new file mode 100644 index 0000000..4778056 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go @@ -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 +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/config.go b/vendor/github.com/aws/aws-sdk-go/aws/config.go new file mode 100644 index 0000000..4fd0d07 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/config.go @@ -0,0 +1,470 @@ +package aws + +import ( + "net/http" + "time" + + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/endpoints" +) + +// UseServiceDefaultRetries instructs the config to use the service's own +// default number of retries. This will be the default action if +// 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, +// 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 { + // Enables verbose error printing of all credential chain errors. + // 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 + + // An optional endpoint URL (hostname only or fully qualified URI) + // that overrides the default generated endpoint for a client. Set this + // to `""` to use the default generated endpoint. + // + // @note You must still provide a `Region` value when specifying an + // endpoint for a client. + Endpoint *string + + // The 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 + // be configured globally or on a per-client basis unless otherwise + // noted. A full list of regions is found in the "Regions and Endpoints" + // document. + // + // @see http://docs.aws.amazon.com/general/latest/gr/rande.html + // AWS Regions and Endpoints + Region *string + + // Set this to `true` to disable SSL when sending requests. Defaults + // to `false`. + DisableSSL *bool + + // The HTTP client to use when sending requests. Defaults to + // `http.DefaultClient`. + HTTPClient *http.Client + + // An integer value representing the logging level. The default log level + // is zero (LogOff), which represents no logging. To enable logging set + // to a LogLevel Value. + LogLevel *LogLevelType + + // The logger writer interface to write logging messages to. Defaults to + // standard out. + Logger Logger + + // The maximum number of times that a request will be retried for failures. + // Defaults to -1, which defers the max retry setting to the service + // specific configuration. + MaxRetries *int + + // Retryer guides how HTTP requests should be retried in case of + // recoverable failures. + // + // When nil or the value does not implement the request.Retryer interface, + // 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 + + // Disables the computation of request and response checksums, e.g., + // CRC32 checksums in Amazon DynamoDB. + DisableComputeChecksums *bool + + // Set this to `true` to force the request to use path-style addressing, + // i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client + // will use virtual hosted bucket addressing when possible + // (`http://BUCKET.s3.amazonaws.com/KEY`). + // + // @note This configuration option is specific to the Amazon S3 service. + // @see http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html + // Amazon S3: Virtual Hosting of Buckets + S3ForcePathStyle *bool + + // 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 endpoint 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) + + // 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 set multiple configuration values inline without using pointers. +// +// // 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 { + 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 +// for chaining. +func (c *Config) WithCredentials(creds *credentials.Credentials) *Config { + c.Credentials = creds + return c +} + +// WithEndpoint sets a config Endpoint value returning a Config pointer for +// chaining. +func (c *Config) WithEndpoint(endpoint string) *Config { + c.Endpoint = &endpoint + return c +} + +// 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 +// chaining. +func (c *Config) WithRegion(region string) *Config { + c.Region = ®ion + return c +} + +// WithDisableSSL sets a config DisableSSL value returning a Config pointer +// for chaining. +func (c *Config) WithDisableSSL(disable bool) *Config { + c.DisableSSL = &disable + return c +} + +// WithHTTPClient sets a config HTTPClient value returning a Config pointer +// for chaining. +func (c *Config) WithHTTPClient(client *http.Client) *Config { + c.HTTPClient = client + return c +} + +// WithMaxRetries sets a config MaxRetries value returning a Config pointer +// for chaining. +func (c *Config) WithMaxRetries(max int) *Config { + c.MaxRetries = &max + return c +} + +// WithDisableParamValidation sets a config DisableParamValidation value +// returning a Config pointer for chaining. +func (c *Config) WithDisableParamValidation(disable bool) *Config { + c.DisableParamValidation = &disable + return c +} + +// WithDisableComputeChecksums sets a config DisableComputeChecksums value +// returning a Config pointer for chaining. +func (c *Config) WithDisableComputeChecksums(disable bool) *Config { + c.DisableComputeChecksums = &disable + return c +} + +// WithLogLevel sets a config LogLevel value returning a Config pointer for +// chaining. +func (c *Config) WithLogLevel(level LogLevelType) *Config { + c.LogLevel = &level + return c +} + +// WithLogger sets a config Logger value returning a Config pointer for +// chaining. +func (c *Config) WithLogger(logger Logger) *Config { + c.Logger = logger + return c +} + +// WithS3ForcePathStyle sets a config S3ForcePathStyle value returning a Config +// pointer for chaining. +func (c *Config) WithS3ForcePathStyle(force bool) *Config { + c.S3ForcePathStyle = &force + return c +} + +// 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 +// next retry. Defaults to time.Sleep. +func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config { + c.SleepDelay = fn + return c +} + +// MergeIn merges the passed in configs into the existing config object. +func (c *Config) MergeIn(cfgs ...*Config) { + for _, other := range cfgs { + mergeInConfig(c, other) + } +} + +func mergeInConfig(dst *Config, other *Config) { + if other == nil { + return + } + + if other.CredentialsChainVerboseErrors != nil { + dst.CredentialsChainVerboseErrors = other.CredentialsChainVerboseErrors + } + + if other.Credentials != nil { + dst.Credentials = other.Credentials + } + + if other.Endpoint != nil { + dst.Endpoint = other.Endpoint + } + + if other.EndpointResolver != nil { + dst.EndpointResolver = other.EndpointResolver + } + + if other.Region != nil { + dst.Region = other.Region + } + + if other.DisableSSL != nil { + dst.DisableSSL = other.DisableSSL + } + + if other.HTTPClient != nil { + dst.HTTPClient = other.HTTPClient + } + + if other.LogLevel != nil { + dst.LogLevel = other.LogLevel + } + + if other.Logger != nil { + dst.Logger = other.Logger + } + + if other.MaxRetries != nil { + dst.MaxRetries = other.MaxRetries + } + + if other.Retryer != nil { + dst.Retryer = other.Retryer + } + + if other.DisableParamValidation != nil { + dst.DisableParamValidation = other.DisableParamValidation + } + + if other.DisableComputeChecksums != nil { + dst.DisableComputeChecksums = other.DisableComputeChecksums + } + + if other.S3ForcePathStyle != nil { + dst.S3ForcePathStyle = other.S3ForcePathStyle + } + + if other.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 { + dst.SleepDelay = other.SleepDelay + } + + 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. If any additional +// configurations are provided they will be merged into the new config returned. +func (c *Config) Copy(cfgs ...*Config) *Config { + dst := &Config{} + dst.MergeIn(c) + + for _, cfg := range cfgs { + dst.MergeIn(cfg) + } + + return dst +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/config_test.go b/vendor/github.com/aws/aws-sdk-go/aws/config_test.go new file mode 100644 index 0000000..fe97a31 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/config_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/context.go b/vendor/github.com/aws/aws-sdk-go/aws/context.go new file mode 100644 index 0000000..79f4268 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/context.go @@ -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 +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/context_1_6.go b/vendor/github.com/aws/aws-sdk-go/aws/context_1_6.go new file mode 100644 index 0000000..8fdda53 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/context_1_6.go @@ -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) +) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/context_1_7.go b/vendor/github.com/aws/aws-sdk-go/aws/context_1_7.go new file mode 100644 index 0000000..064f75c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/context_1_7.go @@ -0,0 +1,9 @@ +// +build go1.7 + +package aws + +import "context" + +var ( + backgroundCtx = context.Background() +) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/context_test.go b/vendor/github.com/aws/aws-sdk-go/aws/context_test.go new file mode 100644 index 0000000..d80a1bb --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/context_test.go @@ -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) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go b/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go new file mode 100644 index 0000000..ff5d58e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/convert_types.go @@ -0,0 +1,387 @@ +package aws + +import "time" + +// String returns a pointer to the string value passed in. +func String(v string) *string { + return &v +} + +// StringValue returns the value of the string pointer passed in or +// "" if the pointer is nil. +func StringValue(v *string) string { + if v != nil { + return *v + } + return "" +} + +// StringSlice converts a slice of string values into a slice of +// string pointers +func StringSlice(src []string) []*string { + dst := make([]*string, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// StringValueSlice converts a slice of string pointers into a slice of +// string values +func StringValueSlice(src []*string) []string { + dst := make([]string, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// StringMap converts a string map of string values into a string +// map of string pointers +func StringMap(src map[string]string) map[string]*string { + dst := make(map[string]*string) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// StringValueMap converts a string map of string pointers into a string +// map of string values +func StringValueMap(src map[string]*string) map[string]string { + dst := make(map[string]string) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Bool returns a pointer to the bool value passed in. +func Bool(v bool) *bool { + return &v +} + +// BoolValue returns the value of the bool pointer passed in or +// false if the pointer is nil. +func BoolValue(v *bool) bool { + if v != nil { + return *v + } + return false +} + +// BoolSlice converts a slice of bool values into a slice of +// bool pointers +func BoolSlice(src []bool) []*bool { + dst := make([]*bool, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// BoolValueSlice converts a slice of bool pointers into a slice of +// bool values +func BoolValueSlice(src []*bool) []bool { + dst := make([]bool, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// BoolMap converts a string map of bool values into a string +// map of bool pointers +func BoolMap(src map[string]bool) map[string]*bool { + dst := make(map[string]*bool) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// BoolValueMap converts a string map of bool pointers into a string +// map of bool values +func BoolValueMap(src map[string]*bool) map[string]bool { + dst := make(map[string]bool) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int returns a pointer to the int value passed in. +func Int(v int) *int { + return &v +} + +// IntValue returns the value of the int pointer passed in or +// 0 if the pointer is nil. +func IntValue(v *int) int { + if v != nil { + return *v + } + return 0 +} + +// IntSlice converts a slice of int values into a slice of +// int pointers +func IntSlice(src []int) []*int { + dst := make([]*int, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// IntValueSlice converts a slice of int pointers into a slice of +// int values +func IntValueSlice(src []*int) []int { + dst := make([]int, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// IntMap converts a string map of int values into a string +// map of int pointers +func IntMap(src map[string]int) map[string]*int { + dst := make(map[string]*int) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// IntValueMap converts a string map of int pointers into a string +// map of int values +func IntValueMap(src map[string]*int) map[string]int { + dst := make(map[string]int) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int64 returns a pointer to the int64 value passed in. +func Int64(v int64) *int64 { + return &v +} + +// Int64Value returns the value of the int64 pointer passed in or +// 0 if the pointer is nil. +func Int64Value(v *int64) int64 { + if v != nil { + return *v + } + return 0 +} + +// Int64Slice converts a slice of int64 values into a slice of +// int64 pointers +func Int64Slice(src []int64) []*int64 { + dst := make([]*int64, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Int64ValueSlice converts a slice of int64 pointers into a slice of +// int64 values +func Int64ValueSlice(src []*int64) []int64 { + dst := make([]int64, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Int64Map converts a string map of int64 values into a string +// map of int64 pointers +func Int64Map(src map[string]int64) map[string]*int64 { + dst := make(map[string]*int64) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Int64ValueMap converts a string map of int64 pointers into a string +// map of int64 values +func Int64ValueMap(src map[string]*int64) map[string]int64 { + dst := make(map[string]int64) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Float64 returns a pointer to the float64 value passed in. +func Float64(v float64) *float64 { + return &v +} + +// Float64Value returns the value of the float64 pointer passed in or +// 0 if the pointer is nil. +func Float64Value(v *float64) float64 { + if v != nil { + return *v + } + return 0 +} + +// Float64Slice converts a slice of float64 values into a slice of +// float64 pointers +func Float64Slice(src []float64) []*float64 { + dst := make([]*float64, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Float64ValueSlice converts a slice of float64 pointers into a slice of +// float64 values +func Float64ValueSlice(src []*float64) []float64 { + dst := make([]float64, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Float64Map converts a string map of float64 values into a string +// map of float64 pointers +func Float64Map(src map[string]float64) map[string]*float64 { + dst := make(map[string]*float64) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Float64ValueMap converts a string map of float64 pointers into a string +// map of float64 values +func Float64ValueMap(src map[string]*float64) map[string]float64 { + dst := make(map[string]float64) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Time returns a pointer to the time.Time value passed in. +func Time(v time.Time) *time.Time { + return &v +} + +// TimeValue returns the value of the time.Time pointer passed in or +// time.Time{} if the pointer is nil. +func TimeValue(v *time.Time) time.Time { + if v != nil { + return *v + } + return time.Time{} +} + +// 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 +// time.Time pointers +func TimeSlice(src []time.Time) []*time.Time { + dst := make([]*time.Time, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// TimeValueSlice converts a slice of time.Time pointers into a slice of +// time.Time values +func TimeValueSlice(src []*time.Time) []time.Time { + dst := make([]time.Time, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// TimeMap converts a string map of time.Time values into a string +// map of time.Time pointers +func TimeMap(src map[string]time.Time) map[string]*time.Time { + dst := make(map[string]*time.Time) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// TimeValueMap converts a string map of time.Time pointers into a string +// map of time.Time values +func TimeValueMap(src map[string]*time.Time) map[string]time.Time { + dst := make(map[string]time.Time) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go b/vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go new file mode 100644 index 0000000..1a9461e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/convert_types_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go new file mode 100644 index 0000000..495e3ef --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go @@ -0,0 +1,242 @@ +package corehandlers + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "regexp" + "runtime" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/request" +) + +// Interface for matching types which also have a Len method. +type lener interface { + Len() int +} + +// 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 +// to determine request body length and no "Content-Length" was specified it will panic. +// +// The Content-Length will only be added to the request if the length of the body +// is greater than 0. If the body is empty or the current `Content-Length` +// header is <= 0, the header will also be stripped. +var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLengthHandler", Fn: func(r *request.Request) { + var length int64 + + if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" { + length, _ = strconv.ParseInt(slength, 10, 64) + } else { + switch body := r.Body.(type) { + case nil: + length = 0 + case lener: + length = int64(body.Len()) + case io.Seeker: + r.BodyStart, _ = body.Seek(0, 1) + end, _ := body.Seek(0, 2) + body.Seek(r.BodyStart, 0) // make sure to seek back to original location + length = end - r.BodyStart + default: + panic("Cannot get length of body, must provide `ContentLength`") + } + } + + if length > 0 { + 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") + } +}} + +// SDKVersionUserAgentHandler is a request handler for adding the SDK Version to the user agent. +var SDKVersionUserAgentHandler = request.NamedHandler{ + Name: "core.SDKVersionUserAgentHandler", + Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion, + runtime.Version(), runtime.GOOS, runtime.GOARCH), +} + +var reStatusCode = regexp.MustCompile(`^(\d{3})`) + +// ValidateReqSigHandler is a request handler to ensure that the request's +// signature doesn't expire before it is sent. This can happen when a request +// is built and signed significantly before it is sent. Or significant delays +// occur when retrying requests that would cause the signature to expire. +var ValidateReqSigHandler = request.NamedHandler{ + Name: "core.ValidateReqSigHandler", + Fn: func(r *request.Request) { + // Unsigned requests are not signed + if r.Config.Credentials == credentials.AnonymousCredentials { + return + } + + signedTime := r.Time + if !r.LastSignedAt.IsZero() { + signedTime = r.LastSignedAt + } + + // 10 minutes to allow for some clock skew/delays in transmission. + // Would be improved with aws/aws-sdk-go#423 + if signedTime.Add(10 * time.Minute).After(time.Now()) { + return + } + + fmt.Println("request expired, resigning") + r.Sign() + }, +} + +// SendHandler is a request handler to send service request using HTTP client. +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{ + StatusCode: int(code), + Status: http.StatusText(int(code)), + Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + } + return + } + } + if r.HTTPResponse == nil { + // Add a dummy request response object to ensure the HTTPResponse + // value is consistent. + r.HTTPResponse = &http.Response{ + StatusCode: int(0), + Status: http.StatusText(int(0)), + Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + } + } + // Catch all other request errors. + r.Error = awserr.New("RequestError", "send request failed", err) + r.Retryable = aws.Bool(true) // network errors are retryable + + // 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. +var ValidateResponseHandler = request.NamedHandler{Name: "core.ValidateResponseHandler", Fn: func(r *request.Request) { + if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 { + // this may be replaced by an UnmarshalError handler + r.Error = awserr.New("UnknownError", "unknown error", nil) + } +}} + +// AfterRetryHandler performs final checks to determine if the request should +// be retried and how long to delay. +var AfterRetryHandler = request.NamedHandler{Name: "core.AfterRetryHandler", Fn: func(r *request.Request) { + // If one of the other handlers already set the retry state + // we don't want to override it based on the service's state + if r.Retryable == nil || aws.BoolValue(r.Config.EnforceShouldRetryCheck) { + r.Retryable = aws.Bool(r.ShouldRetry(r)) + } + + if r.WillRetry() { + r.RetryDelay = r.RetryRules(r) + + 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 + // need to be expired locally so that the next request to + // get credentials will trigger a credentials refresh. + if r.IsErrorExpired() { + r.Config.Credentials.Expire() + } + + r.RetryCount++ + r.Error = nil + } +}} + +// ValidateEndpointHandler is a request handler to validate a request had the +// appropriate Region and Endpoint set. Will set r.Error if the endpoint or +// region is not valid. +var ValidateEndpointHandler = request.NamedHandler{Name: "core.ValidateEndpointHandler", Fn: func(r *request.Request) { + if r.ClientInfo.SigningRegion == "" && aws.StringValue(r.Config.Region) == "" { + r.Error = aws.ErrMissingRegion + } else if r.ClientInfo.Endpoint == "" { + r.Error = aws.ErrMissingEndpoint + } +}} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_1_8_test.go b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_1_8_test.go new file mode 100644 index 0000000..b47afc2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_1_8_test.go @@ -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) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go new file mode 100644 index 0000000..1d715c9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go @@ -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) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go new file mode 100644 index 0000000..7d50b15 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go @@ -0,0 +1,17 @@ +package corehandlers + +import "github.com/aws/aws-sdk-go/aws/request" + +// ValidateParametersHandler is a request handler to validate the input parameters. +// Validating parameters only has meaning if done prior to the request being sent. +var ValidateParametersHandler = request.NamedHandler{Name: "core.ValidateParametersHandler", Fn: func(r *request.Request) { + if !r.ParamsFilled() { + return + } + + if v, ok := r.Params.(request.Validator); ok { + if err := v.Validate(); err != nil { + r.Error = err + } + } +}} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go new file mode 100644 index 0000000..e1d8a08 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go new file mode 100644 index 0000000..f298d65 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go @@ -0,0 +1,102 @@ +package credentials + +import ( + "github.com/aws/aws-sdk-go/aws/awserr" +) + +var ( + // ErrNoValidProvidersFoundInChain Is returned when there are no valid + // providers in the ChainProvider. + // + // This has been deprecated. For verbose error messaging set + // aws.Config.CredentialsChainVerboseErrors to true + // + // @readonly + 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 +// and cache that provider until Retrieve is called again. +// +// The ChainProvider provides a way of chaining multiple providers together +// which will pick the first available using priority order of the Providers +// in the list. +// +// If none of the Providers retrieve valid credentials Value, ChainProvider's +// Retrieve() will return the error ErrNoValidProvidersFoundInChain. +// +// If a Provider is found which returns valid credentials Value ChainProvider +// will cache that Provider for all calls to IsExpired(), until Retrieve is +// called again. +// +// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider. +// In this example EnvProvider will first check if any credentials are available +// via the environment variables. If there are none ChainProvider will check +// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider +// does not return any credentials ChainProvider will return the error +// ErrNoValidProvidersFoundInChain +// +// creds := credentials.NewChainCredentials( +// []credentials.Provider{ +// &credentials.EnvProvider{}, +// &ec2rolecreds.EC2RoleProvider{ +// Client: ec2metadata.New(sess), +// }, +// }) +// +// // Usage of ChainCredentials with aws.Config +// svc := ec2.New(session.Must(session.NewSession(&aws.Config{ +// Credentials: creds, +// }))) +// +type ChainProvider struct { + Providers []Provider + curr Provider + VerboseErrors bool +} + +// NewChainCredentials returns a pointer to a new Credentials object +// wrapping a chain of providers. +func NewChainCredentials(providers []Provider) *Credentials { + return NewCredentials(&ChainProvider{ + Providers: append([]Provider{}, providers...), + }) +} + +// Retrieve returns the credentials value or error if no provider returned +// without error. +// +// If a provider is found it will be cached and any calls to IsExpired() +// will return the expired state of the cached provider. +func (c *ChainProvider) Retrieve() (Value, error) { + var errs []error + for _, p := range c.Providers { + creds, err := p.Retrieve() + if err == nil { + c.curr = p + return creds, nil + } + errs = append(errs, err) + } + c.curr = nil + + var err error + err = 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 +// if there is one. If there is no current provider, true will be returned. +func (c *ChainProvider) IsExpired() bool { + if c.curr != nil { + return c.curr.IsExpired() + } + + return true +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go new file mode 100644 index 0000000..3b393a2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go @@ -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") +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go new file mode 100644 index 0000000..42416fc --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go @@ -0,0 +1,246 @@ +// Package credentials provides credential retrieval and management +// +// The Credentials is the primary method of getting access to and managing +// credentials Values. Using dependency injection retrieval of the credential +// values is handled by a object which satisfies the Provider interface. +// +// By default the Credentials.Get() will cache the successful result of a +// Provider's Retrieve() until Provider.IsExpired() returns true. At which +// point Credentials will call Provider's Retrieve() to get new credential Value. +// +// The Provider is responsible for determining when credentials Value have expired. +// It is also important to note that Credentials will always call Retrieve the +// first time Credentials.Get() is called. +// +// Example of using the environment variable credentials. +// +// creds := credentials.NewEnvCredentials() +// +// // Retrieve the credentials value +// credValue, err := creds.Get() +// if err != nil { +// // handle error +// } +// +// Example of forcing credentials to expire and be refreshed on the next Get(). +// This may be helpful to proactively expire credentials and refresh them sooner +// than they would naturally expire on their own. +// +// creds := credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{}) +// creds.Expire() +// credsValue, err := creds.Get() +// // New credentials will be retrieved instead of from cache. +// +// +// Custom Provider +// +// Each Provider built into this package also provides a helper method to generate +// a Credentials pointer setup with the provider. To use a custom Provider just +// create a type which satisfies the Provider interface and pass it to the +// NewCredentials method. +// +// type MyProvider struct{} +// func (m *MyProvider) Retrieve() (Value, error) {...} +// func (m *MyProvider) IsExpired() bool {...} +// +// creds := credentials.NewCredentials(&MyProvider{}) +// credValue, err := creds.Get() +// +package credentials + +import ( + "sync" + "time" +) + +// AnonymousCredentials is an empty Credential object that can be used as +// dummy placeholder credentials for requests that do not need signed. +// +// This Credentials can be used to configure a service to not sign requests +// when making service API calls. For example, when accessing public +// s3 buckets. +// +// svc := s3.New(session.Must(session.NewSession(&aws.Config{ +// Credentials: credentials.AnonymousCredentials, +// }))) +// // Access public S3 buckets. +// +// @readonly +var AnonymousCredentials = NewStaticCredentials("", "", "") + +// A Value is the AWS credentials value for individual credential fields. +type Value struct { + // AWS Access key ID + AccessKeyID string + + // AWS Secret Access Key + SecretAccessKey string + + // AWS Session Token + SessionToken string + + // Provider used to get credentials + ProviderName string +} + +// A Provider is the interface for any component which will provide credentials +// Value. A provider is required to manage its own Expired state, and what to +// be expired means. +// +// The Provider should not need to implement its own mutexes, because +// that will be managed by Credentials. +type Provider interface { + // Retrieve returns nil if it successfully retrieved the value. + // Error is returned if the value were not obtainable, or empty. + Retrieve() (Value, error) + + // IsExpired returns if the credentials are no longer valid, and need + // to be retrieved. + IsExpired() bool +} + +// 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 +// providers to implement expiry functionality. +// +// The best method to use this struct is as an anonymous field within the +// provider's struct. +// +// Example: +// type EC2RoleProvider struct { +// Expiry +// ... +// } +type Expiry struct { + // The date/time when to expire on + expiration time.Time + + // If set will be used by IsExpired to determine the current time. + // Defaults to time.Now if CurrentTime is not set. Available for testing + // to be able to mock out the current time. + CurrentTime func() time.Time +} + +// SetExpiration sets the expiration IsExpired will check when called. +// +// If window is greater than 0 the expiration time will be reduced by the +// window value. +// +// Using a window is helpful to trigger credentials to expire sooner than +// the expiration time given to ensure no requests are made with expired +// tokens. +func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) { + e.expiration = expiration + if window > 0 { + e.expiration = e.expiration.Add(-window) + } +} + +// IsExpired returns if the credentials are expired. +func (e *Expiry) IsExpired() bool { + if e.CurrentTime == nil { + e.CurrentTime = time.Now + } + return e.expiration.Before(e.CurrentTime()) +} + +// A Credentials provides synchronous safe retrieval of AWS credentials Value. +// Credentials will cache the credentials value until they expire. Once the value +// expires the next Get will attempt to retrieve valid credentials. +// +// Credentials is safe to use across multiple goroutines and will manage the +// synchronous state so the Providers do not need to implement their own +// synchronization. +// +// The first Credentials.Get() will always call Provider.Retrieve() to get the +// first instance of the credentials Value. All calls to Get() after that +// will return the cached credentials Value until IsExpired() returns true. +type Credentials struct { + creds Value + forceRefresh bool + m sync.Mutex + + provider Provider +} + +// NewCredentials returns a pointer to a new Credentials with the provider set. +func NewCredentials(provider Provider) *Credentials { + return &Credentials{ + provider: provider, + forceRefresh: true, + } +} + +// Get returns the credentials value, or error if the credentials Value failed +// to be retrieved. +// +// Will return the cached credentials Value if it has not expired. If the +// credentials Value has expired the Provider's Retrieve() will be called +// to refresh the credentials. +// +// If Credentials.Expire() was called the credentials Value will be force +// expired, and the next call to Get() will cause them to be refreshed. +func (c *Credentials) Get() (Value, error) { + c.m.Lock() + defer c.m.Unlock() + + if c.isExpired() { + creds, err := c.provider.Retrieve() + if err != nil { + return Value{}, err + } + c.creds = creds + c.forceRefresh = false + } + + return c.creds, nil +} + +// Expire expires the credentials and forces them to be retrieved on the +// next call to Get(). +// +// This will override the Provider's expired state, and force Credentials +// to call the Provider's Retrieve(). +func (c *Credentials) Expire() { + c.m.Lock() + defer c.m.Unlock() + + c.forceRefresh = true +} + +// IsExpired returns if the credentials are no longer valid, and need +// to be retrieved. +// +// If the Credentials were forced to be expired with Expire() this will +// reflect that override. +func (c *Credentials) IsExpired() bool { + c.m.Lock() + defer c.m.Unlock() + + return c.isExpired() +} + +// isExpired helper method wrapping the definition of expired credentials. +func (c *Credentials) isExpired() bool { + return c.forceRefresh || c.provider.IsExpired() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go new file mode 100644 index 0000000..7b79ba9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go @@ -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") +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go new file mode 100644 index 0000000..c397495 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go @@ -0,0 +1,178 @@ +package ec2rolecreds + +import ( + "bufio" + "encoding/json" + "fmt" + "path" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/credentials" + "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 +// those credentials are expired. +// +// Example how to configure the EC2RoleProvider with custom http Client, Endpoint +// or ExpiryWindow +// +// p := &ec2rolecreds.EC2RoleProvider{ +// // Pass in a custom timeout to be used when requesting +// // IAM EC2 Role credentials. +// Client: ec2metadata.New(sess, aws.Config{ +// HTTPClient: &http.Client{Timeout: 10 * time.Second}, +// }), +// +// // Do not use early expiry of credentials. If a non zero value is +// // specified the credentials will be expired early +// ExpiryWindow: 0, +// } +type EC2RoleProvider struct { + credentials.Expiry + + // Required EC2Metadata client to use when connecting to EC2 metadata service. + Client *ec2metadata.EC2Metadata + + // ExpiryWindow will allow the credentials to trigger refreshing prior to + // the credentials actually expiring. This is beneficial so race conditions + // with expiring credentials do not cause request to fail unexpectedly + // due to ExpiredTokenException exceptions. + // + // So a ExpiryWindow of 10s would cause calls to IsExpired() to return true + // 10 seconds before the credentials are actually expired. + // + // If ExpiryWindow is 0 or less it will be ignored. + ExpiryWindow time.Duration +} + +// NewCredentials returns a pointer to a new Credentials object wrapping +// the EC2RoleProvider. Takes a ConfigProvider to create a EC2Metadata client. +// The ConfigProvider is satisfied by the session.Session type. +func NewCredentials(c client.ConfigProvider, options ...func(*EC2RoleProvider)) *credentials.Credentials { + p := &EC2RoleProvider{ + Client: ec2metadata.New(c), + } + + for _, option := range options { + option(p) + } + + return credentials.NewCredentials(p) +} + +// 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. +// Error will be returned if the request fails, or unable to extract +// the desired credentials. +func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) { + credsList, err := requestCredList(m.Client) + if err != nil { + return credentials.Value{ProviderName: ProviderName}, err + } + + if len(credsList) == 0 { + return credentials.Value{ProviderName: ProviderName}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil) + } + credsName := credsList[0] + + roleCreds, err := requestCred(m.Client, credsName) + if err != nil { + return credentials.Value{ProviderName: ProviderName}, err + } + + m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow) + + return credentials.Value{ + AccessKeyID: roleCreds.AccessKeyID, + SecretAccessKey: roleCreds.SecretAccessKey, + SessionToken: roleCreds.Token, + ProviderName: ProviderName, + }, nil +} + +// A ec2RoleCredRespBody provides the shape for unmarshaling credential +// request responses. +type ec2RoleCredRespBody struct { + // Success State + Expiration time.Time + AccessKeyID string + SecretAccessKey string + Token string + + // Error state + Code string + Message string +} + +const iamSecurityCredsPath = "/iam/security-credentials" + +// requestCredList requests a list of credentials from the EC2 service. +// If there are no credentials, or there is an error making or receiving the request +func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) { + resp, err := client.GetMetadata(iamSecurityCredsPath) + if err != nil { + return nil, awserr.New("EC2RoleRequestError", "no EC2 instance role found", err) + } + + credsList := []string{} + s := bufio.NewScanner(strings.NewReader(resp)) + for s.Scan() { + credsList = append(credsList, s.Text()) + } + + if err := s.Err(); err != nil { + return nil, awserr.New("SerializationError", "failed to read EC2 instance role from metadata service", err) + } + + return credsList, nil +} + +// requestCred requests the credentials for a specific credentials from the EC2 service. +// +// If the credentials cannot be found, or there is an error reading the response +// and error will be returned. +func requestCred(client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) { + resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName)) + if err != nil { + return ec2RoleCredRespBody{}, + awserr.New("EC2RoleRequestError", + fmt.Sprintf("failed to get %s EC2 instance role credentials", credsName), + err) + } + + respCreds := ec2RoleCredRespBody{} + if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil { + return ec2RoleCredRespBody{}, + awserr.New("SerializationError", + fmt.Sprintf("failed to decode %s EC2 instance role credentials", credsName), + err) + } + + if respCreds.Code != "Success" { + // If an error code was returned something failed requesting the role. + return ec2RoleCredRespBody{}, awserr.New(respCreds.Code, respCreds.Message, nil) + } + + return respCreds, nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go new file mode 100644 index 0000000..cccd4bf --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go new file mode 100644 index 0000000..a4cec5c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go @@ -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) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go new file mode 100644 index 0000000..ad057a3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider_test.go @@ -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()) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go new file mode 100644 index 0000000..c14231a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go @@ -0,0 +1,78 @@ +package credentials + +import ( + "os" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +// EnvProviderName provides a name of Env provider +const EnvProviderName = "EnvProvider" + +var ( + // ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be + // found in the process's environment. + // + // @readonly + ErrAccessKeyIDNotFound = awserr.New("EnvAccessKeyNotFound", "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment", nil) + + // ErrSecretAccessKeyNotFound is returned when the AWS Secret Access Key + // can't be found in the process's environment. + // + // @readonly + ErrSecretAccessKeyNotFound = awserr.New("EnvSecretNotFound", "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment", nil) +) + +// A EnvProvider retrieves credentials from the environment variables of the +// running process. Environment credentials never expire. +// +// Environment variables used: +// +// * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY +// +// * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY +type EnvProvider struct { + retrieved bool +} + +// NewEnvCredentials returns a pointer to a new Credentials object +// wrapping the environment variable provider. +func NewEnvCredentials() *Credentials { + return NewCredentials(&EnvProvider{}) +} + +// Retrieve retrieves the keys from the environment. +func (e *EnvProvider) Retrieve() (Value, error) { + e.retrieved = false + + id := os.Getenv("AWS_ACCESS_KEY_ID") + if id == "" { + id = os.Getenv("AWS_ACCESS_KEY") + } + + secret := os.Getenv("AWS_SECRET_ACCESS_KEY") + if secret == "" { + secret = os.Getenv("AWS_SECRET_KEY") + } + + if id == "" { + return Value{ProviderName: EnvProviderName}, ErrAccessKeyIDNotFound + } + + if secret == "" { + return Value{ProviderName: EnvProviderName}, ErrSecretAccessKeyNotFound + } + + e.retrieved = true + return Value{ + AccessKeyID: id, + SecretAccessKey: secret, + SessionToken: os.Getenv("AWS_SESSION_TOKEN"), + ProviderName: EnvProviderName, + }, nil +} + +// IsExpired returns if the credentials have been retrieved. +func (e *EnvProvider) IsExpired() bool { + return !e.retrieved +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go new file mode 100644 index 0000000..53f6ce2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go @@ -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") +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini b/vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini new file mode 100644 index 0000000..7fc91d9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini @@ -0,0 +1,12 @@ +[default] +aws_access_key_id = accessKey +aws_secret_access_key = secret +aws_session_token = token + +[no_token] +aws_access_key_id = accessKey +aws_secret_access_key = secret + +[with_colon] +aws_access_key_id: accessKey +aws_secret_access_key: secret diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go new file mode 100644 index 0000000..51e21e0 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go @@ -0,0 +1,150 @@ +package credentials + +import ( + "fmt" + "os" + + "github.com/go-ini/ini" + + "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 ( + // ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found. + ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil) +) + +// A SharedCredentialsProvider retrieves credentials from the current user's home +// directory, and keeps track if those credentials are expired. +// +// Profile ini file example: $HOME/.aws/credentials +type SharedCredentialsProvider struct { + // Path to the shared credentials file. + // + // If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the + // env value is empty will default to current user's home directory. + // Linux/OSX: "$HOME/.aws/credentials" + // Windows: "%USERPROFILE%\.aws\credentials" + Filename string + + // AWS Profile to extract credentials from the shared credentials file. If empty + // will default to environment variable "AWS_PROFILE" or "default" if + // environment variable is also not set. + Profile string + + // retrieved states if the credentials have been successfully retrieved. + retrieved bool +} + +// NewSharedCredentials returns a pointer to a new Credentials object +// wrapping the Profile file provider. +func NewSharedCredentials(filename, profile string) *Credentials { + return NewCredentials(&SharedCredentialsProvider{ + Filename: filename, + Profile: profile, + }) +} + +// Retrieve reads and extracts the shared credentials from the current +// users home directory. +func (p *SharedCredentialsProvider) Retrieve() (Value, error) { + p.retrieved = false + + filename, err := p.filename() + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, err + } + + creds, err := loadProfile(filename, p.profile()) + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, err + } + + p.retrieved = true + return creds, nil +} + +// IsExpired returns if the shared credentials have expired. +func (p *SharedCredentialsProvider) IsExpired() bool { + return !p.retrieved +} + +// loadProfiles loads from the file pointed to by shared credentials filename for profile. +// The credentials retrieved from the profile will be returned or error. Error will be +// returned if it fails to read from the file, or the data is invalid. +func loadProfile(filename, profile string) (Value, error) { + config, err := ini.Load(filename) + if err != nil { + 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) + } + + id, err := iniProfile.GetKey("aws_access_key_id") + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsAccessKey", + fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename), + err) + } + + secret, err := iniProfile.GetKey("aws_secret_access_key") + if err != nil { + return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsSecret", + fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename), + nil) + } + + // Default to empty string if not found + token := iniProfile.Key("aws_session_token") + + return Value{ + AccessKeyID: id.String(), + SecretAccessKey: secret.String(), + SessionToken: token.String(), + ProviderName: SharedCredsProviderName, + }, nil +} + +// filename returns the filename to use to read AWS shared credentials. +// +// Will return an error if the user's home directory path cannot be found. +func (p *SharedCredentialsProvider) filename() (string, error) { + if len(p.Filename) != 0 { + return p.Filename, nil + } + + 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 +} + +// profile returns the AWS shared credentials profile. If empty will read +// environment variable "AWS_PROFILE". If that is not set profile will +// return "default". +func (p *SharedCredentialsProvider) profile() string { + if p.Profile == "" { + p.Profile = os.Getenv("AWS_PROFILE") + } + if p.Profile == "" { + p.Profile = "default" + } + + return p.Profile +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go new file mode 100644 index 0000000..1eb45f2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go new file mode 100644 index 0000000..4f5dab3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go @@ -0,0 +1,57 @@ +package credentials + +import ( + "github.com/aws/aws-sdk-go/aws/awserr" +) + +// StaticProviderName provides a name of Static provider +const StaticProviderName = "StaticProvider" + +var ( + // ErrStaticCredentialsEmpty is emitted when static credentials are empty. + // + // @readonly + ErrStaticCredentialsEmpty = awserr.New("EmptyStaticCreds", "static credentials are empty", nil) +) + +// A StaticProvider is a set of credentials which are set programmatically, +// and will never expire. +type StaticProvider struct { + Value +} + +// NewStaticCredentials returns a pointer to a new Credentials object +// wrapping a static credentials value provider. +func NewStaticCredentials(id, secret, token string) *Credentials { + return NewCredentials(&StaticProvider{Value: Value{ + AccessKeyID: id, + SecretAccessKey: secret, + SessionToken: token, + }}) +} + +// 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. +func (s *StaticProvider) Retrieve() (Value, error) { + if s.AccessKeyID == "" || s.SecretAccessKey == "" { + return Value{ProviderName: StaticProviderName}, ErrStaticCredentialsEmpty + } + + if len(s.Value.ProviderName) == 0 { + s.Value.ProviderName = StaticProviderName + } + return s.Value, nil +} + +// IsExpired returns if the credentials are expired. +// +// For StaticProvider, the credentials never expired. +func (s *StaticProvider) IsExpired() bool { + return false +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go new file mode 100644 index 0000000..ea01236 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go @@ -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") +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go new file mode 100644 index 0000000..4108e43 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go @@ -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 +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go new file mode 100644 index 0000000..4c0212a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go @@ -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) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go new file mode 100644 index 0000000..07afe3b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go @@ -0,0 +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 + +import ( + "fmt" + "net/http" + "net/url" + "os" + "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/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" +) + +// A Defaults provides a collection of default values for SDK clients. +type Defaults struct { + Config *aws.Config + Handlers request.Handlers +} + +// Get returns the SDK's default values with Config and handlers pre-configured. +func Get() Defaults { + 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. +// +// Generally you shouldn't need to use this method directly, but +// is available if you need to reset the configuration of an +// existing service client or session. +func Config() *aws.Config { + return aws.NewConfig(). + WithCredentials(credentials.AnonymousCredentials). + WithRegion(os.Getenv("AWS_REGION")). + WithHTTPClient(http.DefaultClient). + WithMaxRetries(aws.UseServiceDefaultRetries). + WithLogger(aws.NewDefaultLogger()). + 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, + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go new file mode 100644 index 0000000..d3e4a86 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults_test.go @@ -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) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go b/vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go new file mode 100644 index 0000000..ca0ee1d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go @@ -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() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/doc.go b/vendor/github.com/aws/aws-sdk-go/aws/doc.go new file mode 100644 index 0000000..4fcb616 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/doc.go @@ -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 diff --git a/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go new file mode 100644 index 0000000..984407a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go @@ -0,0 +1,162 @@ +package ec2metadata + +import ( + "encoding/json" + "fmt" + "net/http" + "path" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" +) + +// GetMetadata uses the path provided to request information from the EC2 +// 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{ + Name: "GetMetadata", + HTTPMethod: "GET", + HTTPPath: path.Join("/", "meta-data", p), + } + + output := &metadataOutput{} + req := c.NewRequest(op, nil, output) + + 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. +func (c *EC2Metadata) Region() (string, error) { + resp, err := c.GetMetadata("placement/availability-zone") + if err != nil { + return "", err + } + + // returns region without the suffix. Eg: us-west-2a becomes us-west-2 + return resp[:len(resp)-1], nil +} + +// Available returns if the application has access to the EC2 Metadata service. +// Can be used to determine if application is running within an EC2 Instance and +// the metadata service is available. +func (c *EC2Metadata) Available() bool { + if _, err := c.GetMetadata("instance-id"); err != nil { + return false + } + + 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"` +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go new file mode 100644 index 0000000..7dde1fb --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go @@ -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(` + + + + 404 - Not Found + + +

404 - Not Found

+ +`) + 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) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go new file mode 100644 index 0000000..5b4379d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go @@ -0,0 +1,124 @@ +// Package ec2metadata provides the client for making API calls to the +// EC2 Metadata service. +package ec2metadata + +import ( + "bytes" + "errors" + "io" + "net/http" + "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/request" +) + +// ServiceName is the name of the service. +const ServiceName = "ec2metadata" + +// A EC2Metadata is an EC2 Metadata service Client. +type EC2Metadata struct { + *client.Client +} + +// New creates a new instance of the EC2Metadata client with a session. +// This client is safe to use across multiple goroutines. +// +// +// Example: +// // Create a EC2Metadata client from just a session. +// svc := ec2metadata.New(mySession) +// +// // Create a EC2Metadata client with additional configuration +// svc := ec2metadata.New(mySession, aws.NewConfig().WithLogLevel(aws.LogDebugHTTPBody)) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2Metadata { + c := p.ClientConfig(ServiceName, cfgs...) + return NewClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion) +} + +// NewClient returns a new EC2Metadata client. Should be used to create +// a client when not using a session. Generally using just New with a session +// is preferred. +// +// If an unmodified HTTP client is provided from the stdlib default, or no client +// the EC2RoleProvider's EC2Metadata HTTP client's timeout will be shortened. +// To disable this set Config.EC2MetadataDisableTimeoutOverride to false. Enabled by default. +func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string, opts ...func(*client.Client)) *EC2Metadata { + if !aws.BoolValue(cfg.EC2MetadataDisableTimeoutOverride) && httpClientZero(cfg.HTTPClient) { + // If the http client is unmodified and this feature is not disabled + // 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, + } + } + + svc := &EC2Metadata{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + Endpoint: endpoint, + APIVersion: "latest", + }, + handlers, + ), + } + + 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 { + Content string +} + +func unmarshalHandler(r *request.Request) { + defer r.HTTPResponse.Body.Close() + b := &bytes.Buffer{} + if _, err := io.Copy(b, r.HTTPResponse.Body); err != nil { + r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err) + return + } + + if data, ok := r.Data.(*metadataOutput); ok { + data.Content = b.String() + } +} + +func unmarshalError(r *request.Request) { + defer r.HTTPResponse.Body.Close() + b := &bytes.Buffer{} + if _, err := io.Copy(b, r.HTTPResponse.Body); err != nil { + r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err) + return + } + + // 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) { + if r.ClientInfo.Endpoint == "" { + r.Error = aws.ErrMissingEndpoint + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go new file mode 100644 index 0000000..c2bc215 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service_test.go @@ -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() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go new file mode 100644 index 0000000..74f72de --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go @@ -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), + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode_test.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode_test.go new file mode 100644 index 0000000..3193907 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode_test.go @@ -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) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go new file mode 100644 index 0000000..8437d6e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go @@ -0,0 +1,2551 @@ +// Code generated by aws/endpoints/v3model_codegen.go. DO NOT EDIT. + +package endpoints + +import ( + "regexp" +) + +// Partition identifiers +const ( + AwsPartitionID = "aws" // AWS Standard partition. + AwsCnPartitionID = "aws-cn" // AWS China partition. + AwsUsGovPartitionID = "aws-us-gov" // AWS GovCloud (US) partition. +) + +// AWS Standard partition's regions. +const ( + ApNortheast1RegionID = "ap-northeast-1" // Asia Pacific (Tokyo). + ApNortheast2RegionID = "ap-northeast-2" // Asia Pacific (Seoul). + ApSouth1RegionID = "ap-south-1" // Asia Pacific (Mumbai). + ApSoutheast1RegionID = "ap-southeast-1" // Asia Pacific (Singapore). + ApSoutheast2RegionID = "ap-southeast-2" // Asia Pacific (Sydney). + CaCentral1RegionID = "ca-central-1" // Canada (Central). + EuCentral1RegionID = "eu-central-1" // EU (Frankfurt). + EuWest1RegionID = "eu-west-1" // EU (Ireland). + EuWest2RegionID = "eu-west-2" // EU (London). + SaEast1RegionID = "sa-east-1" // South America (Sao Paulo). + UsEast1RegionID = "us-east-1" // US East (N. Virginia). + UsEast2RegionID = "us-east-2" // US East (Ohio). + UsWest1RegionID = "us-west-1" // US West (N. California). + UsWest2RegionID = "us-west-2" // US West (Oregon). +) + +// AWS China partition's regions. +const ( + CnNorth1RegionID = "cn-north-1" // China (Beijing). +) + +// AWS GovCloud (US) partition's regions. +const ( + UsGovWest1RegionID = "us-gov-west-1" // AWS GovCloud (US). +) + +// Service identifiers +const ( + AcmServiceID = "acm" // Acm. + ApiPricingServiceID = "api.pricing" // ApiPricing. + ApigatewayServiceID = "apigateway" // Apigateway. + ApplicationAutoscalingServiceID = "application-autoscaling" // ApplicationAutoscaling. + Appstream2ServiceID = "appstream2" // Appstream2. + AthenaServiceID = "athena" // Athena. + AutoscalingServiceID = "autoscaling" // Autoscaling. + BatchServiceID = "batch" // Batch. + BudgetsServiceID = "budgets" // Budgets. + ClouddirectoryServiceID = "clouddirectory" // Clouddirectory. + CloudformationServiceID = "cloudformation" // Cloudformation. + CloudfrontServiceID = "cloudfront" // Cloudfront. + CloudhsmServiceID = "cloudhsm" // Cloudhsm. + Cloudhsmv2ServiceID = "cloudhsmv2" // Cloudhsmv2. + CloudsearchServiceID = "cloudsearch" // Cloudsearch. + CloudtrailServiceID = "cloudtrail" // Cloudtrail. + CodebuildServiceID = "codebuild" // Codebuild. + CodecommitServiceID = "codecommit" // Codecommit. + CodedeployServiceID = "codedeploy" // Codedeploy. + CodepipelineServiceID = "codepipeline" // Codepipeline. + CodestarServiceID = "codestar" // Codestar. + CognitoIdentityServiceID = "cognito-identity" // CognitoIdentity. + CognitoIdpServiceID = "cognito-idp" // CognitoIdp. + CognitoSyncServiceID = "cognito-sync" // CognitoSync. + ConfigServiceID = "config" // Config. + CurServiceID = "cur" // Cur. + DatapipelineServiceID = "datapipeline" // Datapipeline. + DaxServiceID = "dax" // Dax. + DevicefarmServiceID = "devicefarm" // Devicefarm. + DirectconnectServiceID = "directconnect" // Directconnect. + DiscoveryServiceID = "discovery" // Discovery. + DmsServiceID = "dms" // Dms. + DsServiceID = "ds" // Ds. + DynamodbServiceID = "dynamodb" // Dynamodb. + Ec2ServiceID = "ec2" // Ec2. + Ec2metadataServiceID = "ec2metadata" // Ec2metadata. + EcrServiceID = "ecr" // Ecr. + EcsServiceID = "ecs" // Ecs. + ElasticacheServiceID = "elasticache" // Elasticache. + ElasticbeanstalkServiceID = "elasticbeanstalk" // Elasticbeanstalk. + ElasticfilesystemServiceID = "elasticfilesystem" // Elasticfilesystem. + ElasticloadbalancingServiceID = "elasticloadbalancing" // Elasticloadbalancing. + ElasticmapreduceServiceID = "elasticmapreduce" // Elasticmapreduce. + ElastictranscoderServiceID = "elastictranscoder" // Elastictranscoder. + EmailServiceID = "email" // Email. + EntitlementMarketplaceServiceID = "entitlement.marketplace" // EntitlementMarketplace. + EsServiceID = "es" // Es. + EventsServiceID = "events" // Events. + FirehoseServiceID = "firehose" // Firehose. + GameliftServiceID = "gamelift" // Gamelift. + GlacierServiceID = "glacier" // Glacier. + GlueServiceID = "glue" // Glue. + GreengrassServiceID = "greengrass" // Greengrass. + HealthServiceID = "health" // Health. + IamServiceID = "iam" // Iam. + ImportexportServiceID = "importexport" // Importexport. + InspectorServiceID = "inspector" // Inspector. + IotServiceID = "iot" // Iot. + KinesisServiceID = "kinesis" // Kinesis. + KinesisanalyticsServiceID = "kinesisanalytics" // Kinesisanalytics. + KmsServiceID = "kms" // Kms. + LambdaServiceID = "lambda" // Lambda. + LightsailServiceID = "lightsail" // Lightsail. + LogsServiceID = "logs" // Logs. + MachinelearningServiceID = "machinelearning" // Machinelearning. + MarketplacecommerceanalyticsServiceID = "marketplacecommerceanalytics" // Marketplacecommerceanalytics. + MeteringMarketplaceServiceID = "metering.marketplace" // MeteringMarketplace. + MghServiceID = "mgh" // Mgh. + MobileanalyticsServiceID = "mobileanalytics" // Mobileanalytics. + ModelsLexServiceID = "models.lex" // ModelsLex. + MonitoringServiceID = "monitoring" // Monitoring. + MturkRequesterServiceID = "mturk-requester" // MturkRequester. + OpsworksServiceID = "opsworks" // Opsworks. + OpsworksCmServiceID = "opsworks-cm" // OpsworksCm. + OrganizationsServiceID = "organizations" // Organizations. + PinpointServiceID = "pinpoint" // Pinpoint. + PollyServiceID = "polly" // Polly. + RdsServiceID = "rds" // Rds. + RedshiftServiceID = "redshift" // Redshift. + RekognitionServiceID = "rekognition" // Rekognition. + Route53ServiceID = "route53" // Route53. + Route53domainsServiceID = "route53domains" // Route53domains. + RuntimeLexServiceID = "runtime.lex" // RuntimeLex. + S3ServiceID = "s3" // S3. + SdbServiceID = "sdb" // Sdb. + ServicecatalogServiceID = "servicecatalog" // Servicecatalog. + ShieldServiceID = "shield" // Shield. + SmsServiceID = "sms" // Sms. + SnowballServiceID = "snowball" // Snowball. + SnsServiceID = "sns" // Sns. + SqsServiceID = "sqs" // Sqs. + SsmServiceID = "ssm" // Ssm. + StatesServiceID = "states" // States. + StoragegatewayServiceID = "storagegateway" // Storagegateway. + StreamsDynamodbServiceID = "streams.dynamodb" // StreamsDynamodb. + StsServiceID = "sts" // Sts. + SupportServiceID = "support" // Support. + SwfServiceID = "swf" // Swf. + TaggingServiceID = "tagging" // Tagging. + WafServiceID = "waf" // Waf. + WafRegionalServiceID = "waf-regional" // WafRegional. + WorkdocsServiceID = "workdocs" // Workdocs. + WorkspacesServiceID = "workspaces" // Workspaces. + XrayServiceID = "xray" // Xray. +) + +// DefaultResolver returns an Endpoint resolver that will be able +// to resolve endpoints for: AWS Standard, AWS China, and AWS GovCloud (US). +// +// Use DefaultPartitions() to get the list of the default partitions. +func DefaultResolver() Resolver { + return defaultPartitions +} + +// DefaultPartitions returns a list of the partitions the SDK is bundled +// with. The available partitions are: AWS Standard, AWS China, and AWS GovCloud (US). +// +// partitions := endpoints.DefaultPartitions +// for _, p := range partitions { +// // ... inspect partitions +// } +func DefaultPartitions() []Partition { + return defaultPartitions.Partitions() +} + +var defaultPartitions = partitions{ + awsPartition, + awscnPartition, + awsusgovPartition, +} + +// AwsPartition returns the Resolver for AWS Standard. +func AwsPartition() Partition { + return awsPartition.Partition() +} + +var awsPartition = partition{ + ID: "aws", + Name: "AWS Standard", + DNSSuffix: "amazonaws.com", + RegionRegex: regionRegex{ + Regexp: func() *regexp.Regexp { + reg, _ := regexp.Compile("^(us|eu|ap|sa|ca)\\-\\w+\\-\\d+$") + return reg + }(), + }, + Defaults: endpoint{ + Hostname: "{service}.{region}.{dnsSuffix}", + Protocols: []string{"https"}, + SignatureVersions: []string{"v4"}, + }, + Regions: regions{ + "ap-northeast-1": region{ + Description: "Asia Pacific (Tokyo)", + }, + "ap-northeast-2": region{ + Description: "Asia Pacific (Seoul)", + }, + "ap-south-1": region{ + Description: "Asia Pacific (Mumbai)", + }, + "ap-southeast-1": region{ + Description: "Asia Pacific (Singapore)", + }, + "ap-southeast-2": region{ + Description: "Asia Pacific (Sydney)", + }, + "ca-central-1": region{ + Description: "Canada (Central)", + }, + "eu-central-1": region{ + Description: "EU (Frankfurt)", + }, + "eu-west-1": region{ + Description: "EU (Ireland)", + }, + "eu-west-2": region{ + Description: "EU (London)", + }, + "sa-east-1": region{ + Description: "South America (Sao Paulo)", + }, + "us-east-1": region{ + Description: "US East (N. Virginia)", + }, + "us-east-2": region{ + Description: "US East (Ohio)", + }, + "us-west-1": region{ + Description: "US West (N. California)", + }, + "us-west-2": region{ + Description: "US West (Oregon)", + }, + }, + Services: services{ + "acm": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "api.pricing": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "pricing", + }, + }, + Endpoints: endpoints{ + "ap-south-1": endpoint{}, + "us-east-1": endpoint{}, + }, + }, + "apigateway": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "application-autoscaling": service{ + Defaults: endpoint{ + Hostname: "autoscaling.{region}.amazonaws.com", + Protocols: []string{"http", "https"}, + CredentialScope: credentialScope{ + Service: "application-autoscaling", + }, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "appstream2": service{ + Defaults: endpoint{ + Protocols: []string{"https"}, + CredentialScope: credentialScope{ + Service: "appstream", + }, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "athena": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "autoscaling": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "batch": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "budgets": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "budgets.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + }, + }, + "clouddirectory": service{ + + Endpoints: endpoints{ + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cloudformation": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cloudfront": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "cloudfront.amazonaws.com", + Protocols: []string{"http", "https"}, + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + }, + }, + "cloudhsm": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cloudhsmv2": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cloudsearch": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cloudtrail": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "codebuild": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "codecommit": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "codedeploy": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "codepipeline": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "codestar": service{ + + Endpoints: endpoints{ + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cognito-identity": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cognito-idp": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cognito-sync": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "config": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "cur": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "datapipeline": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "dax": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-south-1": endpoint{}, + "eu-west-1": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "devicefarm": service{ + + Endpoints: endpoints{ + "us-west-2": endpoint{}, + }, + }, + "directconnect": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "discovery": service{ + + Endpoints: endpoints{ + "us-west-2": endpoint{}, + }, + }, + "dms": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "ds": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "dynamodb": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "local": endpoint{ + Hostname: "localhost:8000", + Protocols: []string{"http"}, + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "ec2": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "ec2metadata": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "169.254.169.254/latest", + Protocols: []string{"http"}, + }, + }, + }, + "ecr": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "ecs": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "elasticache": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "elasticbeanstalk": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "elasticfilesystem": service{ + + Endpoints: endpoints{ + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "elasticloadbalancing": service{ + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "elasticmapreduce": service{ + Defaults: endpoint{ + SSLCommonName: "{region}.{service}.{dnsSuffix}", + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{ + SSLCommonName: "{service}.{region}.{dnsSuffix}", + }, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{ + SSLCommonName: "{service}.{region}.{dnsSuffix}", + }, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "elastictranscoder": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "email": service{ + + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "entitlement.marketplace": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "aws-marketplace", + }, + }, + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "es": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "events": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "firehose": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "gamelift": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "glacier": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "glue": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "greengrass": service{ + IsRegionalized: boxedTrue, + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "health": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "iam": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "iam.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + }, + }, + "importexport": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "importexport.amazonaws.com", + SignatureVersions: []string{"v2", "v4"}, + CredentialScope: credentialScope{ + Region: "us-east-1", + Service: "IngestionService", + }, + }, + }, + }, + "inspector": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "iot": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "execute-api", + }, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "kinesis": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "kinesisanalytics": service{ + + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "kms": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "lambda": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "lightsail": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "logs": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "machinelearning": service{ + + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + }, + }, + "marketplacecommerceanalytics": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "metering.marketplace": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "aws-marketplace", + }, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "mgh": service{ + + Endpoints: endpoints{ + "us-west-2": endpoint{}, + }, + }, + "mobileanalytics": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "models.lex": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "lex", + }, + }, + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "monitoring": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "mturk-requester": service{ + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "sandbox": endpoint{ + Hostname: "mturk-requester-sandbox.us-east-1.amazonaws.com", + }, + "us-east-1": endpoint{}, + }, + }, + "opsworks": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "opsworks-cm": service{ + + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "organizations": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "organizations.us-east-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + }, + }, + "pinpoint": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "mobiletargeting", + }, + }, + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "polly": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "rds": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{ + SSLCommonName: "{service}.{dnsSuffix}", + }, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "redshift": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "rekognition": service{ + + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "route53": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "route53.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + }, + }, + "route53domains": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "runtime.lex": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "lex", + }, + }, + Endpoints: endpoints{ + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + }, + }, + "s3": service{ + PartitionEndpoint: "us-east-1", + IsRegionalized: boxedTrue, + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + SignatureVersions: []string{"s3v4"}, + + HasDualStack: boxedTrue, + DualStackHostname: "{service}.dualstack.{region}.{dnsSuffix}", + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{ + Hostname: "s3.ap-northeast-1.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{ + Hostname: "s3.ap-southeast-1.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + "ap-southeast-2": endpoint{ + Hostname: "s3.ap-southeast-2.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{ + Hostname: "s3.eu-west-1.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + "eu-west-2": endpoint{}, + "s3-external-1": endpoint{ + Hostname: "s3-external-1.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + "sa-east-1": endpoint{ + Hostname: "s3.sa-east-1.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + "us-east-1": endpoint{ + Hostname: "s3.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + "us-east-2": endpoint{}, + "us-west-1": endpoint{ + Hostname: "s3.us-west-1.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + "us-west-2": endpoint{ + Hostname: "s3.us-west-2.amazonaws.com", + SignatureVersions: []string{"s3", "s3v4"}, + }, + }, + }, + "sdb": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + SignatureVersions: []string{"v2"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-west-1": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{ + Hostname: "sdb.amazonaws.com", + }, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "servicecatalog": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "shield": service{ + IsRegionalized: boxedFalse, + Defaults: endpoint{ + SSLCommonName: "Shield.us-east-1.amazonaws.com", + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "sms": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "snowball": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "sns": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "sqs": service{ + Defaults: endpoint{ + SSLCommonName: "{region}.queue.{dnsSuffix}", + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{ + SSLCommonName: "queue.{dnsSuffix}", + }, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "ssm": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "states": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "storagegateway": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "streams.dynamodb": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + CredentialScope: credentialScope{ + Service: "dynamodb", + }, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "local": endpoint{ + Hostname: "localhost:8000", + Protocols: []string{"http"}, + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "sts": service{ + PartitionEndpoint: "aws-global", + Defaults: endpoint{ + Hostname: "sts.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{ + Hostname: "sts.ap-northeast-2.amazonaws.com", + CredentialScope: credentialScope{ + Region: "ap-northeast-2", + }, + }, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "aws-global": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-1-fips": endpoint{ + Hostname: "sts-fips.us-east-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + "us-east-2": endpoint{}, + "us-east-2-fips": endpoint{ + Hostname: "sts-fips.us-east-2.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-2", + }, + }, + "us-west-1": endpoint{}, + "us-west-1-fips": endpoint{ + Hostname: "sts-fips.us-west-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-west-1", + }, + }, + "us-west-2": endpoint{}, + "us-west-2-fips": endpoint{ + Hostname: "sts-fips.us-west-2.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-west-2", + }, + }, + }, + }, + "support": service{ + + Endpoints: endpoints{ + "us-east-1": endpoint{}, + }, + }, + "swf": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "tagging": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "waf": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "waf.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + }, + }, + }, + "waf-regional": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "workdocs": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-west-1": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "workspaces": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "us-east-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + "xray": service{ + + Endpoints: endpoints{ + "ap-northeast-1": endpoint{}, + "ap-northeast-2": endpoint{}, + "ap-south-1": endpoint{}, + "ap-southeast-1": endpoint{}, + "ap-southeast-2": endpoint{}, + "ca-central-1": endpoint{}, + "eu-central-1": endpoint{}, + "eu-west-1": endpoint{}, + "eu-west-2": endpoint{}, + "sa-east-1": endpoint{}, + "us-east-1": endpoint{}, + "us-east-2": endpoint{}, + "us-west-1": endpoint{}, + "us-west-2": endpoint{}, + }, + }, + }, +} + +// AwsCnPartition returns the Resolver for AWS China. +func AwsCnPartition() Partition { + return awscnPartition.Partition() +} + +var awscnPartition = partition{ + ID: "aws-cn", + Name: "AWS China", + DNSSuffix: "amazonaws.com.cn", + RegionRegex: regionRegex{ + Regexp: func() *regexp.Regexp { + reg, _ := regexp.Compile("^cn\\-\\w+\\-\\d+$") + return reg + }(), + }, + Defaults: endpoint{ + Hostname: "{service}.{region}.{dnsSuffix}", + Protocols: []string{"https"}, + SignatureVersions: []string{"v4"}, + }, + Regions: regions{ + "cn-north-1": region{ + Description: "China (Beijing)", + }, + }, + Services: services{ + "apigateway": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "application-autoscaling": service{ + Defaults: endpoint{ + Hostname: "autoscaling.{region}.amazonaws.com", + Protocols: []string{"http", "https"}, + CredentialScope: credentialScope{ + Service: "application-autoscaling", + }, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "autoscaling": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "cloudformation": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "cloudtrail": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "codedeploy": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "cognito-identity": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "config": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "directconnect": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "dynamodb": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "ec2": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "ec2metadata": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "169.254.169.254/latest", + Protocols: []string{"http"}, + }, + }, + }, + "ecr": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "ecs": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "elasticache": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "elasticbeanstalk": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "elasticloadbalancing": service{ + Defaults: endpoint{ + Protocols: []string{"https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "elasticmapreduce": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "es": service{ + + Endpoints: endpoints{ + "cn-northwest-1": endpoint{}, + }, + }, + "events": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "glacier": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "iam": service{ + PartitionEndpoint: "aws-cn-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-cn-global": endpoint{ + Hostname: "iam.cn-north-1.amazonaws.com.cn", + CredentialScope: credentialScope{ + Region: "cn-north-1", + }, + }, + }, + }, + "iot": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "execute-api", + }, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "kinesis": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "lambda": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "logs": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "monitoring": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "rds": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "redshift": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "s3": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + SignatureVersions: []string{"s3v4"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "snowball": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "sns": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "sqs": service{ + Defaults: endpoint{ + SSLCommonName: "{region}.queue.{dnsSuffix}", + Protocols: []string{"http", "https"}, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "ssm": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "storagegateway": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + "streams.dynamodb": service{ + Defaults: endpoint{ + Protocols: []string{"http", "https"}, + CredentialScope: credentialScope{ + Service: "dynamodb", + }, + }, + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "sts": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "swf": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + "cn-northwest-1": endpoint{}, + }, + }, + "tagging": service{ + + Endpoints: endpoints{ + "cn-north-1": endpoint{}, + }, + }, + }, +} + +// AwsUsGovPartition returns the Resolver for AWS GovCloud (US). +func AwsUsGovPartition() Partition { + return awsusgovPartition.Partition() +} + +var awsusgovPartition = partition{ + ID: "aws-us-gov", + Name: "AWS GovCloud (US)", + DNSSuffix: "amazonaws.com", + RegionRegex: regionRegex{ + Regexp: func() *regexp.Regexp { + reg, _ := regexp.Compile("^us\\-gov\\-\\w+\\-\\d+$") + return reg + }(), + }, + Defaults: endpoint{ + Hostname: "{service}.{region}.{dnsSuffix}", + Protocols: []string{"https"}, + SignatureVersions: []string{"v4"}, + }, + Regions: regions{ + "us-gov-west-1": region{ + Description: "AWS GovCloud (US)", + }, + }, + Services: services{ + "acm": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "apigateway": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "autoscaling": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{ + Protocols: []string{"http", "https"}, + }, + }, + }, + "cloudformation": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "cloudhsm": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "cloudtrail": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "codedeploy": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "config": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "directconnect": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "dms": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "dynamodb": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + "us-gov-west-1-fips": endpoint{ + Hostname: "dynamodb.us-gov-west-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-gov-west-1", + }, + }, + }, + }, + "ec2": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "ec2metadata": service{ + PartitionEndpoint: "aws-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-global": endpoint{ + Hostname: "169.254.169.254/latest", + Protocols: []string{"http"}, + }, + }, + }, + "elasticache": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "elasticbeanstalk": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "elasticloadbalancing": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{ + Protocols: []string{"http", "https"}, + }, + }, + }, + "elasticmapreduce": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{ + Protocols: []string{"http", "https"}, + }, + }, + }, + "events": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "glacier": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{ + Protocols: []string{"http", "https"}, + }, + }, + }, + "iam": service{ + PartitionEndpoint: "aws-us-gov-global", + IsRegionalized: boxedFalse, + + Endpoints: endpoints{ + "aws-us-gov-global": endpoint{ + Hostname: "iam.us-gov.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-gov-west-1", + }, + }, + }, + }, + "kinesis": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "kms": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "lambda": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "logs": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "monitoring": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "rds": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "redshift": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "rekognition": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "s3": service{ + Defaults: endpoint{ + SignatureVersions: []string{"s3", "s3v4"}, + }, + Endpoints: endpoints{ + "fips-us-gov-west-1": endpoint{ + Hostname: "s3-fips-us-gov-west-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-gov-west-1", + }, + }, + "us-gov-west-1": endpoint{ + Hostname: "s3.us-gov-west-1.amazonaws.com", + Protocols: []string{"http", "https"}, + }, + }, + }, + "sms": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "snowball": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "sns": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{ + Protocols: []string{"http", "https"}, + }, + }, + }, + "sqs": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{ + SSLCommonName: "{region}.queue.{dnsSuffix}", + Protocols: []string{"http", "https"}, + }, + }, + }, + "ssm": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "streams.dynamodb": service{ + Defaults: endpoint{ + CredentialScope: credentialScope{ + Service: "dynamodb", + }, + }, + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + "us-gov-west-1-fips": endpoint{ + Hostname: "dynamodb.us-gov-west-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "us-gov-west-1", + }, + }, + }, + }, + "sts": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + "swf": service{ + + Endpoints: endpoints{ + "us-gov-west-1": endpoint{}, + }, + }, + }, +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go new file mode 100644 index 0000000..84316b9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go @@ -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 diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go new file mode 100644 index 0000000..9c3eedb --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go @@ -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() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints_test.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints_test.go new file mode 100644 index 0000000..9c0e09d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints_test.go @@ -0,0 +1,335 @@ +package endpoints + +import "testing" + +func TestEnumDefaultPartitions(t *testing.T) { + resolver := DefaultResolver() + enum, ok := resolver.(EnumPartitions) + + if ok != true { + t.Fatalf("resolver must satisfy EnumPartition interface") + } + + ps := enum.Partitions() + + if a, e := len(ps), len(defaultPartitions); a != e { + t.Errorf("expected %d partitions, got %d", e, a) + } +} + +func TestEnumDefaultRegions(t *testing.T) { + expectPart := defaultPartitions[0] + partEnum := defaultPartitions[0].Partition() + + regEnum := partEnum.Regions() + + if a, e := len(regEnum), len(expectPart.Regions); a != e { + t.Errorf("expected %d regions, got %d", e, a) + } +} + +func TestEnumPartitionServices(t *testing.T) { + expectPart := testPartitions[0] + partEnum := testPartitions[0].Partition() + + if a, e := partEnum.ID(), "part-id"; a != e { + t.Errorf("expect %q partition ID, got %q", e, a) + } + + svcEnum := partEnum.Services() + + if a, e := len(svcEnum), len(expectPart.Services); a != e { + t.Errorf("expected %d regions, got %d", e, a) + } +} + +func TestEnumRegionServices(t *testing.T) { + p := testPartitions[0].Partition() + + rs := p.Regions() + + if a, e := len(rs), 2; a != e { + t.Errorf("expect %d regions got %d", e, a) + } + + if _, ok := rs["us-east-1"]; !ok { + t.Errorf("expect us-east-1 region to be found, was not") + } + if _, ok := rs["us-west-2"]; !ok { + t.Errorf("expect us-west-2 region to be found, was not") + } + + r := rs["us-east-1"] + + if a, e := r.ID(), "us-east-1"; a != e { + t.Errorf("expect %q region ID, got %q", e, a) + } + + ss := r.Services() + if a, e := len(ss), 1; a != e { + t.Errorf("expect %d services for us-east-1, got %d", e, a) + } + + if _, ok := ss["service1"]; !ok { + t.Errorf("expect service1 service to be found, was not") + } + + resolved, err := r.ResolveEndpoint("service1") + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if a, e := resolved.URL, "https://service1.us-east-1.amazonaws.com"; a != e { + t.Errorf("expect %q resolved URL, got %q", e, a) + } +} + +func TestEnumServiceRegions(t *testing.T) { + p := testPartitions[0].Partition() + + rs := p.Services()["service1"].Regions() + if e, a := 2, len(rs); e != a { + t.Errorf("expect %d regions, got %d", e, a) + } + + if _, ok := rs["us-east-1"]; !ok { + t.Errorf("expect region to be found") + } + if _, ok := rs["us-west-2"]; !ok { + t.Errorf("expect region to be found") + } +} + +func TestEnumServicesEndpoints(t *testing.T) { + p := testPartitions[0].Partition() + + ss := p.Services() + + if a, e := len(ss), 5; a != e { + t.Errorf("expect %d regions got %d", e, a) + } + + if _, ok := ss["service1"]; !ok { + t.Errorf("expect service1 region to be found, was not") + } + if _, ok := ss["service2"]; !ok { + t.Errorf("expect service2 region to be found, was not") + } + + s := ss["service1"] + if a, e := s.ID(), "service1"; a != e { + t.Errorf("expect %q service ID, got %q", e, a) + } + + resolved, err := s.ResolveEndpoint("us-west-2") + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if a, e := resolved.URL, "https://service1.us-west-2.amazonaws.com"; a != e { + t.Errorf("expect %q resolved URL, got %q", e, a) + } +} + +func TestEnumEndpoints(t *testing.T) { + p := testPartitions[0].Partition() + s := p.Services()["service1"] + + es := s.Endpoints() + if a, e := len(es), 2; a != e { + t.Errorf("expect %d endpoints for service2, got %d", e, a) + } + if _, ok := es["us-east-1"]; !ok { + t.Errorf("expect us-east-1 to be found, was not") + } + + e := es["us-east-1"] + if a, e := e.ID(), "us-east-1"; a != e { + t.Errorf("expect %q endpoint ID, got %q", e, a) + } + if a, e := e.ServiceID(), "service1"; a != e { + t.Errorf("expect %q service ID, got %q", e, a) + } + + resolved, err := e.ResolveEndpoint() + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if a, e := resolved.URL, "https://service1.us-east-1.amazonaws.com"; a != e { + t.Errorf("expect %q resolved URL, got %q", e, a) + } +} + +func TestResolveEndpointForPartition(t *testing.T) { + enum := testPartitions.Partitions()[0] + + expected, err := testPartitions.EndpointFor("service1", "us-east-1") + + actual, err := enum.EndpointFor("service1", "us-east-1") + if err != nil { + t.Fatalf("unexpected error, %v", err) + } + + if expected != actual { + t.Errorf("expect resolved endpoint to be %v, but got %v", expected, actual) + } +} + +func TestAddScheme(t *testing.T) { + cases := []struct { + In string + Expect string + DisableSSL bool + }{ + { + In: "https://example.com", + Expect: "https://example.com", + }, + { + In: "example.com", + Expect: "https://example.com", + }, + { + In: "http://example.com", + Expect: "http://example.com", + }, + { + In: "example.com", + Expect: "http://example.com", + DisableSSL: true, + }, + { + In: "https://example.com", + Expect: "https://example.com", + DisableSSL: true, + }, + } + + for i, c := range cases { + actual := AddScheme(c.In, c.DisableSSL) + if actual != c.Expect { + t.Errorf("%d, expect URL to be %q, got %q", i, c.Expect, actual) + } + } +} + +func TestResolverFunc(t *testing.T) { + var resolver Resolver + + resolver = ResolverFunc(func(s, r string, opts ...func(*Options)) (ResolvedEndpoint, error) { + return ResolvedEndpoint{ + URL: "https://service.region.dnssuffix.com", + SigningRegion: "region", + SigningName: "service", + }, nil + }) + + resolved, err := resolver.EndpointFor("service", "region", func(o *Options) { + o.DisableSSL = true + }) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if a, e := resolved.URL, "https://service.region.dnssuffix.com"; a != e { + t.Errorf("expect %q endpoint URL, got %q", e, a) + } + + if a, e := resolved.SigningRegion, "region"; a != e { + t.Errorf("expect %q region, got %q", e, a) + } + if a, e := resolved.SigningName, "service"; a != e { + t.Errorf("expect %q signing name, got %q", e, a) + } +} + +func TestOptionsSet(t *testing.T) { + var actual Options + actual.Set(DisableSSLOption, UseDualStackOption, StrictMatchingOption) + + expect := Options{ + DisableSSL: true, + UseDualStack: true, + StrictMatching: true, + } + + if actual != expect { + t.Errorf("expect %v options got %v", expect, actual) + } +} + +func TestRegionsForService(t *testing.T) { + ps := DefaultPartitions() + + var expect map[string]Region + var serviceID string + for _, s := range ps[0].Services() { + expect = s.Regions() + serviceID = s.ID() + if len(expect) > 0 { + break + } + } + + actual, ok := RegionsForService(ps, ps[0].ID(), serviceID) + if !ok { + t.Fatalf("expect regions to be found, was not") + } + + if len(actual) == 0 { + t.Fatalf("expect service %s to have regions", serviceID) + } + if e, a := len(expect), len(actual); e != a { + t.Fatalf("expect %d regions, got %d", e, a) + } + + for id, r := range actual { + if e, a := id, r.ID(); e != a { + t.Errorf("expect %s region id, got %s", e, a) + } + if _, ok := expect[id]; !ok { + t.Errorf("expect %s region to be found", id) + } + } +} + +func TestRegionsForService_NotFound(t *testing.T) { + ps := testPartitions.Partitions() + + actual, ok := RegionsForService(ps, ps[0].ID(), "service-not-exists") + if ok { + t.Fatalf("expect no regions to be found, but were") + } + if len(actual) != 0 { + t.Errorf("expect no regions, got %v", actual) + } +} + +func TestPartitionForRegion(t *testing.T) { + ps := DefaultPartitions() + expect := ps[len(ps)%2] + + var regionID string + for id := range expect.Regions() { + regionID = id + break + } + + actual, ok := PartitionForRegion(ps, regionID) + if !ok { + t.Fatalf("expect partition to be found") + } + if e, a := expect.ID(), actual.ID(); e != a { + t.Errorf("expect %s partition, got %s", e, a) + } +} + +func TestPartitionForRegion_NotFound(t *testing.T) { + ps := DefaultPartitions() + + actual, ok := PartitionForRegion(ps, "regionNotExists") + if ok { + t.Errorf("expect no partition to be found, got %v", actual) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/example_test.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/example_test.go new file mode 100644 index 0000000..007fed2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/example_test.go @@ -0,0 +1,66 @@ +package endpoints_test + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" + "github.com/aws/aws-sdk-go/service/sqs" +) + +func ExampleEnumPartitions() { + 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) + } + } +} + +func ExampleResolverFunc() { + 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), + })) + + // Create the S3 service client with the shared session. This will + // automatically use the S3 custom endpoint configured in the custom + // endpoint resolver wrapping the default endpoint resolver. + s3Svc := s3.New(sess) + // Operation calls will be made to the custom endpoint. + s3Svc.GetObject(&s3.GetObjectInput{ + Bucket: aws.String("myBucket"), + Key: aws.String("myObjectKey"), + }) + + // Create the SQS service client with the shared session. This will + // fallback to the default endpoint resolver because the customization + // passes any non S3 service endpoint resolve to the default resolver. + sqsSvc := sqs.New(sess) + // Operation calls will be made to the default endpoint for SQS for the + // region configured. + sqsSvc.ReceiveMessage(&sqs.ReceiveMessageInput{ + QueueUrl: aws.String("my-queue-url"), + }) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go new file mode 100644 index 0000000..13d968a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go @@ -0,0 +1,303 @@ +package endpoints + +import ( + "fmt" + "regexp" + "strconv" + "strings" +) + +type partitions []partition + +func (ps partitions) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) { + var opt Options + opt.Set(opts...) + + for i := 0; i < len(ps); i++ { + if !ps[i].canResolveEndpoint(service, region, opt.StrictMatching) { + continue + } + + return ps[i].EndpointFor(service, region, opts...) + } + + // If loose matching fallback to first partition format to use + // when resolving the endpoint. + if !opt.StrictMatching && len(ps) > 0 { + return ps[0].EndpointFor(service, region, opts...) + } + + return ResolvedEndpoint{}, NewUnknownEndpointError("all partitions", service, region, []string{}) +} + +// Partitions satisfies the EnumPartitions interface and returns a list +// of Partitions representing each partition represented in the SDK's +// endpoints model. +func (ps partitions) Partitions() []Partition { + parts := make([]Partition, 0, len(ps)) + for i := 0; i < len(ps); i++ { + parts = append(parts, ps[i].Partition()) + } + + return parts +} + +type partition struct { + ID string `json:"partition"` + Name string `json:"partitionName"` + DNSSuffix string `json:"dnsSuffix"` + RegionRegex regionRegex `json:"regionRegex"` + Defaults endpoint `json:"defaults"` + Regions regions `json:"regions"` + Services services `json:"services"` +} + +func (p partition) Partition() Partition { + return Partition{ + id: p.ID, + p: &p, + } +} + +func (p partition) canResolveEndpoint(service, region string, strictMatch bool) bool { + s, hasService := p.Services[service] + _, hasEndpoint := s.Endpoints[region] + + if hasEndpoint && hasService { + return true + } + + if strictMatch { + return false + } + + return p.RegionRegex.MatchString(region) +} + +func (p partition) EndpointFor(service, region string, opts ...func(*Options)) (resolved ResolvedEndpoint, err error) { + var opt Options + opt.Set(opts...) + + s, hasService := p.Services[service] + if !(hasService || opt.ResolveUnknownService) { + // Only return error if the resolver will not fallback to creating + // endpoint based on service endpoint ID passed in. + return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services)) + } + + e, hasEndpoint := s.endpointForRegion(region) + if !hasEndpoint && opt.StrictMatching { + return resolved, NewUnknownEndpointError(p.ID, service, region, endpointList(s.Endpoints)) + } + + defs := []endpoint{p.Defaults, s.Defaults} + return e.resolve(service, region, p.DNSSuffix, defs, opt), nil +} + +func serviceList(ss services) []string { + list := make([]string, 0, len(ss)) + for k := range ss { + list = append(list, k) + } + return list +} +func endpointList(es endpoints) []string { + list := make([]string, 0, len(es)) + for k := range es { + list = append(list, k) + } + return list +} + +type regionRegex struct { + *regexp.Regexp +} + +func (rr *regionRegex) UnmarshalJSON(b []byte) (err error) { + // Strip leading and trailing quotes + regex, err := strconv.Unquote(string(b)) + if err != nil { + return fmt.Errorf("unable to strip quotes from regex, %v", err) + } + + rr.Regexp, err = regexp.Compile(regex) + if err != nil { + return fmt.Errorf("unable to unmarshal region regex, %v", err) + } + return nil +} + +type regions map[string]region + +type region struct { + Description string `json:"description"` +} + +type services map[string]service + +type service struct { + PartitionEndpoint string `json:"partitionEndpoint"` + IsRegionalized boxedBool `json:"isRegionalized,omitempty"` + Defaults endpoint `json:"defaults"` + Endpoints endpoints `json:"endpoints"` +} + +func (s *service) endpointForRegion(region string) (endpoint, bool) { + if s.IsRegionalized == boxedFalse { + return s.Endpoints[s.PartitionEndpoint], region == s.PartitionEndpoint + } + + if e, ok := s.Endpoints[region]; ok { + return e, true + } + + // Unable to find any matching endpoint, return + // blank that will be used for generic endpoint creation. + return endpoint{}, false +} + +type endpoints map[string]endpoint + +type endpoint struct { + Hostname string `json:"hostname"` + Protocols []string `json:"protocols"` + CredentialScope credentialScope `json:"credentialScope"` + + // Custom fields not modeled + HasDualStack boxedBool `json:"-"` + DualStackHostname string `json:"-"` + + // Signature Version not used + SignatureVersions []string `json:"signatureVersions"` + + // SSLCommonName not used. + SSLCommonName string `json:"sslCommonName"` +} + +const ( + defaultProtocol = "https" + defaultSigner = "v4" +) + +var ( + protocolPriority = []string{"https", "http"} + signerPriority = []string{"v4", "v2"} +) + +func getByPriority(s []string, p []string, def string) string { + if len(s) == 0 { + return def + } + + for i := 0; i < len(p); i++ { + for j := 0; j < len(s); j++ { + if s[j] == p[i] { + return s[j] + } + } + } + + return s[0] +} + +func (e endpoint) resolve(service, region, dnsSuffix string, defs []endpoint, opts Options) ResolvedEndpoint { + var merged endpoint + for _, def := range defs { + merged.mergeIn(def) + } + merged.mergeIn(e) + e = merged + + hostname := e.Hostname + + // Offset the hostname for dualstack if enabled + if opts.UseDualStack && e.HasDualStack == boxedTrue { + hostname = e.DualStackHostname + } + + u := strings.Replace(hostname, "{service}", service, 1) + u = strings.Replace(u, "{region}", region, 1) + u = strings.Replace(u, "{dnsSuffix}", dnsSuffix, 1) + + scheme := getEndpointScheme(e.Protocols, opts.DisableSSL) + u = fmt.Sprintf("%s://%s", scheme, u) + + signingRegion := e.CredentialScope.Region + if len(signingRegion) == 0 { + signingRegion = region + } + signingName := e.CredentialScope.Service + if len(signingName) == 0 { + signingName = service + } + + return ResolvedEndpoint{ + URL: u, + SigningRegion: signingRegion, + SigningName: signingName, + SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner), + } +} + +func getEndpointScheme(protocols []string, disableSSL bool) string { + if disableSSL { + return "http" + } + + return getByPriority(protocols, protocolPriority, defaultProtocol) +} + +func (e *endpoint) mergeIn(other endpoint) { + if len(other.Hostname) > 0 { + e.Hostname = other.Hostname + } + if len(other.Protocols) > 0 { + e.Protocols = other.Protocols + } + if len(other.SignatureVersions) > 0 { + e.SignatureVersions = other.SignatureVersions + } + if len(other.CredentialScope.Region) > 0 { + e.CredentialScope.Region = other.CredentialScope.Region + } + if len(other.CredentialScope.Service) > 0 { + e.CredentialScope.Service = other.CredentialScope.Service + } + if len(other.SSLCommonName) > 0 { + e.SSLCommonName = other.SSLCommonName + } + if other.HasDualStack != boxedBoolUnset { + e.HasDualStack = other.HasDualStack + } + if len(other.DualStackHostname) > 0 { + e.DualStackHostname = other.DualStackHostname + } +} + +type credentialScope struct { + Region string `json:"region"` + Service string `json:"service"` +} + +type boxedBool int + +func (b *boxedBool) UnmarshalJSON(buf []byte) error { + v, err := strconv.ParseBool(string(buf)) + if err != nil { + return err + } + + if v { + *b = boxedTrue + } else { + *b = boxedFalse + } + + return nil +} + +const ( + boxedBoolUnset boxedBool = iota + boxedFalse + boxedTrue +) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go new file mode 100644 index 0000000..05e92df --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go @@ -0,0 +1,337 @@ +// +build codegen + +package endpoints + +import ( + "fmt" + "io" + "reflect" + "strings" + "text/template" + "unicode" +) + +// A CodeGenOptions are the options for code generating the endpoints into +// Go code from the endpoints model definition. +type CodeGenOptions struct { + // Options for how the model will be decoded. + DecodeModelOptions DecodeModelOptions +} + +// Set combines all of the option functions together +func (d *CodeGenOptions) Set(optFns ...func(*CodeGenOptions)) { + for _, fn := range optFns { + fn(d) + } +} + +// CodeGenModel given a endpoints model file will decode it and attempt to +// generate Go code from the model definition. Error will be returned if +// the code is unable to be generated, or decoded. +func CodeGenModel(modelFile io.Reader, outFile io.Writer, optFns ...func(*CodeGenOptions)) error { + var opts CodeGenOptions + opts.Set(optFns...) + + resolver, err := DecodeModel(modelFile, func(d *DecodeModelOptions) { + *d = opts.DecodeModelOptions + }) + if err != nil { + return err + } + + tmpl := template.Must(template.New("tmpl").Funcs(funcMap).Parse(v3Tmpl)) + if err := tmpl.ExecuteTemplate(outFile, "defaults", resolver); err != nil { + return fmt.Errorf("failed to execute template, %v", err) + } + + return nil +} + +func toSymbol(v string) string { + out := []rune{} + for _, c := range strings.Title(v) { + if !(unicode.IsNumber(c) || unicode.IsLetter(c)) { + continue + } + + out = append(out, c) + } + + return string(out) +} + +func quoteString(v string) string { + return fmt.Sprintf("%q", v) +} + +func regionConstName(p, r string) string { + return toSymbol(p) + toSymbol(r) +} + +func partitionGetter(id string) string { + return fmt.Sprintf("%sPartition", toSymbol(id)) +} + +func partitionVarName(id string) string { + return fmt.Sprintf("%sPartition", strings.ToLower(toSymbol(id))) +} + +func listPartitionNames(ps partitions) string { + names := []string{} + switch len(ps) { + case 1: + return ps[0].Name + case 2: + return fmt.Sprintf("%s and %s", ps[0].Name, ps[1].Name) + default: + for i, p := range ps { + if i == len(ps)-1 { + names = append(names, "and "+p.Name) + } else { + names = append(names, p.Name) + } + } + return strings.Join(names, ", ") + } +} + +func boxedBoolIfSet(msg string, v boxedBool) string { + switch v { + case boxedTrue: + return fmt.Sprintf(msg, "boxedTrue") + case boxedFalse: + return fmt.Sprintf(msg, "boxedFalse") + default: + return "" + } +} + +func stringIfSet(msg, v string) string { + if len(v) == 0 { + return "" + } + + return fmt.Sprintf(msg, v) +} + +func stringSliceIfSet(msg string, vs []string) string { + if len(vs) == 0 { + return "" + } + + names := []string{} + for _, v := range vs { + names = append(names, `"`+v+`"`) + } + + return fmt.Sprintf(msg, strings.Join(names, ",")) +} + +func endpointIsSet(v endpoint) bool { + return !reflect.DeepEqual(v, endpoint{}) +} + +func serviceSet(ps partitions) map[string]struct{} { + set := map[string]struct{}{} + for _, p := range ps { + for id := range p.Services { + set[id] = struct{}{} + } + } + + return set +} + +var funcMap = template.FuncMap{ + "ToSymbol": toSymbol, + "QuoteString": quoteString, + "RegionConst": regionConstName, + "PartitionGetter": partitionGetter, + "PartitionVarName": partitionVarName, + "ListPartitionNames": listPartitionNames, + "BoxedBoolIfSet": boxedBoolIfSet, + "StringIfSet": stringIfSet, + "StringSliceIfSet": stringSliceIfSet, + "EndpointIsSet": endpointIsSet, + "ServicesSet": serviceSet, +} + +const v3Tmpl = ` +{{ define "defaults" -}} +// Code generated by aws/endpoints/v3model_codegen.go. DO NOT EDIT. + +package endpoints + +import ( + "regexp" +) + + {{ template "partition consts" . }} + + {{ range $_, $partition := . }} + {{ template "partition region consts" $partition }} + {{ end }} + + {{ template "service consts" . }} + + {{ template "endpoint resolvers" . }} +{{- end }} + +{{ define "partition consts" }} + // Partition identifiers + const ( + {{ range $_, $p := . -}} + {{ ToSymbol $p.ID }}PartitionID = {{ QuoteString $p.ID }} // {{ $p.Name }} partition. + {{ end -}} + ) +{{- end }} + +{{ define "partition region consts" }} + // {{ .Name }} partition's regions. + const ( + {{ range $id, $region := .Regions -}} + {{ ToSymbol $id }}RegionID = {{ QuoteString $id }} // {{ $region.Description }}. + {{ end -}} + ) +{{- end }} + +{{ define "service consts" }} + // Service identifiers + const ( + {{ $serviceSet := ServicesSet . -}} + {{ range $id, $_ := $serviceSet -}} + {{ ToSymbol $id }}ServiceID = {{ QuoteString $id }} // {{ ToSymbol $id }}. + {{ end -}} + ) +{{- end }} + +{{ define "endpoint resolvers" }} + // DefaultResolver returns an Endpoint resolver that will be able + // to resolve endpoints for: {{ ListPartitionNames . }}. + // + // Use DefaultPartitions() to get the list of the default partitions. + func DefaultResolver() Resolver { + return defaultPartitions + } + + // DefaultPartitions returns a list of the partitions the SDK is bundled + // with. The available partitions are: {{ ListPartitionNames . }}. + // + // partitions := endpoints.DefaultPartitions + // for _, p := range partitions { + // // ... inspect partitions + // } + func DefaultPartitions() []Partition { + return defaultPartitions.Partitions() + } + + var defaultPartitions = partitions{ + {{ range $_, $partition := . -}} + {{ PartitionVarName $partition.ID }}, + {{ end }} + } + + {{ range $_, $partition := . -}} + {{ $name := PartitionGetter $partition.ID -}} + // {{ $name }} returns the Resolver for {{ $partition.Name }}. + func {{ $name }}() Partition { + return {{ PartitionVarName $partition.ID }}.Partition() + } + var {{ PartitionVarName $partition.ID }} = {{ template "gocode Partition" $partition }} + {{ end }} +{{ end }} + +{{ define "default partitions" }} + func DefaultPartitions() []Partition { + return []partition{ + {{ range $_, $partition := . -}} + // {{ ToSymbol $partition.ID}}Partition(), + {{ end }} + } + } +{{ end }} + +{{ define "gocode Partition" -}} +partition{ + {{ StringIfSet "ID: %q,\n" .ID -}} + {{ StringIfSet "Name: %q,\n" .Name -}} + {{ StringIfSet "DNSSuffix: %q,\n" .DNSSuffix -}} + RegionRegex: {{ template "gocode RegionRegex" .RegionRegex }}, + {{ if EndpointIsSet .Defaults -}} + Defaults: {{ template "gocode Endpoint" .Defaults }}, + {{- end }} + Regions: {{ template "gocode Regions" .Regions }}, + Services: {{ template "gocode Services" .Services }}, +} +{{- end }} + +{{ define "gocode RegionRegex" -}} +regionRegex{ + Regexp: func() *regexp.Regexp{ + reg, _ := regexp.Compile({{ QuoteString .Regexp.String }}) + return reg + }(), +} +{{- end }} + +{{ define "gocode Regions" -}} +regions{ + {{ range $id, $region := . -}} + "{{ $id }}": {{ template "gocode Region" $region }}, + {{ end -}} +} +{{- end }} + +{{ define "gocode Region" -}} +region{ + {{ StringIfSet "Description: %q,\n" .Description -}} +} +{{- end }} + +{{ define "gocode Services" -}} +services{ + {{ range $id, $service := . -}} + "{{ $id }}": {{ template "gocode Service" $service }}, + {{ end }} +} +{{- end }} + +{{ define "gocode Service" -}} +service{ + {{ StringIfSet "PartitionEndpoint: %q,\n" .PartitionEndpoint -}} + {{ BoxedBoolIfSet "IsRegionalized: %s,\n" .IsRegionalized -}} + {{ if EndpointIsSet .Defaults -}} + Defaults: {{ template "gocode Endpoint" .Defaults -}}, + {{- end }} + {{ if .Endpoints -}} + Endpoints: {{ template "gocode Endpoints" .Endpoints }}, + {{- end }} +} +{{- end }} + +{{ define "gocode Endpoints" -}} +endpoints{ + {{ range $id, $endpoint := . -}} + "{{ $id }}": {{ template "gocode Endpoint" $endpoint }}, + {{ end }} +} +{{- end }} + +{{ define "gocode Endpoint" -}} +endpoint{ + {{ StringIfSet "Hostname: %q,\n" .Hostname -}} + {{ StringIfSet "SSLCommonName: %q,\n" .SSLCommonName -}} + {{ StringSliceIfSet "Protocols: []string{%s},\n" .Protocols -}} + {{ StringSliceIfSet "SignatureVersions: []string{%s},\n" .SignatureVersions -}} + {{ if or .CredentialScope.Region .CredentialScope.Service -}} + CredentialScope: credentialScope{ + {{ StringIfSet "Region: %q,\n" .CredentialScope.Region -}} + {{ StringIfSet "Service: %q,\n" .CredentialScope.Service -}} + }, + {{- end }} + {{ BoxedBoolIfSet "HasDualStack: %s,\n" .HasDualStack -}} + {{ StringIfSet "DualStackHostname: %q,\n" .DualStackHostname -}} + +} +{{- end }} +` diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_test.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_test.go new file mode 100644 index 0000000..1385cb4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_test.go @@ -0,0 +1,354 @@ +package endpoints + +import ( + "encoding/json" + "regexp" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUnmarshalRegionRegex(t *testing.T) { + var input = []byte(` +{ + "regionRegex": "^(us|eu|ap|sa|ca)\\-\\w+\\-\\d+$" +}`) + + p := partition{} + err := json.Unmarshal(input, &p) + assert.NoError(t, err) + + expectRegexp, err := regexp.Compile(`^(us|eu|ap|sa|ca)\-\w+\-\d+$`) + assert.NoError(t, err) + + assert.Equal(t, expectRegexp.String(), p.RegionRegex.Regexp.String()) +} + +func TestUnmarshalRegion(t *testing.T) { + var input = []byte(` +{ + "aws-global": { + "description": "AWS partition-global endpoint" + }, + "us-east-1": { + "description": "US East (N. Virginia)" + } +}`) + + rs := regions{} + err := json.Unmarshal(input, &rs) + assert.NoError(t, err) + + assert.Len(t, rs, 2) + r, ok := rs["aws-global"] + assert.True(t, ok) + assert.Equal(t, "AWS partition-global endpoint", r.Description) + + r, ok = rs["us-east-1"] + assert.True(t, ok) + assert.Equal(t, "US East (N. Virginia)", r.Description) +} + +func TestUnmarshalServices(t *testing.T) { + var input = []byte(` +{ + "acm": { + "endpoints": { + "us-east-1": {} + } + }, + "apigateway": { + "isRegionalized": true, + "endpoints": { + "us-east-1": {}, + "us-west-2": {} + } + }, + "notRegionalized": { + "isRegionalized": false, + "endpoints": { + "us-east-1": {}, + "us-west-2": {} + } + } +}`) + + ss := services{} + err := json.Unmarshal(input, &ss) + assert.NoError(t, err) + + assert.Len(t, ss, 3) + s, ok := ss["acm"] + assert.True(t, ok) + assert.Len(t, s.Endpoints, 1) + assert.Equal(t, boxedBoolUnset, s.IsRegionalized) + + s, ok = ss["apigateway"] + assert.True(t, ok) + assert.Len(t, s.Endpoints, 2) + assert.Equal(t, boxedTrue, s.IsRegionalized) + + s, ok = ss["notRegionalized"] + assert.True(t, ok) + assert.Len(t, s.Endpoints, 2) + assert.Equal(t, boxedFalse, s.IsRegionalized) +} + +func TestUnmarshalEndpoints(t *testing.T) { + var inputs = []byte(` +{ + "aws-global": { + "hostname": "cloudfront.amazonaws.com", + "protocols": [ + "http", + "https" + ], + "signatureVersions": [ "v4" ], + "credentialScope": { + "region": "us-east-1", + "service": "serviceName" + }, + "sslCommonName": "commonName" + }, + "us-east-1": {} +}`) + + es := endpoints{} + err := json.Unmarshal(inputs, &es) + assert.NoError(t, err) + + assert.Len(t, es, 2) + s, ok := es["aws-global"] + assert.True(t, ok) + assert.Equal(t, "cloudfront.amazonaws.com", s.Hostname) + assert.Equal(t, []string{"http", "https"}, s.Protocols) + assert.Equal(t, []string{"v4"}, s.SignatureVersions) + assert.Equal(t, credentialScope{"us-east-1", "serviceName"}, s.CredentialScope) + assert.Equal(t, "commonName", s.SSLCommonName) +} + +func TestEndpointResolve(t *testing.T) { + defs := []endpoint{ + { + Hostname: "{service}.{region}.{dnsSuffix}", + SignatureVersions: []string{"v2"}, + SSLCommonName: "sslCommonName", + }, + { + Hostname: "other-hostname", + Protocols: []string{"http"}, + CredentialScope: credentialScope{ + Region: "signing_region", + Service: "signing_service", + }, + }, + } + + e := endpoint{ + Hostname: "{service}.{region}.{dnsSuffix}", + Protocols: []string{"http", "https"}, + SignatureVersions: []string{"v4"}, + SSLCommonName: "new sslCommonName", + } + + resolved := e.resolve("service", "region", "dnsSuffix", + defs, Options{}, + ) + + assert.Equal(t, "https://service.region.dnsSuffix", resolved.URL) + assert.Equal(t, "signing_service", resolved.SigningName) + assert.Equal(t, "signing_region", resolved.SigningRegion) + assert.Equal(t, "v4", resolved.SigningMethod) +} + +func TestEndpointMergeIn(t *testing.T) { + expected := endpoint{ + Hostname: "other hostname", + Protocols: []string{"http"}, + SignatureVersions: []string{"v4"}, + SSLCommonName: "ssl common name", + CredentialScope: credentialScope{ + Region: "region", + Service: "service", + }, + } + + actual := endpoint{} + actual.mergeIn(endpoint{ + Hostname: "other hostname", + Protocols: []string{"http"}, + SignatureVersions: []string{"v4"}, + SSLCommonName: "ssl common name", + CredentialScope: credentialScope{ + Region: "region", + Service: "service", + }, + }) + + assert.Equal(t, expected, actual) +} + +var testPartitions = partitions{ + partition{ + ID: "part-id", + Name: "partitionName", + DNSSuffix: "amazonaws.com", + RegionRegex: regionRegex{ + Regexp: func() *regexp.Regexp { + reg, _ := regexp.Compile("^(us|eu|ap|sa|ca)\\-\\w+\\-\\d+$") + return reg + }(), + }, + Defaults: endpoint{ + Hostname: "{service}.{region}.{dnsSuffix}", + Protocols: []string{"https"}, + SignatureVersions: []string{"v4"}, + }, + Regions: regions{ + "us-east-1": region{ + Description: "region description", + }, + "us-west-2": region{}, + }, + Services: services{ + "s3": service{}, + "service1": service{ + Endpoints: endpoints{ + "us-east-1": {}, + "us-west-2": { + HasDualStack: boxedTrue, + DualStackHostname: "{service}.dualstack.{region}.{dnsSuffix}", + }, + }, + }, + "service2": service{}, + "httpService": service{ + Defaults: endpoint{ + Protocols: []string{"http"}, + }, + }, + "globalService": service{ + IsRegionalized: boxedFalse, + PartitionEndpoint: "aws-global", + Endpoints: endpoints{ + "aws-global": endpoint{ + CredentialScope: credentialScope{ + Region: "us-east-1", + }, + Hostname: "globalService.amazonaws.com", + }, + }, + }, + }, + }, +} + +func TestResolveEndpoint(t *testing.T) { + resolved, err := testPartitions.EndpointFor("service2", "us-west-2") + + assert.NoError(t, err) + assert.Equal(t, "https://service2.us-west-2.amazonaws.com", resolved.URL) + assert.Equal(t, "us-west-2", resolved.SigningRegion) + assert.Equal(t, "service2", resolved.SigningName) +} + +func TestResolveEndpoint_DisableSSL(t *testing.T) { + resolved, err := testPartitions.EndpointFor("service2", "us-west-2", DisableSSLOption) + + assert.NoError(t, err) + assert.Equal(t, "http://service2.us-west-2.amazonaws.com", resolved.URL) + assert.Equal(t, "us-west-2", resolved.SigningRegion) + assert.Equal(t, "service2", resolved.SigningName) +} + +func TestResolveEndpoint_UseDualStack(t *testing.T) { + resolved, err := testPartitions.EndpointFor("service1", "us-west-2", UseDualStackOption) + + assert.NoError(t, err) + assert.Equal(t, "https://service1.dualstack.us-west-2.amazonaws.com", resolved.URL) + assert.Equal(t, "us-west-2", resolved.SigningRegion) + assert.Equal(t, "service1", resolved.SigningName) +} + +func TestResolveEndpoint_HTTPProtocol(t *testing.T) { + resolved, err := testPartitions.EndpointFor("httpService", "us-west-2") + + assert.NoError(t, err) + assert.Equal(t, "http://httpService.us-west-2.amazonaws.com", resolved.URL) + assert.Equal(t, "us-west-2", resolved.SigningRegion) + assert.Equal(t, "httpService", resolved.SigningName) +} + +func TestResolveEndpoint_UnknownService(t *testing.T) { + _, err := testPartitions.EndpointFor("unknownservice", "us-west-2") + + assert.Error(t, err) + + _, ok := err.(UnknownServiceError) + assert.True(t, ok, "expect error to be UnknownServiceError") +} + +func TestResolveEndpoint_ResolveUnknownService(t *testing.T) { + resolved, err := testPartitions.EndpointFor("unknown-service", "us-region-1", + ResolveUnknownServiceOption) + + assert.NoError(t, err) + + assert.Equal(t, "https://unknown-service.us-region-1.amazonaws.com", resolved.URL) + assert.Equal(t, "us-region-1", resolved.SigningRegion) + assert.Equal(t, "unknown-service", resolved.SigningName) +} + +func TestResolveEndpoint_UnknownMatchedRegion(t *testing.T) { + resolved, err := testPartitions.EndpointFor("service2", "us-region-1") + + assert.NoError(t, err) + assert.Equal(t, "https://service2.us-region-1.amazonaws.com", resolved.URL) + assert.Equal(t, "us-region-1", resolved.SigningRegion) + assert.Equal(t, "service2", resolved.SigningName) +} + +func TestResolveEndpoint_UnknownRegion(t *testing.T) { + resolved, err := testPartitions.EndpointFor("service2", "unknownregion") + + assert.NoError(t, err) + assert.Equal(t, "https://service2.unknownregion.amazonaws.com", resolved.URL) + assert.Equal(t, "unknownregion", resolved.SigningRegion) + assert.Equal(t, "service2", resolved.SigningName) +} + +func TestResolveEndpoint_StrictPartitionUnknownEndpoint(t *testing.T) { + _, err := testPartitions[0].EndpointFor("service2", "unknownregion", StrictMatchingOption) + + assert.Error(t, err) + + _, ok := err.(UnknownEndpointError) + assert.True(t, ok, "expect error to be UnknownEndpointError") +} + +func TestResolveEndpoint_StrictPartitionsUnknownEndpoint(t *testing.T) { + _, err := testPartitions.EndpointFor("service2", "us-region-1", StrictMatchingOption) + + assert.Error(t, err) + + _, ok := err.(UnknownEndpointError) + assert.True(t, ok, "expect error to be UnknownEndpointError") +} + +func TestResolveEndpoint_NotRegionalized(t *testing.T) { + resolved, err := testPartitions.EndpointFor("globalService", "us-west-2") + + assert.NoError(t, err) + assert.Equal(t, "https://globalService.amazonaws.com", resolved.URL) + assert.Equal(t, "us-east-1", resolved.SigningRegion) + assert.Equal(t, "globalService", resolved.SigningName) +} + +func TestResolveEndpoint_AwsGlobal(t *testing.T) { + resolved, err := testPartitions.EndpointFor("globalService", "aws-global") + + assert.NoError(t, err) + assert.Equal(t, "https://globalService.amazonaws.com", resolved.URL) + assert.Equal(t, "us-east-1", resolved.SigningRegion) + assert.Equal(t, "globalService", resolved.SigningName) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/errors.go b/vendor/github.com/aws/aws-sdk-go/aws/errors.go new file mode 100644 index 0000000..5766361 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/errors.go @@ -0,0 +1,17 @@ +package aws + +import "github.com/aws/aws-sdk-go/aws/awserr" + +var ( + // ErrMissingRegion is an error that is returned if region configuration is + // not found. + // + // @readonly + ErrMissingRegion = awserr.New("MissingRegion", "could not find region configuration", nil) + + // ErrMissingEndpoint is an error that is returned if an endpoint cannot be + // resolved for a service. + // + // @readonly + ErrMissingEndpoint = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil) +) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go b/vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go new file mode 100644 index 0000000..91a6f27 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go @@ -0,0 +1,12 @@ +package aws + +// JSONValue is a representation of a grab bag type that will be marshaled +// into a json string. This type can be used just like any other map. +// +// Example: +// +// values := aws.JSONValue{ +// "Foo": "Bar", +// } +// values["Baz"] = "Qux" +type JSONValue map[string]interface{} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/logger.go b/vendor/github.com/aws/aws-sdk-go/aws/logger.go new file mode 100644 index 0000000..3babb5a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/logger.go @@ -0,0 +1,112 @@ +package aws + +import ( + "log" + "os" +) + +// A LogLevelType defines the level logging should be performed at. Used to instruct +// the SDK which statements should be logged. +type LogLevelType uint + +// LogLevel returns the pointer to a LogLevel. Should be used to workaround +// not being able to take the address of a non-composite literal. +func LogLevel(l LogLevelType) *LogLevelType { + return &l +} + +// Value returns the LogLevel value or the default value LogOff if the LogLevel +// is nil. Safe to use on nil value LogLevelTypes. +func (l *LogLevelType) Value() LogLevelType { + if l != nil { + return *l + } + return LogOff +} + +// Matches returns true if the v LogLevel is enabled by this LogLevel. Should be +// used with logging sub levels. Is safe to use on nil value LogLevelTypes. If +// LogLevel is nil, will default to LogOff comparison. +func (l *LogLevelType) Matches(v LogLevelType) bool { + c := l.Value() + return c&v == v +} + +// AtLeast returns true if this LogLevel is at least high enough to satisfies v. +// Is safe to use on nil value LogLevelTypes. If LogLevel is nil, will default +// to LogOff comparison. +func (l *LogLevelType) AtLeast(v LogLevelType) bool { + c := l.Value() + return c >= v +} + +const ( + // LogOff states that no logging should be performed by the SDK. This is the + // default state of the SDK, and should be use to disable all logging. + LogOff LogLevelType = iota * 0x1000 + + // LogDebug state that debug output should be logged by the SDK. This should + // be used to inspect request made and responses received. + LogDebug +) + +// Debug Logging Sub Levels +const ( + // LogDebugWithSigning states that the SDK should log request signing and + // presigning events. This should be used to log the signing details of + // requests for debugging. Will also enable LogDebug. + LogDebugWithSigning LogLevelType = LogDebug | (1 << iota) + + // LogDebugWithHTTPBody states the SDK should log HTTP request and response + // HTTP bodys in addition to the headers and path. This should be used to + // see the body content of requests and responses made while using the SDK + // Will also enable LogDebug. + LogDebugWithHTTPBody + + // LogDebugWithRequestRetries states the SDK should log when service requests will + // be retried. This should be used to log when you want to log when service + // requests are being retried. Will also enable LogDebug. + LogDebugWithRequestRetries + + // LogDebugWithRequestErrors states the SDK should log when service requests fail + // to build, send, validate, or unmarshal. + LogDebugWithRequestErrors +) + +// A Logger is a minimalistic interface for the SDK to log messages to. Should +// be used to provide custom logging writers for the SDK to use. +type Logger interface { + Log(...interface{}) +} + +// A LoggerFunc is a convenience type to convert a function taking a variadic +// list of arguments and wrap it so the Logger interface can be used. +// +// Example: +// s3.New(sess, &aws.Config{Logger: aws.LoggerFunc(func(args ...interface{}) { +// fmt.Fprintln(os.Stdout, args...) +// })}) +type LoggerFunc func(...interface{}) + +// Log calls the wrapped function with the arguments provided +func (f LoggerFunc) Log(args ...interface{}) { + f(args...) +} + +// NewDefaultLogger returns a Logger which will write log messages to stdout, and +// use same formatting runes as the stdlib log.Logger +func NewDefaultLogger() Logger { + return &defaultLogger{ + logger: log.New(os.Stdout, "", log.LstdFlags), + } +} + +// A defaultLogger provides a minimalistic logger satisfying the Logger interface. +type defaultLogger struct { + logger *log.Logger +} + +// Log logs the parameters to the stdlib logger. See log.Println. +func (l defaultLogger) Log(args ...interface{}) { + l.logger.Println(args...) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go new file mode 100644 index 0000000..271da43 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go @@ -0,0 +1,19 @@ +// +build !appengine,!plan9 + +package request + +import ( + "net" + "os" + "syscall" +) + +func isErrConnectionReset(err error) bool { + if opErr, ok := err.(*net.OpError); ok { + if sysErr, ok := opErr.Err.(*os.SyscallError); ok { + return sysErr.Err == syscall.ECONNRESET + } + } + + return false +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go new file mode 100644 index 0000000..daf9eca --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go @@ -0,0 +1,11 @@ +// +build appengine plan9 + +package request + +import ( + "strings" +) + +func isErrConnectionReset(err error) bool { + return strings.Contains(err.Error(), "connection reset") +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other_test.go new file mode 100644 index 0000000..aba8eb4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other_test.go @@ -0,0 +1,9 @@ +// +build appengine plan9 + +package request_test + +import ( + "errors" +) + +var stubConnectionResetError = errors.New("connection reset") diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_test.go new file mode 100644 index 0000000..bb5f6bd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_test.go @@ -0,0 +1,11 @@ +// +build !appengine,!plan9 + +package request_test + +import ( + "net" + "os" + "syscall" +) + +var stubConnectionResetError = &net.OpError{Err: &os.SyscallError{Syscall: "read", Err: syscall.ECONNRESET}} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go new file mode 100644 index 0000000..802ac88 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go @@ -0,0 +1,256 @@ +package request + +import ( + "fmt" + "strings" +) + +// A Handlers provides a collection of request handlers for various +// stages of handling requests. +type Handlers struct { + Validate HandlerList + Build HandlerList + Sign HandlerList + Send HandlerList + ValidateResponse HandlerList + Unmarshal HandlerList + UnmarshalMeta HandlerList + UnmarshalError HandlerList + Retry HandlerList + AfterRetry HandlerList + Complete HandlerList +} + +// Copy returns of this handler's lists. +func (h *Handlers) Copy() Handlers { + return Handlers{ + Validate: h.Validate.copy(), + Build: h.Build.copy(), + Sign: h.Sign.copy(), + Send: h.Send.copy(), + ValidateResponse: h.ValidateResponse.copy(), + Unmarshal: h.Unmarshal.copy(), + UnmarshalError: h.UnmarshalError.copy(), + UnmarshalMeta: h.UnmarshalMeta.copy(), + Retry: h.Retry.copy(), + AfterRetry: h.AfterRetry.copy(), + Complete: h.Complete.copy(), + } +} + +// Clear removes callback functions for all handlers +func (h *Handlers) Clear() { + h.Validate.Clear() + h.Build.Clear() + h.Send.Clear() + h.Sign.Clear() + h.Unmarshal.Clear() + h.UnmarshalMeta.Clear() + h.UnmarshalError.Clear() + h.ValidateResponse.Clear() + h.Retry.Clear() + h.AfterRetry.Clear() + h.Complete.Clear() +} + +// A HandlerListRunItem represents an entry in the HandlerList which +// is being run. +type HandlerListRunItem struct { + Index int + Handler NamedHandler + Request *Request +} + +// A HandlerList manages zero or more handlers in a list. +type HandlerList struct { + list []NamedHandler + + // Called after each request handler in the list is called. If set + // and the func returns true the HandlerList will continue to iterate + // over the request handlers. If false is returned the HandlerList + // will stop iterating. + // + // Should be used if extra logic to be performed between each handler + // in the list. This can be used to terminate a list's iteration + // based on a condition such as error like, HandlerListStopOnError. + // Or for logging like HandlerListLogItem. + AfterEachFn func(item HandlerListRunItem) bool +} + +// A NamedHandler is a struct that contains a name and function callback. +type NamedHandler struct { + Name string + Fn func(*Request) +} + +// copy creates a copy of the handler list. +func (l *HandlerList) copy() HandlerList { + n := HandlerList{ + AfterEachFn: l.AfterEachFn, + } + if len(l.list) == 0 { + return n + } + + n.list = append(make([]NamedHandler, 0, len(l.list)), l.list...) + return n +} + +// Clear clears the handler list. +func (l *HandlerList) Clear() { + l.list = l.list[0:0] +} + +// Len returns the number of handlers in the list. +func (l *HandlerList) Len() int { + return len(l.list) +} + +// PushBack pushes handler f to the back of the handler list. +func (l *HandlerList) PushBack(f func(*Request)) { + l.PushBackNamed(NamedHandler{"__anonymous", f}) +} + +// PushBackNamed pushes named handler f to the back of the handler list. +func (l *HandlerList) PushBackNamed(n NamedHandler) { + if cap(l.list) == 0 { + l.list = make([]NamedHandler, 0, 5) + } + l.list = append(l.list, n) +} + +// PushFront pushes handler f to the front of the handler list. +func (l *HandlerList) PushFront(f func(*Request)) { + l.PushFrontNamed(NamedHandler{"__anonymous", f}) +} + +// PushFrontNamed pushes named handler f to the front of the handler list. +func (l *HandlerList) PushFrontNamed(n NamedHandler) { + if cap(l.list) == len(l.list) { + // Allocating new list required + l.list = append([]NamedHandler{n}, l.list...) + } else { + // Enough room to prepend into list. + l.list = append(l.list, NamedHandler{}) + copy(l.list[1:], l.list) + l.list[0] = n + } +} + +// Remove removes a NamedHandler n +func (l *HandlerList) Remove(n NamedHandler) { + l.RemoveByName(n.Name) +} + +// RemoveByName removes a NamedHandler by name. +func (l *HandlerList) RemoveByName(name string) { + for i := 0; i < len(l.list); i++ { + m := l.list[i] + if m.Name == name { + // Shift array preventing creating new arrays + copy(l.list[i:], l.list[i+1:]) + l.list[len(l.list)-1] = NamedHandler{} + l.list = l.list[:len(l.list)-1] + + // decrement list so next check to length is correct + i-- + } + } +} + +// SwapNamed will swap out any existing handlers with the same name as the +// passed in NamedHandler returning true if handlers were swapped. False is +// returned otherwise. +func (l *HandlerList) SwapNamed(n NamedHandler) (swapped bool) { + for i := 0; i < len(l.list); i++ { + if l.list[i].Name == n.Name { + l.list[i].Fn = n.Fn + swapped = true + } + } + + return swapped +} + +// SetBackNamed will replace the named handler if it exists in the handler list. +// If the handler does not exist the handler will be added to the end of the list. +func (l *HandlerList) SetBackNamed(n NamedHandler) { + if !l.SwapNamed(n) { + l.PushBackNamed(n) + } +} + +// SetFrontNamed will replace the named handler if it exists in the handler list. +// If the handler does not exist the handler will be added to the beginning of +// the list. +func (l *HandlerList) SetFrontNamed(n NamedHandler) { + if !l.SwapNamed(n) { + l.PushFrontNamed(n) + } +} + +// Run executes all handlers in the list with a given request object. +func (l *HandlerList) Run(r *Request) { + for i, h := range l.list { + h.Fn(r) + item := HandlerListRunItem{ + Index: i, Handler: h, Request: r, + } + if l.AfterEachFn != nil && !l.AfterEachFn(item) { + return + } + } +} + +// HandlerListLogItem logs the request handler and the state of the +// request's Error value. Always returns true to continue iterating +// request handlers in a HandlerList. +func HandlerListLogItem(item HandlerListRunItem) bool { + if item.Request.Config.Logger == nil { + return true + } + item.Request.Config.Logger.Log("DEBUG: RequestHandler", + item.Index, item.Handler.Name, item.Request.Error) + + return true +} + +// HandlerListStopOnError returns false to stop the HandlerList iterating +// over request handlers if Request.Error is not nil. True otherwise +// to continue iterating. +func HandlerListStopOnError(item HandlerListRunItem) bool { + return item.Request.Error == nil +} + +// WithAppendUserAgent will add a string to the user agent prefixed with a +// single white space. +func WithAppendUserAgent(s string) Option { + return func(r *Request) { + r.Handlers.Build.PushBack(func(r2 *Request) { + AddToUserAgent(r, s) + }) + } +} + +// MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request +// header. If the extra parameters are provided they will be added as metadata to the +// name/version pair resulting in the following format. +// "name/version (extra0; extra1; ...)" +// The user agent part will be concatenated with this current request's user agent string. +func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) { + ua := fmt.Sprintf("%s/%s", name, version) + if len(extra) > 0 { + ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; ")) + } + return func(r *Request) { + AddToUserAgent(r, ua) + } +} + +// MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header. +// The input string will be concatenated with the current request's user agent string. +func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) { + return func(r *Request) { + AddToUserAgent(r, s) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/handlers_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers_test.go new file mode 100644 index 0000000..b2da558 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers_test.go @@ -0,0 +1,266 @@ +package request_test + +import ( + "reflect" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/service/s3" +) + +func TestHandlerList(t *testing.T) { + s := "" + r := &request.Request{} + l := request.HandlerList{} + l.PushBack(func(r *request.Request) { + s += "a" + r.Data = s + }) + l.Run(r) + if e, a := "a", s; e != a { + t.Errorf("expect %q update got %q", e, a) + } + if e, a := "a", r.Data.(string); e != a { + t.Errorf("expect %q data update got %q", e, a) + } +} + +func TestMultipleHandlers(t *testing.T) { + r := &request.Request{} + l := request.HandlerList{} + l.PushBack(func(r *request.Request) { r.Data = nil }) + l.PushFront(func(r *request.Request) { r.Data = aws.Bool(true) }) + l.Run(r) + if r.Data != nil { + t.Error("Expected handler to execute") + } +} + +func TestNamedHandlers(t *testing.T) { + l := request.HandlerList{} + named := request.NamedHandler{Name: "Name", Fn: func(r *request.Request) {}} + named2 := request.NamedHandler{Name: "NotName", Fn: func(r *request.Request) {}} + l.PushBackNamed(named) + l.PushBackNamed(named) + l.PushBackNamed(named2) + l.PushBack(func(r *request.Request) {}) + if e, a := 4, l.Len(); e != a { + t.Errorf("expect %d list length, got %d", e, a) + } + l.Remove(named) + if e, a := 2, l.Len(); e != a { + t.Errorf("expect %d list length, got %d", e, a) + } +} + +func TestSwapHandlers(t *testing.T) { + firstHandlerCalled := 0 + swappedOutHandlerCalled := 0 + swappedInHandlerCalled := 0 + + l := request.HandlerList{} + named := request.NamedHandler{Name: "Name", Fn: func(r *request.Request) { + firstHandlerCalled++ + }} + named2 := request.NamedHandler{Name: "SwapOutName", Fn: func(r *request.Request) { + swappedOutHandlerCalled++ + }} + l.PushBackNamed(named) + l.PushBackNamed(named2) + l.PushBackNamed(named) + + l.SwapNamed(request.NamedHandler{Name: "SwapOutName", Fn: func(r *request.Request) { + swappedInHandlerCalled++ + }}) + + l.Run(&request.Request{}) + + if e, a := 2, firstHandlerCalled; e != a { + t.Errorf("expect first handler to be called %d, was called %d times", e, a) + } + if n := swappedOutHandlerCalled; n != 0 { + t.Errorf("expect swapped out handler to not be called, was called %d times", n) + } + if e, a := 1, swappedInHandlerCalled; e != a { + t.Errorf("expect swapped in handler to be called %d, was called %d times", e, a) + } +} + +func TestSetBackNamed_Exists(t *testing.T) { + firstHandlerCalled := 0 + swappedOutHandlerCalled := 0 + swappedInHandlerCalled := 0 + + l := request.HandlerList{} + named := request.NamedHandler{Name: "Name", Fn: func(r *request.Request) { + firstHandlerCalled++ + }} + named2 := request.NamedHandler{Name: "SwapOutName", Fn: func(r *request.Request) { + swappedOutHandlerCalled++ + }} + l.PushBackNamed(named) + l.PushBackNamed(named2) + + l.SetBackNamed(request.NamedHandler{Name: "SwapOutName", Fn: func(r *request.Request) { + swappedInHandlerCalled++ + }}) + + l.Run(&request.Request{}) + + if e, a := 1, firstHandlerCalled; e != a { + t.Errorf("expect first handler to be called %d, was called %d times", e, a) + } + if n := swappedOutHandlerCalled; n != 0 { + t.Errorf("expect swapped out handler to not be called, was called %d times", n) + } + if e, a := 1, swappedInHandlerCalled; e != a { + t.Errorf("expect swapped in handler to be called %d, was called %d times", e, a) + } +} + +func TestSetBackNamed_NotExists(t *testing.T) { + firstHandlerCalled := 0 + secondHandlerCalled := 0 + swappedInHandlerCalled := 0 + + l := request.HandlerList{} + named := request.NamedHandler{Name: "Name", Fn: func(r *request.Request) { + firstHandlerCalled++ + }} + named2 := request.NamedHandler{Name: "OtherName", Fn: func(r *request.Request) { + secondHandlerCalled++ + }} + l.PushBackNamed(named) + l.PushBackNamed(named2) + + l.SetBackNamed(request.NamedHandler{Name: "SwapOutName", Fn: func(r *request.Request) { + swappedInHandlerCalled++ + }}) + + l.Run(&request.Request{}) + + if e, a := 1, firstHandlerCalled; e != a { + t.Errorf("expect first handler to be called %d, was called %d times", e, a) + } + if e, a := 1, secondHandlerCalled; e != a { + t.Errorf("expect second handler to be called %d, was called %d times", e, a) + } + if e, a := 1, swappedInHandlerCalled; e != a { + t.Errorf("expect swapped in handler to be called %d, was called %d times", e, a) + } +} + +func TestLoggedHandlers(t *testing.T) { + expectedHandlers := []string{"name1", "name2"} + l := request.HandlerList{} + loggedHandlers := []string{} + l.AfterEachFn = request.HandlerListLogItem + cfg := aws.Config{Logger: aws.LoggerFunc(func(args ...interface{}) { + loggedHandlers = append(loggedHandlers, args[2].(string)) + })} + + named1 := request.NamedHandler{Name: "name1", Fn: func(r *request.Request) {}} + named2 := request.NamedHandler{Name: "name2", Fn: func(r *request.Request) {}} + l.PushBackNamed(named1) + l.PushBackNamed(named2) + l.Run(&request.Request{Config: cfg}) + + if !reflect.DeepEqual(expectedHandlers, loggedHandlers) { + t.Errorf("expect handlers executed %v to match logged handlers, %v", + expectedHandlers, loggedHandlers) + } +} + +func TestStopHandlers(t *testing.T) { + l := request.HandlerList{} + stopAt := 1 + l.AfterEachFn = func(item request.HandlerListRunItem) bool { + return item.Index != stopAt + } + + called := 0 + l.PushBackNamed(request.NamedHandler{Name: "name1", Fn: func(r *request.Request) { + called++ + }}) + l.PushBackNamed(request.NamedHandler{Name: "name2", Fn: func(r *request.Request) { + called++ + }}) + l.PushBackNamed(request.NamedHandler{Name: "name3", Fn: func(r *request.Request) { + t.Fatalf("third handler should not be called") + }}) + l.Run(&request.Request{}) + + if e, a := 2, called; e != a { + t.Errorf("expect %d handlers called, got %d", e, a) + } +} + +func BenchmarkNewRequest(b *testing.B) { + svc := s3.New(unit.Session) + + for i := 0; i < b.N; i++ { + r, _ := svc.GetObjectRequest(nil) + if r == nil { + b.Fatal("r should not be nil") + } + } +} + +func BenchmarkHandlersCopy(b *testing.B) { + handlers := request.Handlers{} + + handlers.Validate.PushBack(func(r *request.Request) {}) + handlers.Validate.PushBack(func(r *request.Request) {}) + handlers.Build.PushBack(func(r *request.Request) {}) + handlers.Build.PushBack(func(r *request.Request) {}) + handlers.Send.PushBack(func(r *request.Request) {}) + handlers.Send.PushBack(func(r *request.Request) {}) + handlers.Unmarshal.PushBack(func(r *request.Request) {}) + handlers.Unmarshal.PushBack(func(r *request.Request) {}) + + for i := 0; i < b.N; i++ { + h := handlers.Copy() + if e, a := handlers.Validate.Len(), h.Validate.Len(); e != a { + b.Fatalf("expected %d handlers got %d", e, a) + } + } +} + +func BenchmarkHandlersPushBack(b *testing.B) { + handlers := request.Handlers{} + + for i := 0; i < b.N; i++ { + h := handlers.Copy() + h.Validate.PushBack(func(r *request.Request) {}) + h.Validate.PushBack(func(r *request.Request) {}) + h.Validate.PushBack(func(r *request.Request) {}) + h.Validate.PushBack(func(r *request.Request) {}) + } +} + +func BenchmarkHandlersPushFront(b *testing.B) { + handlers := request.Handlers{} + + for i := 0; i < b.N; i++ { + h := handlers.Copy() + h.Validate.PushFront(func(r *request.Request) {}) + h.Validate.PushFront(func(r *request.Request) {}) + h.Validate.PushFront(func(r *request.Request) {}) + h.Validate.PushFront(func(r *request.Request) {}) + } +} + +func BenchmarkHandlersClear(b *testing.B) { + handlers := request.Handlers{} + + for i := 0; i < b.N; i++ { + h := handlers.Copy() + h.Validate.PushFront(func(r *request.Request) {}) + h.Validate.PushFront(func(r *request.Request) {}) + h.Validate.PushFront(func(r *request.Request) {}) + h.Validate.PushFront(func(r *request.Request) {}) + h.Clear() + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go new file mode 100644 index 0000000..79f7960 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go @@ -0,0 +1,24 @@ +package request + +import ( + "io" + "net/http" + "net/url" +) + +func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request { + req := new(http.Request) + *req = *r + req.URL = &url.URL{} + *req.URL = *r.URL + req.Body = body + + req.Header = http.Header{} + for k, v := range r.Header { + for _, vv := range v { + req.Header.Add(k, vv) + } + } + + return req +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/http_request_copy_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request_copy_test.go new file mode 100644 index 0000000..4a4f855 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request_copy_test.go @@ -0,0 +1,34 @@ +package request + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/url" + "sync" + "testing" +) + +func TestRequestCopyRace(t *testing.T) { + origReq := &http.Request{URL: &url.URL{}, Header: http.Header{}} + origReq.Header.Set("Header", "OrigValue") + + var wg sync.WaitGroup + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + req := copyHTTPRequest(origReq, ioutil.NopCloser(&bytes.Buffer{})) + req.Header.Set("Header", "Value") + go func() { + req2 := copyHTTPRequest(req, ioutil.NopCloser(&bytes.Buffer{})) + req2.Header.Add("Header", "Value2") + }() + _ = req.Header.Get("Header") + wg.Done() + }() + _ = origReq.Header.Get("Header") + } + origReq.Header.Get("Header") + + wg.Wait() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/http_request_retry_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request_retry_test.go new file mode 100644 index 0000000..2ce9ef4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request_retry_test.go @@ -0,0 +1,37 @@ +// +build go1.5 + +package request_test + +import ( + "errors" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/awstesting/mock" + "github.com/stretchr/testify/assert" +) + +func TestRequestCancelRetry(t *testing.T) { + c := make(chan struct{}) + + reqNum := 0 + s := mock.NewMockClient(aws.NewConfig().WithMaxRetries(10)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.Clear() + s.Handlers.UnmarshalMeta.Clear() + s.Handlers.UnmarshalError.Clear() + s.Handlers.Send.PushFront(func(r *request.Request) { + reqNum++ + r.Error = errors.New("net/http: request canceled") + }) + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + r.HTTPRequest.Cancel = c + close(c) + + err := r.Send() + assert.True(t, strings.Contains(err.Error(), "canceled")) + assert.Equal(t, 1, reqNum) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go new file mode 100644 index 0000000..02f07f4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go @@ -0,0 +1,58 @@ +package request + +import ( + "io" + "sync" +) + +// offsetReader is a thread-safe io.ReadCloser to prevent racing +// with retrying requests +type offsetReader struct { + buf io.ReadSeeker + lock sync.Mutex + closed bool +} + +func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader { + reader := &offsetReader{} + buf.Seek(offset, 0) + + reader.buf = buf + return reader +} + +// Close will close the instance of the offset reader's access to +// the underlying io.ReadSeeker. +func (o *offsetReader) Close() error { + o.lock.Lock() + defer o.lock.Unlock() + o.closed = true + return nil +} + +// Read is a thread-safe read of the underlying io.ReadSeeker +func (o *offsetReader) Read(p []byte) (int, error) { + o.lock.Lock() + defer o.lock.Unlock() + + if o.closed { + return 0, io.EOF + } + + return o.buf.Read(p) +} + +// Seek is a thread-safe seeking operation. +func (o *offsetReader) Seek(offset int64, whence int) (int64, error) { + o.lock.Lock() + defer o.lock.Unlock() + + return o.buf.Seek(offset, whence) +} + +// CloseAndCopy will return a new offsetReader with a copy of the old buffer +// and close the old buffer. +func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader { + o.Close() + return newOffsetReader(o.buf, offset) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader_test.go new file mode 100644 index 0000000..01856e3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader_test.go @@ -0,0 +1,139 @@ +package request + +import ( + "bytes" + "io" + "math/rand" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestOffsetReaderRead(t *testing.T) { + buf := []byte("testData") + reader := &offsetReader{buf: bytes.NewReader(buf)} + + tempBuf := make([]byte, len(buf)) + + n, err := reader.Read(tempBuf) + + assert.Equal(t, n, len(buf)) + assert.Nil(t, err) + assert.Equal(t, buf, tempBuf) +} + +func TestOffsetReaderSeek(t *testing.T) { + buf := []byte("testData") + reader := newOffsetReader(bytes.NewReader(buf), 0) + + orig, err := reader.Seek(0, 1) + assert.NoError(t, err) + assert.Equal(t, int64(0), orig) + + n, err := reader.Seek(0, 2) + assert.NoError(t, err) + assert.Equal(t, int64(len(buf)), n) + + n, err = reader.Seek(orig, 0) + assert.NoError(t, err) + assert.Equal(t, int64(0), n) +} + +func TestOffsetReaderClose(t *testing.T) { + buf := []byte("testData") + reader := &offsetReader{buf: bytes.NewReader(buf)} + + err := reader.Close() + assert.Nil(t, err) + + tempBuf := make([]byte, len(buf)) + n, err := reader.Read(tempBuf) + assert.Equal(t, n, 0) + assert.Equal(t, err, io.EOF) +} + +func TestOffsetReaderCloseAndCopy(t *testing.T) { + buf := []byte("testData") + tempBuf := make([]byte, len(buf)) + reader := &offsetReader{buf: bytes.NewReader(buf)} + + newReader := reader.CloseAndCopy(0) + + n, err := reader.Read(tempBuf) + assert.Equal(t, n, 0) + assert.Equal(t, err, io.EOF) + + n, err = newReader.Read(tempBuf) + assert.Equal(t, n, len(buf)) + assert.Nil(t, err) + assert.Equal(t, buf, tempBuf) +} + +func TestOffsetReaderCloseAndCopyOffset(t *testing.T) { + buf := []byte("testData") + tempBuf := make([]byte, len(buf)) + reader := &offsetReader{buf: bytes.NewReader(buf)} + + newReader := reader.CloseAndCopy(4) + n, err := newReader.Read(tempBuf) + assert.Equal(t, n, len(buf)-4) + assert.Nil(t, err) + + expected := []byte{'D', 'a', 't', 'a', 0, 0, 0, 0} + assert.Equal(t, expected, tempBuf) +} + +func TestOffsetReaderRace(t *testing.T) { + wg := sync.WaitGroup{} + + f := func(reader *offsetReader) { + defer wg.Done() + var err error + buf := make([]byte, 1) + _, err = reader.Read(buf) + for err != io.EOF { + _, err = reader.Read(buf) + } + + } + + closeFn := func(reader *offsetReader) { + defer wg.Done() + time.Sleep(time.Duration(rand.Intn(20)+1) * time.Millisecond) + reader.Close() + } + for i := 0; i < 50; i++ { + reader := &offsetReader{buf: bytes.NewReader(make([]byte, 1024*1024))} + wg.Add(1) + go f(reader) + wg.Add(1) + go closeFn(reader) + } + wg.Wait() +} + +func BenchmarkOffsetReader(b *testing.B) { + bufSize := 1024 * 1024 * 100 + buf := make([]byte, bufSize) + reader := &offsetReader{buf: bytes.NewReader(buf)} + + tempBuf := make([]byte, 1024) + + for i := 0; i < b.N; i++ { + reader.Read(tempBuf) + } +} + +func BenchmarkBytesReader(b *testing.B) { + bufSize := 1024 * 1024 * 100 + buf := make([]byte, bufSize) + reader := bytes.NewReader(buf) + + tempBuf := make([]byte, 1024) + + for i := 0; i < b.N; i++ { + reader.Read(tempBuf) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go new file mode 100644 index 0000000..5c7db49 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go @@ -0,0 +1,679 @@ +package request + +import ( + "bytes" + "fmt" + "io" + "net" + "net/http" + "net/url" + "reflect" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/client/metadata" +) + +const ( + // ErrCodeSerialization is the serialization error code that is received + // during protocol unmarshaling. + ErrCodeSerialization = "SerializationError" + + // ErrCodeRead is an error that is returned during HTTP reads. + ErrCodeRead = "ReadError" + + // ErrCodeResponseTimeout is the connection timeout error that is received + // during body reads. + ErrCodeResponseTimeout = "ResponseTimeout" + + // ErrCodeInvalidPresignExpire is returned when the expire time provided to + // presign is invalid + ErrCodeInvalidPresignExpire = "InvalidPresignExpireError" + + // CanceledErrorCode is the error code that will be returned by an + // API request that was canceled. Requests given a aws.Context may + // return this error when canceled. + CanceledErrorCode = "RequestCanceled" +) + +// A Request is the service request to be made. +type Request struct { + Config aws.Config + ClientInfo metadata.ClientInfo + Handlers Handlers + + Retryer + Time time.Time + Operation *Operation + HTTPRequest *http.Request + HTTPResponse *http.Response + Body io.ReadSeeker + BodyStart int64 // offset from beginning of Body that the request body starts + Params interface{} + Error error + Data interface{} + RequestID string + RetryCount int + Retryable *bool + RetryDelay time.Duration + NotHoist bool + SignedHeaderVals http.Header + LastSignedAt time.Time + DisableFollowRedirects bool + + // A value greater than 0 instructs the request to be signed as Presigned URL + // You should not set this field directly. Instead use Request's + // Presign or PresignRequest methods. + ExpireTime time.Duration + + context aws.Context + + built bool + + // Need to persist an intermediate body between the input Body and HTTP + // request body because the HTTP Client's transport can maintain a reference + // to the HTTP request's body after the client has returned. This value is + // safe to use concurrently and wrap the input Body for each HTTP request. + safeBody *offsetReader +} + +// An Operation is the service API operation to be made. +type Operation struct { + Name string + HTTPMethod string + HTTPPath string + *Paginator + + BeforePresignFn func(r *Request) error +} + +// New returns a new Request pointer for the service API +// operation and parameters. +// +// Params is any value of input parameters to be the request payload. +// Data is pointer value to an object which the request's response +// payload will be deserialized to. +func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers, + retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request { + + method := operation.HTTPMethod + if method == "" { + method = "POST" + } + + httpReq, _ := http.NewRequest(method, "", nil) + + var err error + httpReq.URL, err = url.Parse(clientInfo.Endpoint + operation.HTTPPath) + if err != nil { + httpReq.URL = &url.URL{} + err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err) + } + + SanitizeHostForHeader(httpReq) + + r := &Request{ + Config: cfg, + ClientInfo: clientInfo, + Handlers: handlers.Copy(), + + Retryer: retryer, + Time: time.Now(), + ExpireTime: 0, + Operation: operation, + HTTPRequest: httpReq, + Body: nil, + Params: params, + Error: err, + Data: data, + } + r.SetBufferBody([]byte{}) + + return r +} + +// A Option is a functional option that can augment or modify a request when +// using a WithContext API operation method. +type Option func(*Request) + +// WithGetResponseHeader builds a request Option which will retrieve a single +// header value from the HTTP Response. If there are multiple values for the +// header key use WithGetResponseHeaders instead to access the http.Header +// map directly. The passed in val pointer must be non-nil. +// +// This Option can be used multiple times with a single API operation. +// +// var id2, versionID string +// svc.PutObjectWithContext(ctx, params, +// request.WithGetResponseHeader("x-amz-id-2", &id2), +// request.WithGetResponseHeader("x-amz-version-id", &versionID), +// ) +func WithGetResponseHeader(key string, val *string) Option { + return func(r *Request) { + r.Handlers.Complete.PushBack(func(req *Request) { + *val = req.HTTPResponse.Header.Get(key) + }) + } +} + +// WithGetResponseHeaders builds a request Option which will retrieve the +// headers from the HTTP response and assign them to the passed in headers +// variable. The passed in headers pointer must be non-nil. +// +// var headers http.Header +// svc.PutObjectWithContext(ctx, params, request.WithGetResponseHeaders(&headers)) +func WithGetResponseHeaders(headers *http.Header) Option { + return func(r *Request) { + r.Handlers.Complete.PushBack(func(req *Request) { + *headers = req.HTTPResponse.Header + }) + } +} + +// WithLogLevel is a request option that will set the request to use a specific +// log level when the request is made. +// +// svc.PutObjectWithContext(ctx, params, request.WithLogLevel(aws.LogDebugWithHTTPBody) +func WithLogLevel(l aws.LogLevelType) Option { + return func(r *Request) { + r.Config.LogLevel = aws.LogLevel(l) + } +} + +// ApplyOptions will apply each option to the request calling them in the order +// the were provided. +func (r *Request) ApplyOptions(opts ...Option) { + for _, opt := range opts { + opt(r) + } +} + +// Context will always returns a non-nil context. If Request does not have a +// context aws.BackgroundContext will be returned. +func (r *Request) Context() aws.Context { + if r.context != nil { + return r.context + } + return aws.BackgroundContext() +} + +// SetContext adds a Context to the current request that can be used to cancel +// a in-flight request. The Context value must not be nil, or this method will +// panic. +// +// Unlike http.Request.WithContext, SetContext does not return a copy of the +// Request. It is not safe to use use a single Request value for multiple +// requests. A new Request should be created for each API operation request. +// +// Go 1.6 and below: +// The http.Request's Cancel field will be set to the Done() value of +// the context. This will overwrite the Cancel field's value. +// +// Go 1.7 and above: +// The http.Request.WithContext will be used to set the context on the underlying +// http.Request. This will create a shallow copy of the http.Request. The SDK +// may create sub contexts in the future for nested requests such as retries. +func (r *Request) SetContext(ctx aws.Context) { + if ctx == nil { + panic("context cannot be nil") + } + setRequestContext(r, ctx) +} + +// WillRetry returns if the request's can be retried. +func (r *Request) WillRetry() bool { + return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries() +} + +// ParamsFilled returns if the request's parameters have been populated +// and the parameters are valid. False is returned if no parameters are +// provided or invalid. +func (r *Request) ParamsFilled() bool { + return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid() +} + +// DataFilled returns true if the request's data for response deserialization +// target has been set and is a valid. False is returned if data is not +// set, or is invalid. +func (r *Request) DataFilled() bool { + return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid() +} + +// SetBufferBody will set the request's body bytes that will be sent to +// the service API. +func (r *Request) SetBufferBody(buf []byte) { + r.SetReaderBody(bytes.NewReader(buf)) +} + +// SetStringBody sets the body of the request to be backed by a string. +func (r *Request) SetStringBody(s string) { + r.SetReaderBody(strings.NewReader(s)) +} + +// SetReaderBody will set the request's body reader. +func (r *Request) SetReaderBody(reader io.ReadSeeker) { + r.Body = reader + r.ResetBody() +} + +// Presign returns the request's signed URL. Error will be returned +// if the signing fails. +// +// It is invalid to create a presigned URL with a expire duration 0 or less. An +// error is returned if expire duration is 0 or less. +func (r *Request) Presign(expire time.Duration) (string, error) { + r = r.copy() + + // Presign requires all headers be hoisted. There is no way to retrieve + // the signed headers not hoisted without this. Making the presigned URL + // useless. + r.NotHoist = false + + u, _, err := getPresignedURL(r, expire) + return u, err +} + +// PresignRequest behaves just like presign, with the addition of returning a +// set of headers that were signed. +// +// It is invalid to create a presigned URL with a expire duration 0 or less. An +// error is returned if expire duration is 0 or less. +// +// Returns the URL string for the API operation with signature in the query string, +// and the HTTP headers that were included in the signature. These headers must +// be included in any HTTP request made with the presigned URL. +// +// To prevent hoisting any headers to the query string set NotHoist to true on +// this Request value prior to calling PresignRequest. +func (r *Request) PresignRequest(expire time.Duration) (string, http.Header, error) { + r = r.copy() + return getPresignedURL(r, expire) +} + +func getPresignedURL(r *Request, expire time.Duration) (string, http.Header, error) { + if expire <= 0 { + return "", nil, awserr.New( + ErrCodeInvalidPresignExpire, + "presigned URL requires an expire duration greater than 0", + nil, + ) + } + + r.ExpireTime = expire + + if r.Operation.BeforePresignFn != nil { + if err := r.Operation.BeforePresignFn(r); err != nil { + return "", nil, err + } + } + + if err := r.Sign(); err != nil { + return "", nil, err + } + + return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil +} + +func debugLogReqError(r *Request, stage string, retrying bool, err error) { + if !r.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) { + return + } + + retryStr := "not retrying" + if retrying { + retryStr = "will retry" + } + + r.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v", + stage, r.ClientInfo.ServiceName, r.Operation.Name, retryStr, err)) +} + +// Build will build the request's object so it can be signed and sent +// to the service. Build will also validate all the request's parameters. +// Anny additional build Handlers set on this request will be run +// in the order they were set. +// +// The request will only be built once. Multiple calls to build will have +// no effect. +// +// If any Validate or Build errors occur the build will stop and the error +// which occurred will be returned. +func (r *Request) Build() error { + if !r.built { + r.Handlers.Validate.Run(r) + if r.Error != nil { + debugLogReqError(r, "Validate Request", false, r.Error) + return r.Error + } + r.Handlers.Build.Run(r) + if r.Error != nil { + debugLogReqError(r, "Build Request", false, r.Error) + return r.Error + } + r.built = true + } + + return r.Error +} + +// Sign will sign the request returning error if errors are encountered. +// +// Send will build the request prior to signing. All Sign Handlers will +// be executed in the order they were set. +func (r *Request) Sign() error { + r.Build() + if r.Error != nil { + debugLogReqError(r, "Build Request", false, r.Error) + return r.Error + } + + r.Handlers.Sign.Run(r) + return r.Error +} + +func (r *Request) getNextRequestBody() (io.ReadCloser, error) { + if r.safeBody != nil { + r.safeBody.Close() + } + + r.safeBody = newOffsetReader(r.Body, r.BodyStart) + + // Go 1.8 tightened and clarified the rules code needs to use when building + // requests with the http package. Go 1.8 removed the automatic detection + // of if the Request.Body was empty, or actually had bytes in it. The SDK + // always sets the Request.Body even if it is empty and should not actually + // be sent. This is incorrect. + // + // Go 1.8 did add a http.NoBody value that the SDK can use to tell the http + // client that the request really should be sent without a body. The + // Request.Body cannot be set to nil, which is preferable, because the + // field is exported and could introduce nil pointer dereferences for users + // of the SDK if they used that field. + // + // Related golang/go#18257 + l, err := computeBodyLength(r.Body) + if err != nil { + return nil, awserr.New(ErrCodeSerialization, "failed to compute request body size", err) + } + + var body io.ReadCloser + if l == 0 { + body = NoBody + } else if l > 0 { + body = r.safeBody + } else { + // Hack to prevent sending bodies for methods where the body + // should be ignored by the server. Sending bodies on these + // methods without an associated ContentLength will cause the + // request to socket timeout because the server does not handle + // Transfer-Encoding: chunked bodies for these methods. + // + // This would only happen if a aws.ReaderSeekerCloser was used with + // a io.Reader that was not also an io.Seeker. + switch r.Operation.HTTPMethod { + case "GET", "HEAD", "DELETE": + body = NoBody + default: + body = r.safeBody + } + } + + return body, nil +} + +// Attempts to compute the length of the body of the reader using the +// io.Seeker interface. If the value is not seekable because of being +// a ReaderSeekerCloser without an unerlying Seeker -1 will be returned. +// If no error occurs the length of the body will be returned. +func computeBodyLength(r io.ReadSeeker) (int64, error) { + seekable := true + // Determine if the seeker is actually seekable. ReaderSeekerCloser + // hides the fact that a io.Readers might not actually be seekable. + switch v := r.(type) { + case aws.ReaderSeekerCloser: + seekable = v.IsSeeker() + case *aws.ReaderSeekerCloser: + seekable = v.IsSeeker() + } + if !seekable { + return -1, nil + } + + curOffset, err := r.Seek(0, 1) + if err != nil { + return 0, err + } + + endOffset, err := r.Seek(0, 2) + if err != nil { + return 0, err + } + + _, err = r.Seek(curOffset, 0) + if err != nil { + return 0, err + } + + return endOffset - curOffset, nil +} + +// GetBody will return an io.ReadSeeker of the Request's underlying +// input body with a concurrency safe wrapper. +func (r *Request) GetBody() io.ReadSeeker { + return r.safeBody +} + +// Send will send the request returning error if errors are encountered. +// +// Send will sign the request prior to sending. All Send Handlers will +// be executed in the order they were set. +// +// Canceling a request is non-deterministic. If a request has been canceled, +// then the transport will choose, randomly, one of the state channels during +// reads or getting the connection. +// +// readLoop() and getConn(req *Request, cm connectMethod) +// https://github.com/golang/go/blob/master/src/net/http/transport.go +// +// Send will not close the request.Request's body. +func (r *Request) Send() error { + defer func() { + // Regardless of success or failure of the request trigger the Complete + // request handlers. + r.Handlers.Complete.Run(r) + }() + + for { + if aws.BoolValue(r.Retryable) { + if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) { + r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d", + r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount)) + } + + // The previous http.Request will have a reference to the r.Body + // and the HTTP Client's Transport may still be reading from + // the request's body even though the Client's Do returned. + r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil) + r.ResetBody() + + // Closing response body to ensure that no response body is leaked + // between retry attempts. + if r.HTTPResponse != nil && r.HTTPResponse.Body != nil { + r.HTTPResponse.Body.Close() + } + } + + r.Sign() + if r.Error != nil { + return r.Error + } + + r.Retryable = nil + + r.Handlers.Send.Run(r) + if r.Error != nil { + if !shouldRetryCancel(r) { + return r.Error + } + + err := r.Error + r.Handlers.Retry.Run(r) + r.Handlers.AfterRetry.Run(r) + if r.Error != nil { + debugLogReqError(r, "Send Request", false, err) + return r.Error + } + debugLogReqError(r, "Send Request", true, err) + continue + } + r.Handlers.UnmarshalMeta.Run(r) + r.Handlers.ValidateResponse.Run(r) + if r.Error != nil { + r.Handlers.UnmarshalError.Run(r) + err := r.Error + + r.Handlers.Retry.Run(r) + r.Handlers.AfterRetry.Run(r) + if r.Error != nil { + debugLogReqError(r, "Validate Response", false, err) + return r.Error + } + debugLogReqError(r, "Validate Response", true, err) + continue + } + + r.Handlers.Unmarshal.Run(r) + if r.Error != nil { + err := r.Error + r.Handlers.Retry.Run(r) + r.Handlers.AfterRetry.Run(r) + if r.Error != nil { + debugLogReqError(r, "Unmarshal Response", false, err) + return r.Error + } + debugLogReqError(r, "Unmarshal Response", true, err) + continue + } + + break + } + + return nil +} + +// copy will copy a request which will allow for local manipulation of the +// request. +func (r *Request) copy() *Request { + req := &Request{} + *req = *r + req.Handlers = r.Handlers.Copy() + op := *r.Operation + req.Operation = &op + return req +} + +// AddToUserAgent adds the string to the end of the request's current user agent. +func AddToUserAgent(r *Request, s string) { + curUA := r.HTTPRequest.Header.Get("User-Agent") + if len(curUA) > 0 { + s = curUA + " " + s + } + r.HTTPRequest.Header.Set("User-Agent", s) +} + +func shouldRetryCancel(r *Request) bool { + awsErr, ok := r.Error.(awserr.Error) + timeoutErr := false + errStr := r.Error.Error() + if ok { + if awsErr.Code() == CanceledErrorCode { + return false + } + err := awsErr.OrigErr() + netErr, netOK := err.(net.Error) + timeoutErr = netOK && netErr.Temporary() + if urlErr, ok := err.(*url.Error); !timeoutErr && ok { + errStr = urlErr.Err.Error() + } + } + + // There can be two types of canceled errors here. + // The first being a net.Error and the other being an error. + // If the request was timed out, we want to continue the retry + // process. Otherwise, return the canceled error. + return timeoutErr || + (errStr != "net/http: request canceled" && + errStr != "net/http: request canceled while waiting for connection") + +} + +// SanitizeHostForHeader removes default port from host and updates request.Host +func SanitizeHostForHeader(r *http.Request) { + host := getHost(r) + port := portOnly(host) + if port != "" && isDefaultPort(r.URL.Scheme, port) { + r.Host = stripPort(host) + } +} + +// Returns host from request +func getHost(r *http.Request) string { + if r.Host != "" { + return r.Host + } + + return r.URL.Host +} + +// Hostname returns u.Host, without any port number. +// +// If Host is an IPv6 literal with a port number, Hostname returns the +// IPv6 literal without the square brackets. IPv6 literals may include +// a zone identifier. +// +// Copied from the Go 1.8 standard library (net/url) +func stripPort(hostport string) string { + colon := strings.IndexByte(hostport, ':') + if colon == -1 { + return hostport + } + if i := strings.IndexByte(hostport, ']'); i != -1 { + return strings.TrimPrefix(hostport[:i], "[") + } + return hostport[:colon] +} + +// Port returns the port part of u.Host, without the leading colon. +// If u.Host doesn't contain a port, Port returns an empty string. +// +// Copied from the Go 1.8 standard library (net/url) +func portOnly(hostport string) string { + colon := strings.IndexByte(hostport, ':') + if colon == -1 { + return "" + } + if i := strings.Index(hostport, "]:"); i != -1 { + return hostport[i+len("]:"):] + } + if strings.Contains(hostport, "]") { + return "" + } + return hostport[colon+len(":"):] +} + +// Returns true if the specified URI is using the standard port +// (i.e. port 80 for HTTP URIs or 443 for HTTPS URIs) +func isDefaultPort(scheme, port string) bool { + if port == "" { + return true + } + + lowerCaseScheme := strings.ToLower(scheme) + if (lowerCaseScheme == "http" && port == "80") || (lowerCaseScheme == "https" && port == "443") { + return true + } + + return false +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_5_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_5_test.go new file mode 100644 index 0000000..91b4e7b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_5_test.go @@ -0,0 +1,11 @@ +// +build !go1.6 + +package request_test + +import ( + "errors" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +var errTimeout = awserr.New("foo", "bar", errors.New("net/http: request canceled Timeout")) diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_6_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_6_test.go new file mode 100644 index 0000000..d0314ab --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_6_test.go @@ -0,0 +1,51 @@ +// +build go1.6 + +package request_test + +import ( + "errors" + "testing" + + "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/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/defaults" + "github.com/aws/aws-sdk-go/aws/request" +) + +// go version 1.4 and 1.5 do not return an error. Version 1.5 will url encode +// the uri while 1.4 will not +func TestRequestInvalidEndpoint(t *testing.T) { + endpoint := "http://localhost:90 " + + r := request.New( + aws.Config{}, + metadata.ClientInfo{Endpoint: endpoint}, + defaults.Handlers(), + client.DefaultRetryer{}, + &request.Operation{}, + nil, + nil, + ) + + assert.Error(t, r.Error) +} + +type timeoutErr struct { + error +} + +var errTimeout = awserr.New("foo", "bar", &timeoutErr{ + errors.New("net/http: request canceled"), +}) + +func (e *timeoutErr) Timeout() bool { + return true +} + +func (e *timeoutErr) Temporary() bool { + return true +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go new file mode 100644 index 0000000..869b97a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go @@ -0,0 +1,39 @@ +// +build !go1.8 + +package request + +import "io" + +// NoBody is an io.ReadCloser with no bytes. Read always returns EOF +// and Close always returns nil. It can be used in an outgoing client +// request to explicitly signal that a request has zero bytes. +// An alternative, however, is to simply set Request.Body to nil. +// +// Copy of Go 1.8 NoBody type from net/http/http.go +type noBody struct{} + +func (noBody) Read([]byte) (int, error) { return 0, io.EOF } +func (noBody) Close() error { return nil } +func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil } + +// NoBody is an empty reader that will trigger the Go HTTP client to not include +// and body in the HTTP request. +var NoBody = noBody{} + +// ResetBody rewinds the request body back to its starting position, and +// set's the HTTP Request body reference. When the body is read prior +// to being sent in the HTTP request it will need to be rewound. +// +// ResetBody will automatically be called by the SDK's build handler, but if +// the request is being used directly ResetBody must be called before the request +// is Sent. SetStringBody, SetBufferBody, and SetReaderBody will automatically +// call ResetBody. +func (r *Request) ResetBody() { + body, err := r.getNextRequestBody() + if err != nil { + r.Error = err + return + } + + r.HTTPRequest.Body = body +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7_test.go new file mode 100644 index 0000000..ca6150c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7_test.go @@ -0,0 +1,24 @@ +// +build !go1.8 + +package request + +import ( + "net/http" + "strings" + "testing" +) + +func TestResetBody_WithEmptyBody(t *testing.T) { + r := Request{ + HTTPRequest: &http.Request{}, + } + + reader := strings.NewReader("") + r.Body = reader + + r.ResetBody() + + if a, e := r.HTTPRequest.Body, (noBody{}); a != e { + t.Errorf("expected request body to be set to reader, got %#v", r.HTTPRequest.Body) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go new file mode 100644 index 0000000..c32fc69 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go @@ -0,0 +1,33 @@ +// +build go1.8 + +package request + +import ( + "net/http" +) + +// NoBody is a http.NoBody reader instructing Go HTTP client to not include +// and body in the HTTP request. +var NoBody = http.NoBody + +// ResetBody rewinds the request body back to its starting position, and +// set's the HTTP Request body reference. When the body is read prior +// to being sent in the HTTP request it will need to be rewound. +// +// ResetBody will automatically be called by the SDK's build handler, but if +// the request is being used directly ResetBody must be called before the request +// is Sent. SetStringBody, SetBufferBody, and SetReaderBody will automatically +// call ResetBody. +// +// Will also set the Go 1.8's http.Request.GetBody member to allow retrying +// PUT/POST redirects. +func (r *Request) ResetBody() { + body, err := r.getNextRequestBody() + if err != nil { + r.Error = err + return + } + + r.HTTPRequest.Body = body + r.HTTPRequest.GetBody = r.getNextRequestBody +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8_test.go new file mode 100644 index 0000000..8f3b0f0 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8_test.go @@ -0,0 +1,85 @@ +// +build go1.8 + +package request_test + +import ( + "bytes" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/awstesting/unit" +) + +func TestResetBody_WithEmptyBody(t *testing.T) { + r := request.Request{ + HTTPRequest: &http.Request{}, + } + + reader := strings.NewReader("") + r.Body = reader + + r.ResetBody() + + if a, e := r.HTTPRequest.Body, http.NoBody; a != e { + t.Errorf("expected request body to be set to reader, got %#v", + r.HTTPRequest.Body) + } +} + +func TestRequest_FollowPUTRedirects(t *testing.T) { + const bodySize = 1024 + + redirectHit := 0 + endpointHit := 0 + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/redirect-me": + u := *r.URL + u.Path = "/endpoint" + w.Header().Set("Location", u.String()) + w.WriteHeader(307) + redirectHit++ + case "/endpoint": + b := bytes.Buffer{} + io.Copy(&b, r.Body) + r.Body.Close() + if e, a := bodySize, b.Len(); e != a { + t.Fatalf("expect %d body size, got %d", e, a) + } + endpointHit++ + default: + t.Fatalf("unexpected endpoint used, %q", r.URL.String()) + } + })) + + svc := awstesting.NewClient(&aws.Config{ + Region: unit.Session.Config.Region, + DisableSSL: aws.Bool(true), + Endpoint: aws.String(server.URL), + }) + + req := svc.NewRequest(&request.Operation{ + Name: "Operation", + HTTPMethod: "PUT", + HTTPPath: "/redirect-me", + }, &struct{}{}, &struct{}{}) + req.SetReaderBody(bytes.NewReader(make([]byte, bodySize))) + + err := req.Send() + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if e, a := 1, redirectHit; e != a { + t.Errorf("expect %d redirect hits, got %d", e, a) + } + if e, a := 1, endpointHit; e != a { + t.Errorf("expect %d endpoint hits, got %d", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go new file mode 100644 index 0000000..a7365cd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go @@ -0,0 +1,14 @@ +// +build go1.7 + +package request + +import "github.com/aws/aws-sdk-go/aws" + +// setContext updates the Request to use the passed in context for cancellation. +// Context will also be used for request retry delay. +// +// Creates shallow copy of the http.Request with the WithContext method. +func setRequestContext(r *Request, ctx aws.Context) { + r.context = ctx + r.HTTPRequest = r.HTTPRequest.WithContext(ctx) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go new file mode 100644 index 0000000..307fa07 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go @@ -0,0 +1,14 @@ +// +build !go1.7 + +package request + +import "github.com/aws/aws-sdk-go/aws" + +// setContext updates the Request to use the passed in context for cancellation. +// Context will also be used for request retry delay. +// +// Creates shallow copy of the http.Request with the WithContext method. +func setRequestContext(r *Request, ctx aws.Context) { + r.context = ctx + r.HTTPRequest.Cancel = ctx.Done() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_test.go new file mode 100644 index 0000000..2af2867 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_test.go @@ -0,0 +1,46 @@ +package request_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws/corehandlers" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/awstesting" +) + +func TestRequest_SetContext(t *testing.T) { + svc := awstesting.NewClient() + svc.Handlers.Clear() + svc.Handlers.Send.PushBackNamed(corehandlers.SendHandler) + + r := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) + ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})} + r.SetContext(ctx) + + ctx.Error = fmt.Errorf("context canceled") + close(ctx.DoneCh) + + err := r.Send() + if err == nil { + t.Fatalf("expected error, got none") + } + + // Only check against canceled because go 1.6 will not use the context's + // Err(). + if e, a := "canceled", err.Error(); !strings.Contains(a, e) { + t.Errorf("expect %q to be in %q, but was not", e, a) + } +} + +func TestRequest_SetContextPanic(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatalf("expect SetContext to panic, did not") + } + }() + r := &request.Request{} + + r.SetContext(nil) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_internal_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_internal_test.go new file mode 100644 index 0000000..966f934 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_internal_test.go @@ -0,0 +1,27 @@ +package request + +import ( + "testing" +) + +func TestCopy(t *testing.T) { + handlers := Handlers{} + op := &Operation{} + op.HTTPMethod = "Foo" + req := &Request{} + req.Operation = op + req.Handlers = handlers + + r := req.copy() + + if r == req { + t.Fatal("expect request pointer copy to be different") + } + if r.Operation == req.Operation { + t.Errorf("expect request operation pointer to be different") + } + + if e, a := req.Operation.HTTPMethod, r.Operation.HTTPMethod; e != a { + t.Errorf("expect %q http method, got %q", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go new file mode 100644 index 0000000..59de673 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go @@ -0,0 +1,236 @@ +package request + +import ( + "reflect" + "sync/atomic" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" +) + +// A Pagination provides paginating of SDK API operations which are paginatable. +// Generally you should not use this type directly, but use the "Pages" API +// operations method to automatically perform pagination for you. Such as, +// "S3.ListObjectsPages", and "S3.ListObjectsPagesWithContext" methods. +// +// Pagination differs from a Paginator type in that pagination is the type that +// does the pagination between API operations, and Paginator defines the +// configuration that will be used per page request. +// +// cont := true +// for p.Next() && cont { +// data := p.Page().(*s3.ListObjectsOutput) +// // process the page's data +// } +// return p.Err() +// +// See service client API operation Pages methods for examples how the SDK will +// use the Pagination type. +type Pagination struct { + // Function to return a Request value for each pagination request. + // Any configuration or handlers that need to be applied to the request + // prior to getting the next page should be done here before the request + // returned. + // + // NewRequest should always be built from the same API operations. It is + // undefined if different API operations are returned on subsequent calls. + NewRequest func() (*Request, error) + + started bool + nextTokens []interface{} + + err error + curPage interface{} +} + +// HasNextPage will return true if Pagination is able to determine that the API +// operation has additional pages. False will be returned if there are no more +// pages remaining. +// +// Will always return true if Next has not been called yet. +func (p *Pagination) HasNextPage() bool { + return !(p.started && len(p.nextTokens) == 0) +} + +// Err returns the error Pagination encountered when retrieving the next page. +func (p *Pagination) Err() error { + return p.err +} + +// Page returns the current page. Page should only be called after a successful +// call to Next. It is undefined what Page will return if Page is called after +// Next returns false. +func (p *Pagination) Page() interface{} { + return p.curPage +} + +// Next will attempt to retrieve the next page for the API operation. When a page +// is retrieved true will be returned. If the page cannot be retrieved, or there +// are no more pages false will be returned. +// +// Use the Page method to retrieve the current page data. The data will need +// to be cast to the API operation's output type. +// +// Use the Err method to determine if an error occurred if Page returns false. +func (p *Pagination) Next() bool { + if !p.HasNextPage() { + return false + } + + req, err := p.NewRequest() + if err != nil { + p.err = err + return false + } + + if p.started { + for i, intok := range req.Operation.InputTokens { + awsutil.SetValueAtPath(req.Params, intok, p.nextTokens[i]) + } + } + p.started = true + + err = req.Send() + if err != nil { + p.err = err + return false + } + + p.nextTokens = req.nextPageTokens() + p.curPage = req.Data + + return true +} + +// A Paginator is the configuration data that defines how an API operation +// should be paginated. This type is used by the API service models to define +// the generated pagination config for service APIs. +// +// The Pagination type is what provides iterating between pages of an API. It +// is only used to store the token metadata the SDK should use for performing +// pagination. +type Paginator struct { + InputTokens []string + OutputTokens []string + LimitToken string + TruncationToken string +} + +// nextPageTokens returns the tokens to use when asking for the next page of data. +func (r *Request) nextPageTokens() []interface{} { + if r.Operation.Paginator == nil { + return nil + } + if r.Operation.TruncationToken != "" { + tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken) + if len(tr) == 0 { + return nil + } + + switch v := tr[0].(type) { + case *bool: + if !aws.BoolValue(v) { + return nil + } + case bool: + if v == false { + return nil + } + } + } + + tokens := []interface{}{} + tokenAdded := false + for _, outToken := range r.Operation.OutputTokens { + v, _ := awsutil.ValuesAtPath(r.Data, outToken) + if len(v) > 0 { + tokens = append(tokens, v[0]) + tokenAdded = true + } else { + tokens = append(tokens, nil) + } + } + if !tokenAdded { + return nil + } + + return tokens +} + +// Ensure a deprecated item is only logged once instead of each time its used. +func logDeprecatedf(logger aws.Logger, flag *int32, msg string) { + if logger == nil { + return + } + if atomic.CompareAndSwapInt32(flag, 0, 1) { + logger.Log(msg) + } +} + +var ( + logDeprecatedHasNextPage int32 + logDeprecatedNextPage int32 + logDeprecatedEachPage int32 +) + +// HasNextPage returns true if this request has more pages of data available. +// +// Deprecated Use Pagination type for configurable pagination of API operations +func (r *Request) HasNextPage() bool { + logDeprecatedf(r.Config.Logger, &logDeprecatedHasNextPage, + "Request.HasNextPage deprecated. Use Pagination type for configurable pagination of API operations") + + return len(r.nextPageTokens()) > 0 +} + +// NextPage returns a new Request that can be executed to return the next +// page of result data. Call .Send() on this request to execute it. +// +// Deprecated Use Pagination type for configurable pagination of API operations +func (r *Request) NextPage() *Request { + logDeprecatedf(r.Config.Logger, &logDeprecatedNextPage, + "Request.NextPage deprecated. Use Pagination type for configurable pagination of API operations") + + tokens := r.nextPageTokens() + if len(tokens) == 0 { + return nil + } + + data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface() + nr := New(r.Config, r.ClientInfo, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data) + for i, intok := range nr.Operation.InputTokens { + awsutil.SetValueAtPath(nr.Params, intok, tokens[i]) + } + return nr +} + +// EachPage iterates over each page of a paginated request object. The fn +// parameter should be a function with the following sample signature: +// +// func(page *T, lastPage bool) bool { +// return true // return false to stop iterating +// } +// +// Where "T" is the structure type matching the output structure of the given +// operation. For example, a request object generated by +// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput +// as the structure "T". The lastPage value represents whether the page is +// the last page of data or not. The return value of this function should +// return true to keep iterating or false to stop. +// +// Deprecated Use Pagination type for configurable pagination of API operations +func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error { + logDeprecatedf(r.Config.Logger, &logDeprecatedEachPage, + "Request.EachPage deprecated. Use Pagination type for configurable pagination of API operations") + + for page := r; page != nil; page = page.NextPage() { + if err := page.Send(); err != nil { + return err + } + if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage { + return page.Error + } + } + + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go new file mode 100644 index 0000000..73a95ba --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go @@ -0,0 +1,604 @@ +package request_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/aws/aws-sdk-go/aws" + "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/dynamodb" + "github.com/aws/aws-sdk-go/service/route53" + "github.com/aws/aws-sdk-go/service/s3" +) + +// Use DynamoDB methods for simplicity +func TestPaginationQueryPage(t *testing.T) { + db := dynamodb.New(unit.Session) + tokens, pages, numPages, gotToEnd := []map[string]*dynamodb.AttributeValue{}, []map[string]*dynamodb.AttributeValue{}, 0, false + + reqNum := 0 + resps := []*dynamodb.QueryOutput{ + { + LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}}, + Count: aws.Int64(1), + Items: []map[string]*dynamodb.AttributeValue{ + { + "key": {S: aws.String("key1")}, + }, + }, + }, + { + LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}}, + Count: aws.Int64(1), + Items: []map[string]*dynamodb.AttributeValue{ + { + "key": {S: aws.String("key2")}, + }, + }, + }, + { + LastEvaluatedKey: map[string]*dynamodb.AttributeValue{}, + Count: aws.Int64(1), + Items: []map[string]*dynamodb.AttributeValue{ + { + "key": {S: aws.String("key3")}, + }, + }, + }, + } + + db.Handlers.Send.Clear() // mock sending + db.Handlers.Unmarshal.Clear() + db.Handlers.UnmarshalMeta.Clear() + db.Handlers.ValidateResponse.Clear() + db.Handlers.Build.PushBack(func(r *request.Request) { + in := r.Params.(*dynamodb.QueryInput) + if in == nil { + tokens = append(tokens, nil) + } else if len(in.ExclusiveStartKey) != 0 { + tokens = append(tokens, in.ExclusiveStartKey) + } + }) + db.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = resps[reqNum] + reqNum++ + }) + + params := &dynamodb.QueryInput{ + Limit: aws.Int64(2), + TableName: aws.String("tablename"), + } + err := db.QueryPages(params, func(p *dynamodb.QueryOutput, last bool) bool { + numPages++ + for _, item := range p.Items { + pages = append(pages, item) + } + if last { + if gotToEnd { + assert.Fail(t, "last=true happened twice") + } + gotToEnd = true + } + return true + }) + assert.Nil(t, err) + + assert.Equal(t, + []map[string]*dynamodb.AttributeValue{ + {"key": {S: aws.String("key1")}}, + {"key": {S: aws.String("key2")}}, + }, tokens) + assert.Equal(t, + []map[string]*dynamodb.AttributeValue{ + {"key": {S: aws.String("key1")}}, + {"key": {S: aws.String("key2")}}, + {"key": {S: aws.String("key3")}}, + }, pages) + assert.Equal(t, 3, numPages) + assert.True(t, gotToEnd) + assert.Nil(t, params.ExclusiveStartKey) +} + +// Use DynamoDB methods for simplicity +func TestPagination(t *testing.T) { + db := dynamodb.New(unit.Session) + tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false + + reqNum := 0 + resps := []*dynamodb.ListTablesOutput{ + {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, + {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, + {TableNames: []*string{aws.String("Table5")}}, + } + + db.Handlers.Send.Clear() // mock sending + db.Handlers.Unmarshal.Clear() + db.Handlers.UnmarshalMeta.Clear() + db.Handlers.ValidateResponse.Clear() + db.Handlers.Build.PushBack(func(r *request.Request) { + in := r.Params.(*dynamodb.ListTablesInput) + if in == nil { + tokens = append(tokens, "") + } else if in.ExclusiveStartTableName != nil { + tokens = append(tokens, *in.ExclusiveStartTableName) + } + }) + db.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = resps[reqNum] + reqNum++ + }) + + params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} + err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { + numPages++ + for _, t := range p.TableNames { + pages = append(pages, *t) + } + if last { + if gotToEnd { + assert.Fail(t, "last=true happened twice") + } + gotToEnd = true + } + return true + }) + + assert.Equal(t, []string{"Table2", "Table4"}, tokens) + assert.Equal(t, []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages) + assert.Equal(t, 3, numPages) + assert.True(t, gotToEnd) + assert.Nil(t, err) + assert.Nil(t, params.ExclusiveStartTableName) +} + +// Use DynamoDB methods for simplicity +func TestPaginationEachPage(t *testing.T) { + db := dynamodb.New(unit.Session) + tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false + + reqNum := 0 + resps := []*dynamodb.ListTablesOutput{ + {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, + {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, + {TableNames: []*string{aws.String("Table5")}}, + } + + db.Handlers.Send.Clear() // mock sending + db.Handlers.Unmarshal.Clear() + db.Handlers.UnmarshalMeta.Clear() + db.Handlers.ValidateResponse.Clear() + db.Handlers.Build.PushBack(func(r *request.Request) { + in := r.Params.(*dynamodb.ListTablesInput) + if in == nil { + tokens = append(tokens, "") + } else if in.ExclusiveStartTableName != nil { + tokens = append(tokens, *in.ExclusiveStartTableName) + } + }) + db.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = resps[reqNum] + reqNum++ + }) + + params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} + req, _ := db.ListTablesRequest(params) + err := req.EachPage(func(p interface{}, last bool) bool { + numPages++ + for _, t := range p.(*dynamodb.ListTablesOutput).TableNames { + pages = append(pages, *t) + } + if last { + if gotToEnd { + assert.Fail(t, "last=true happened twice") + } + gotToEnd = true + } + + return true + }) + + assert.Equal(t, []string{"Table2", "Table4"}, tokens) + assert.Equal(t, []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages) + assert.Equal(t, 3, numPages) + assert.True(t, gotToEnd) + assert.Nil(t, err) +} + +// Use DynamoDB methods for simplicity +func TestPaginationEarlyExit(t *testing.T) { + db := dynamodb.New(unit.Session) + numPages, gotToEnd := 0, false + + reqNum := 0 + resps := []*dynamodb.ListTablesOutput{ + {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, + {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, + {TableNames: []*string{aws.String("Table5")}}, + } + + db.Handlers.Send.Clear() // mock sending + db.Handlers.Unmarshal.Clear() + db.Handlers.UnmarshalMeta.Clear() + db.Handlers.ValidateResponse.Clear() + db.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = resps[reqNum] + reqNum++ + }) + + params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} + err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { + numPages++ + if numPages == 2 { + return false + } + if last { + if gotToEnd { + assert.Fail(t, "last=true happened twice") + } + gotToEnd = true + } + return true + }) + + assert.Equal(t, 2, numPages) + assert.False(t, gotToEnd) + assert.Nil(t, err) +} + +func TestSkipPagination(t *testing.T) { + client := s3.New(unit.Session) + client.Handlers.Send.Clear() // mock sending + client.Handlers.Unmarshal.Clear() + client.Handlers.UnmarshalMeta.Clear() + client.Handlers.ValidateResponse.Clear() + client.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = &s3.HeadBucketOutput{} + }) + + req, _ := client.HeadBucketRequest(&s3.HeadBucketInput{Bucket: aws.String("bucket")}) + + numPages, gotToEnd := 0, false + req.EachPage(func(p interface{}, last bool) bool { + numPages++ + if last { + gotToEnd = true + } + return true + }) + assert.Equal(t, 1, numPages) + assert.True(t, gotToEnd) +} + +// Use S3 for simplicity +func TestPaginationTruncation(t *testing.T) { + client := s3.New(unit.Session) + + reqNum := 0 + resps := []*s3.ListObjectsOutput{ + {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key1")}}}, + {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key2")}}}, + {IsTruncated: aws.Bool(false), Contents: []*s3.Object{{Key: aws.String("Key3")}}}, + {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key4")}}}, + } + + client.Handlers.Send.Clear() // mock sending + client.Handlers.Unmarshal.Clear() + client.Handlers.UnmarshalMeta.Clear() + client.Handlers.ValidateResponse.Clear() + client.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = resps[reqNum] + reqNum++ + }) + + params := &s3.ListObjectsInput{Bucket: aws.String("bucket")} + + results := []string{} + err := client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { + results = append(results, *p.Contents[0].Key) + return true + }) + + assert.Equal(t, []string{"Key1", "Key2", "Key3"}, results) + assert.Nil(t, err) + + // Try again without truncation token at all + reqNum = 0 + resps[1].IsTruncated = nil + resps[2].IsTruncated = aws.Bool(true) + results = []string{} + err = client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { + results = append(results, *p.Contents[0].Key) + return true + }) + + assert.Equal(t, []string{"Key1", "Key2"}, results) + assert.Nil(t, err) +} + +func TestPaginationNilToken(t *testing.T) { + client := route53.New(unit.Session) + + reqNum := 0 + resps := []*route53.ListResourceRecordSetsOutput{ + { + ResourceRecordSets: []*route53.ResourceRecordSet{ + {Name: aws.String("first.example.com.")}, + }, + IsTruncated: aws.Bool(true), + NextRecordName: aws.String("second.example.com."), + NextRecordType: aws.String("MX"), + NextRecordIdentifier: aws.String("second"), + MaxItems: aws.String("1"), + }, + { + ResourceRecordSets: []*route53.ResourceRecordSet{ + {Name: aws.String("second.example.com.")}, + }, + IsTruncated: aws.Bool(true), + NextRecordName: aws.String("third.example.com."), + NextRecordType: aws.String("MX"), + MaxItems: aws.String("1"), + }, + { + ResourceRecordSets: []*route53.ResourceRecordSet{ + {Name: aws.String("third.example.com.")}, + }, + IsTruncated: aws.Bool(false), + MaxItems: aws.String("1"), + }, + } + client.Handlers.Send.Clear() // mock sending + client.Handlers.Unmarshal.Clear() + client.Handlers.UnmarshalMeta.Clear() + client.Handlers.ValidateResponse.Clear() + + idents := []string{} + client.Handlers.Build.PushBack(func(r *request.Request) { + p := r.Params.(*route53.ListResourceRecordSetsInput) + idents = append(idents, aws.StringValue(p.StartRecordIdentifier)) + + }) + client.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = resps[reqNum] + reqNum++ + }) + + params := &route53.ListResourceRecordSetsInput{ + HostedZoneId: aws.String("id-zone"), + } + + results := []string{} + err := client.ListResourceRecordSetsPages(params, func(p *route53.ListResourceRecordSetsOutput, last bool) bool { + results = append(results, *p.ResourceRecordSets[0].Name) + return true + }) + + assert.NoError(t, err) + assert.Equal(t, []string{"", "second", ""}, idents) + assert.Equal(t, []string{"first.example.com.", "second.example.com.", "third.example.com."}, results) +} + +func TestPaginationNilInput(t *testing.T) { + // Code generation doesn't have a great way to verify the code is correct + // other than being run via unit tests in the SDK. This should be fixed + // So code generation can be validated independently. + + client := s3.New(unit.Session) + client.Handlers.Validate.Clear() + client.Handlers.Send.Clear() // mock sending + client.Handlers.Unmarshal.Clear() + client.Handlers.UnmarshalMeta.Clear() + client.Handlers.ValidateResponse.Clear() + client.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = &s3.ListObjectsOutput{} + }) + + gotToEnd := false + numPages := 0 + err := client.ListObjectsPages(nil, func(p *s3.ListObjectsOutput, last bool) bool { + numPages++ + if last { + gotToEnd = true + } + return true + }) + + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } + if e, a := 1, numPages; e != a { + t.Errorf("expect %d number pages but got %d", e, a) + } + if !gotToEnd { + t.Errorf("expect to of gotten to end, did not") + } +} + +func TestPaginationWithContextNilInput(t *testing.T) { + // Code generation doesn't have a great way to verify the code is correct + // other than being run via unit tests in the SDK. This should be fixed + // So code generation can be validated independently. + + client := s3.New(unit.Session) + client.Handlers.Validate.Clear() + client.Handlers.Send.Clear() // mock sending + client.Handlers.Unmarshal.Clear() + client.Handlers.UnmarshalMeta.Clear() + client.Handlers.ValidateResponse.Clear() + client.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = &s3.ListObjectsOutput{} + }) + + gotToEnd := false + numPages := 0 + ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})} + err := client.ListObjectsPagesWithContext(ctx, nil, func(p *s3.ListObjectsOutput, last bool) bool { + numPages++ + if last { + gotToEnd = true + } + return true + }) + + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } + if e, a := 1, numPages; e != a { + t.Errorf("expect %d number pages but got %d", e, a) + } + if !gotToEnd { + t.Errorf("expect to of gotten to end, did not") + } +} + +type testPageInput struct { + NextToken string +} +type testPageOutput struct { + Value string + NextToken *string +} + +func TestPagination_Standalone(t *testing.T) { + expect := []struct { + Value, PrevToken, NextToken string + }{ + {"FirstValue", "InitalToken", "FirstToken"}, + {"SecondValue", "FirstToken", "SecondToken"}, + {"ThirdValue", "SecondToken", ""}, + } + input := testPageInput{ + NextToken: expect[0].PrevToken, + } + + c := awstesting.NewClient() + i := 0 + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + r := c.NewRequest( + &request.Operation{ + Name: "Operation", + Paginator: &request.Paginator{ + InputTokens: []string{"NextToken"}, + OutputTokens: []string{"NextToken"}, + }, + }, + &input, &testPageOutput{}, + ) + // Setup handlers for testing + r.Handlers.Clear() + r.Handlers.Build.PushBack(func(req *request.Request) { + in := req.Params.(*testPageInput) + if e, a := expect[i].PrevToken, in.NextToken; e != a { + t.Errorf("%d, expect NextToken input %q, got %q", i, e, a) + } + }) + r.Handlers.Unmarshal.PushBack(func(req *request.Request) { + out := &testPageOutput{ + Value: expect[i].Value, + } + if len(expect[i].NextToken) > 0 { + out.NextToken = aws.String(expect[i].NextToken) + } + req.Data = out + }) + return r, nil + }, + } + + for p.Next() { + data := p.Page().(*testPageOutput) + + if e, a := expect[i].Value, data.Value; e != a { + t.Errorf("%d, expect Value to be %q, got %q", i, e, a) + } + if e, a := expect[i].NextToken, aws.StringValue(data.NextToken); e != a { + t.Errorf("%d, expect NextToken to be %q, got %q", i, e, a) + } + + i++ + } + if e, a := len(expect), i; e != a { + t.Errorf("expected to process %d pages, did %d", e, a) + } + if err := p.Err(); err != nil { + t.Fatalf("%d, expected no error, got %v", i, err) + } +} + +// Benchmarks +var benchResps = []*dynamodb.ListTablesOutput{ + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE"), aws.String("NXT")}, LastEvaluatedTableName: aws.String("NXT")}, + {TableNames: []*string{aws.String("TABLE")}}, +} + +var benchDb = func() *dynamodb.DynamoDB { + db := dynamodb.New(unit.Session) + db.Handlers.Send.Clear() // mock sending + db.Handlers.Unmarshal.Clear() + db.Handlers.UnmarshalMeta.Clear() + db.Handlers.ValidateResponse.Clear() + return db +} + +func BenchmarkCodegenIterator(b *testing.B) { + reqNum := 0 + db := benchDb() + db.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = benchResps[reqNum] + reqNum++ + }) + + input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} + iter := func(fn func(*dynamodb.ListTablesOutput, bool) bool) error { + page, _ := db.ListTablesRequest(input) + for ; page != nil; page = page.NextPage() { + page.Send() + out := page.Data.(*dynamodb.ListTablesOutput) + if result := fn(out, !page.HasNextPage()); page.Error != nil || !result { + return page.Error + } + } + return nil + } + + for i := 0; i < b.N; i++ { + reqNum = 0 + iter(func(p *dynamodb.ListTablesOutput, last bool) bool { + return true + }) + } +} + +func BenchmarkEachPageIterator(b *testing.B) { + reqNum := 0 + db := benchDb() + db.Handlers.Unmarshal.PushBack(func(r *request.Request) { + r.Data = benchResps[reqNum] + reqNum++ + }) + + input := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} + for i := 0; i < b.N; i++ { + reqNum = 0 + req, _ := db.ListTablesRequest(input) + req.EachPage(func(p interface{}, last bool) bool { + return true + }) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_resetbody_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_resetbody_test.go new file mode 100644 index 0000000..4a91724 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_resetbody_test.go @@ -0,0 +1,58 @@ +package request + +import ( + "bytes" + "net/http" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" +) + +func TestResetBody_WithBodyContents(t *testing.T) { + r := Request{ + HTTPRequest: &http.Request{}, + } + + reader := strings.NewReader("abc") + r.Body = reader + + r.ResetBody() + + if v, ok := r.HTTPRequest.Body.(*offsetReader); !ok || v == nil { + t.Errorf("expected request body to be set to reader, got %#v", + r.HTTPRequest.Body) + } +} + +func TestResetBody_ExcludeUnseekableBodyByMethod(t *testing.T) { + cases := []struct { + Method string + IsNoBody bool + }{ + {"GET", true}, + {"HEAD", true}, + {"DELETE", true}, + {"PUT", false}, + {"PATCH", false}, + {"POST", false}, + } + + reader := aws.ReadSeekCloser(bytes.NewBuffer([]byte("abc"))) + + for i, c := range cases { + r := Request{ + HTTPRequest: &http.Request{}, + Operation: &Operation{ + HTTPMethod: c.Method, + }, + } + + r.SetReaderBody(reader) + + if a, e := r.HTTPRequest.Body == NoBody, c.IsNoBody; a != e { + t.Errorf("%d, expect body to be set to noBody(%t), but was %t", i, e, a) + } + } + +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_test.go new file mode 100644 index 0000000..151cbf3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_test.go @@ -0,0 +1,1004 @@ +package request_test + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "net/url" + "reflect" + "runtime" + "strconv" + "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/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/credentials" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" + "github.com/aws/aws-sdk-go/private/protocol/rest" + "github.com/aws/aws-sdk-go/aws/defaults" +) + +type testData struct { + Data string +} + +func body(str string) io.ReadCloser { + return ioutil.NopCloser(bytes.NewReader([]byte(str))) +} + +func unmarshal(req *request.Request) { + defer req.HTTPResponse.Body.Close() + if req.Data != nil { + json.NewDecoder(req.HTTPResponse.Body).Decode(req.Data) + } + return +} + +func unmarshalError(req *request.Request) { + bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body) + if err != nil { + req.Error = awserr.New("UnmarshaleError", req.HTTPResponse.Status, err) + return + } + if len(bodyBytes) == 0 { + req.Error = awserr.NewRequestFailure( + awserr.New("UnmarshaleError", req.HTTPResponse.Status, fmt.Errorf("empty body")), + req.HTTPResponse.StatusCode, + "", + ) + return + } + var jsonErr jsonErrorResponse + if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { + req.Error = awserr.New("UnmarshaleError", "JSON unmarshal", err) + return + } + req.Error = awserr.NewRequestFailure( + awserr.New(jsonErr.Code, jsonErr.Message, nil), + req.HTTPResponse.StatusCode, + "", + ) +} + +type jsonErrorResponse struct { + Code string `json:"__type"` + Message string `json:"message"` +} + +// test that retries occur for 5xx status codes +func TestRequestRecoverRetry5xx(t *testing.T) { + reqNum := 0 + reqs := []http.Response{ + {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, + {StatusCode: 501, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, + {StatusCode: 200, Body: body(`{"data":"valid"}`)}, + } + + s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &reqs[reqNum] + reqNum++ + }) + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + err := r.Send() + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } + if e, a := 2, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + if e, a := "valid", out.Data; e != a { + t.Errorf("expect %q output got %q", e, a) + } +} + +// test that retries occur for 4xx status codes with a response type that can be retried - see `shouldRetry` +func TestRequestRecoverRetry4xxRetryable(t *testing.T) { + reqNum := 0 + reqs := []http.Response{ + {StatusCode: 400, Body: body(`{"__type":"Throttling","message":"Rate exceeded."}`)}, + {StatusCode: 400, Body: body(`{"__type":"ProvisionedThroughputExceededException","message":"Rate exceeded."}`)}, + {StatusCode: 429, Body: body(`{"__type":"FooException","message":"Rate exceeded."}`)}, + {StatusCode: 200, Body: body(`{"data":"valid"}`)}, + } + + s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &reqs[reqNum] + reqNum++ + }) + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + err := r.Send() + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } + if e, a := 3, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + if e, a := "valid", out.Data; e != a { + t.Errorf("expect %q output got %q", e, a) + } +} + +// test that retries don't occur for 4xx status codes with a response type that can't be retried +func TestRequest4xxUnretryable(t *testing.T) { + s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &http.Response{StatusCode: 401, Body: body(`{"__type":"SignatureDoesNotMatch","message":"Signature does not match."}`)} + }) + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + err := r.Send() + if err == nil { + t.Fatalf("expect error, but did not get one") + } + aerr := err.(awserr.RequestFailure) + if e, a := 401, aerr.StatusCode(); e != a { + t.Errorf("expect %d status code, got %d", e, a) + } + if e, a := "SignatureDoesNotMatch", aerr.Code(); e != a { + t.Errorf("expect %q error code, got %q", e, a) + } + if e, a := "Signature does not match.", aerr.Message(); e != a { + t.Errorf("expect %q error message, got %q", e, a) + } + if e, a := 0, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } +} + +func TestRequestExhaustRetries(t *testing.T) { + delays := []time.Duration{} + sleepDelay := func(delay time.Duration) { + delays = append(delays, delay) + } + + reqNum := 0 + reqs := []http.Response{ + {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, + {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, + {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, + {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, + } + + s := awstesting.NewClient(aws.NewConfig().WithSleepDelay(sleepDelay)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &reqs[reqNum] + reqNum++ + }) + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) + err := r.Send() + if err == nil { + t.Fatalf("expect error, but did not get one") + } + aerr := err.(awserr.RequestFailure) + if e, a := 500, aerr.StatusCode(); e != a { + t.Errorf("expect %d status code, got %d", e, a) + } + if e, a := "UnknownError", aerr.Code(); e != a { + t.Errorf("expect %q error code, got %q", e, a) + } + if e, a := "An error occurred.", aerr.Message(); e != a { + t.Errorf("expect %q error message, got %q", e, a) + } + if e, a := 3, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + + expectDelays := []struct{ min, max time.Duration }{{30, 59}, {60, 118}, {120, 236}} + for i, v := range delays { + min := expectDelays[i].min * time.Millisecond + max := expectDelays[i].max * time.Millisecond + if !(min <= v && v <= max) { + t.Errorf("Expect delay to be within range, i:%d, v:%s, min:%s, max:%s", + i, v, min, max) + } + } +} + +// test that the request is retried after the credentials are expired. +func TestRequestRecoverExpiredCreds(t *testing.T) { + reqNum := 0 + reqs := []http.Response{ + {StatusCode: 400, Body: body(`{"__type":"ExpiredTokenException","message":"expired token"}`)}, + {StatusCode: 200, Body: body(`{"data":"valid"}`)}, + } + + s := awstesting.NewClient(&aws.Config{MaxRetries: aws.Int(10), Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "")}) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + + credExpiredBeforeRetry := false + credExpiredAfterRetry := false + + s.Handlers.AfterRetry.PushBack(func(r *request.Request) { + credExpiredAfterRetry = r.Config.Credentials.IsExpired() + }) + + s.Handlers.Sign.Clear() + s.Handlers.Sign.PushBack(func(r *request.Request) { + r.Config.Credentials.Get() + }) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &reqs[reqNum] + reqNum++ + }) + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + err := r.Send() + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if credExpiredBeforeRetry { + t.Errorf("Expect valid creds before retry check") + } + if !credExpiredAfterRetry { + t.Errorf("Expect expired creds after retry check") + } + if s.Config.Credentials.IsExpired() { + t.Errorf("Expect valid creds after cred expired recovery") + } + + if e, a := 1, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + if e, a := "valid", out.Data; e != a { + t.Errorf("expect %q output got %q", e, a) + } +} + +func TestMakeAddtoUserAgentHandler(t *testing.T) { + fn := request.MakeAddToUserAgentHandler("name", "version", "extra1", "extra2") + r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}} + r.HTTPRequest.Header.Set("User-Agent", "foo/bar") + fn(r) + + if e, a := "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent"); e != a { + t.Errorf("expect %q user agent, got %q", e, a) + } +} + +func TestMakeAddtoUserAgentFreeFormHandler(t *testing.T) { + fn := request.MakeAddToUserAgentFreeFormHandler("name/version (extra1; extra2)") + r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}} + r.HTTPRequest.Header.Set("User-Agent", "foo/bar") + fn(r) + + if e, a := "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent"); e != a { + t.Errorf("expect %q user agent, got %q", e, a) + } +} + +func TestRequestUserAgent(t *testing.T) { + s := awstesting.NewClient(&aws.Config{Region: aws.String("us-east-1")}) + // s.Handlers.Validate.Clear() + + req := s.NewRequest(&request.Operation{Name: "Operation"}, nil, &testData{}) + req.HTTPRequest.Header.Set("User-Agent", "foo/bar") + if err := req.Build(); err != nil { + t.Fatalf("expect no error, got %v", err) + } + + expectUA := fmt.Sprintf("foo/bar %s/%s (%s; %s; %s)", + aws.SDKName, aws.SDKVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH) + if e, a := expectUA, req.HTTPRequest.Header.Get("User-Agent"); e != a { + t.Errorf("expect %q user agent, got %q", e, a) + } +} + +func TestRequestThrottleRetries(t *testing.T) { + delays := []time.Duration{} + sleepDelay := func(delay time.Duration) { + delays = append(delays, delay) + } + + reqNum := 0 + reqs := []http.Response{ + {StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)}, + {StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)}, + {StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)}, + {StatusCode: 500, Body: body(`{"__type":"Throttling","message":"An error occurred."}`)}, + } + + s := awstesting.NewClient(aws.NewConfig().WithSleepDelay(sleepDelay)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &reqs[reqNum] + reqNum++ + }) + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) + err := r.Send() + if err == nil { + t.Fatalf("expect error, but did not get one") + } + aerr := err.(awserr.RequestFailure) + if e, a := 500, aerr.StatusCode(); e != a { + t.Errorf("expect %d status code, got %d", e, a) + } + if e, a := "Throttling", aerr.Code(); e != a { + t.Errorf("expect %q error code, got %q", e, a) + } + if e, a := "An error occurred.", aerr.Message(); e != a { + t.Errorf("expect %q error message, got %q", e, a) + } + if e, a := 3, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + + expectDelays := []struct{ min, max time.Duration }{{500, 999}, {1000, 1998}, {2000, 3996}} + for i, v := range delays { + min := expectDelays[i].min * time.Millisecond + max := expectDelays[i].max * time.Millisecond + if !(min <= v && v <= max) { + t.Errorf("Expect delay to be within range, i:%d, v:%s, min:%s, max:%s", + i, v, min, max) + } + } +} + +// test that retries occur for request timeouts when response.Body can be nil +func TestRequestRecoverTimeoutWithNilBody(t *testing.T) { + reqNum := 0 + reqs := []*http.Response{ + {StatusCode: 0, Body: nil}, // body can be nil when requests time out + {StatusCode: 200, Body: body(`{"data":"valid"}`)}, + } + errors := []error{ + errTimeout, nil, + } + + s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + s.Handlers.AfterRetry.Clear() // force retry on all errors + s.Handlers.AfterRetry.PushBack(func(r *request.Request) { + if r.Error != nil { + r.Error = nil + r.Retryable = aws.Bool(true) + r.RetryCount++ + } + }) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = reqs[reqNum] + r.Error = errors[reqNum] + reqNum++ + }) + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + err := r.Send() + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } + if e, a := 1, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + if e, a := "valid", out.Data; e != a { + t.Errorf("expect %q output got %q", e, a) + } +} + +func TestRequestRecoverTimeoutWithNilResponse(t *testing.T) { + reqNum := 0 + reqs := []*http.Response{ + nil, + {StatusCode: 200, Body: body(`{"data":"valid"}`)}, + } + errors := []error{ + errTimeout, + nil, + } + + s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10)) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + s.Handlers.AfterRetry.Clear() // force retry on all errors + s.Handlers.AfterRetry.PushBack(func(r *request.Request) { + if r.Error != nil { + r.Error = nil + r.Retryable = aws.Bool(true) + r.RetryCount++ + } + }) + s.Handlers.Send.Clear() // mock sending + s.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = reqs[reqNum] + r.Error = errors[reqNum] + reqNum++ + }) + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + err := r.Send() + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } + if e, a := 1, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + if e, a := "valid", out.Data; e != a { + t.Errorf("expect %q output got %q", e, a) + } +} + +func TestRequest_NoBody(t *testing.T) { + cases := []string{ + "GET", "HEAD", "DELETE", + "PUT", "POST", "PATCH", + } + + for i, c := range cases { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if v := r.TransferEncoding; len(v) > 0 { + t.Errorf("%d, expect no body sent with Transfer-Encoding, %v", i, v) + } + + outMsg := []byte(`{"Value": "abc"}`) + + if b, err := ioutil.ReadAll(r.Body); err != nil { + t.Fatalf("%d, expect no error reading request body, got %v", i, err) + } else if n := len(b); n > 0 { + t.Errorf("%d, expect no request body, got %d bytes", i, n) + } + + w.Header().Set("Content-Length", strconv.Itoa(len(outMsg))) + if _, err := w.Write(outMsg); err != nil { + t.Fatalf("%d, expect no error writing server response, got %v", i, err) + } + })) + + s := awstesting.NewClient(&aws.Config{ + Region: aws.String("mock-region"), + MaxRetries: aws.Int(0), + Endpoint: aws.String(server.URL), + DisableSSL: aws.Bool(true), + }) + s.Handlers.Build.PushBack(rest.Build) + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + + in := struct { + Bucket *string `location:"uri" locationName:"bucket"` + Key *string `location:"uri" locationName:"key"` + }{ + Bucket: aws.String("mybucket"), Key: aws.String("myKey"), + } + + out := struct { + Value *string + }{} + + r := s.NewRequest(&request.Operation{ + Name: "OpName", HTTPMethod: c, HTTPPath: "/{bucket}/{key+}", + }, &in, &out) + + if err := r.Send(); err != nil { + t.Fatalf("%d, expect no error sending request, got %v", i, err) + } + } +} + +func TestIsSerializationErrorRetryable(t *testing.T) { + testCases := []struct { + err error + expected bool + }{ + { + err: awserr.New(request.ErrCodeSerialization, "foo error", nil), + expected: false, + }, + { + err: awserr.New("ErrFoo", "foo error", nil), + expected: false, + }, + { + err: nil, + expected: false, + }, + { + err: awserr.New(request.ErrCodeSerialization, "foo error", stubConnectionResetError), + expected: true, + }, + } + + for i, c := range testCases { + r := &request.Request{ + Error: c.err, + } + if r.IsErrorRetryable() != c.expected { + t.Errorf("Case %d: Expected %v, but received %v", i+1, c.expected, !c.expected) + } + } +} + +func TestWithLogLevel(t *testing.T) { + r := &request.Request{} + + opt := request.WithLogLevel(aws.LogDebugWithHTTPBody) + r.ApplyOptions(opt) + + if !r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) { + t.Errorf("expect log level to be set, but was not, %v", + r.Config.LogLevel.Value()) + } +} + +func TestWithGetResponseHeader(t *testing.T) { + r := &request.Request{} + + var val, val2 string + r.ApplyOptions( + request.WithGetResponseHeader("x-a-header", &val), + request.WithGetResponseHeader("x-second-header", &val2), + ) + + r.HTTPResponse = &http.Response{ + Header: func() http.Header { + h := http.Header{} + h.Set("x-a-header", "first") + h.Set("x-second-header", "second") + return h + }(), + } + r.Handlers.Complete.Run(r) + + if e, a := "first", val; e != a { + t.Errorf("expect %q header value got %q", e, a) + } + if e, a := "second", val2; e != a { + t.Errorf("expect %q header value got %q", e, a) + } +} + +func TestWithGetResponseHeaders(t *testing.T) { + r := &request.Request{} + + var headers http.Header + opt := request.WithGetResponseHeaders(&headers) + + r.ApplyOptions(opt) + + r.HTTPResponse = &http.Response{ + Header: func() http.Header { + h := http.Header{} + h.Set("x-a-header", "headerValue") + return h + }(), + } + r.Handlers.Complete.Run(r) + + if e, a := "headerValue", headers.Get("x-a-header"); e != a { + t.Errorf("expect %q header value got %q", e, a) + } +} + +type connResetCloser struct { +} + +func (rc *connResetCloser) Read(b []byte) (int, error) { + return 0, stubConnectionResetError +} + +func (rc *connResetCloser) Close() error { + return nil +} + +func TestSerializationErrConnectionReset(t *testing.T) { + count := 0 + handlers := request.Handlers{} + handlers.Send.PushBack(func(r *request.Request) { + count++ + r.HTTPResponse = &http.Response{} + r.HTTPResponse.Body = &connResetCloser{} + }) + + handlers.Sign.PushBackNamed(v4.SignRequestHandler) + handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) + + op := &request.Operation{ + Name: "op", + HTTPMethod: "POST", + HTTPPath: "/", + } + + meta := metadata.ClientInfo{ + ServiceName: "fooService", + SigningName: "foo", + SigningRegion: "foo", + Endpoint: "localhost", + APIVersion: "2001-01-01", + JSONVersion: "1.1", + TargetPrefix: "Foo", + } + cfg := unit.Session.Config.Copy() + cfg.MaxRetries = aws.Int(5) + + req := request.New( + *cfg, + meta, + handlers, + client.DefaultRetryer{NumMaxRetries: 5}, + op, + &struct { + }{}, + &struct { + }{}, + ) + + osErr := stubConnectionResetError + req.ApplyOptions(request.WithResponseReadTimeout(time.Second)) + err := req.Send() + if err == nil { + t.Error("Expected rror 'SerializationError', but received nil") + } + if aerr, ok := err.(awserr.Error); ok && aerr.Code() != "SerializationError" { + t.Errorf("Expected 'SerializationError', but received %q", aerr.Code()) + } else if !ok { + t.Errorf("Expected 'awserr.Error', but received %v", reflect.TypeOf(err)) + } else if aerr.OrigErr().Error() != osErr.Error() { + t.Errorf("Expected %q, but received %q", osErr.Error(), aerr.OrigErr().Error()) + } + + if count != 6 { + t.Errorf("Expected '6', but received %d", count) + } +} + +type testRetryer struct { + shouldRetry bool +} + +func (d *testRetryer) MaxRetries() int { + return 3 +} + +// RetryRules returns the delay duration before retrying this request again +func (d *testRetryer) RetryRules(r *request.Request) time.Duration { + return time.Duration(time.Millisecond) +} + +func (d *testRetryer) ShouldRetry(r *request.Request) bool { + d.shouldRetry = true + if r.Retryable != nil { + return *r.Retryable + } + + if r.HTTPResponse.StatusCode >= 500 { + return true + } + return r.IsErrorRetryable() +} + +func TestEnforceShouldRetryCheck(t *testing.T) { + tp := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + ResponseHeaderTimeout: 1 * time.Millisecond, + } + + client := &http.Client{Transport: tp} + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // This server should wait forever. Requests will timeout and the SDK should + // attempt to retry. + select {} + })) + + retryer := &testRetryer{} + s := awstesting.NewClient(&aws.Config{ + Region: aws.String("mock-region"), + MaxRetries: aws.Int(0), + Endpoint: aws.String(server.URL), + DisableSSL: aws.Bool(true), + Retryer: retryer, + HTTPClient: client, + EnforceShouldRetryCheck: aws.Bool(true), + }) + + s.Handlers.Validate.Clear() + s.Handlers.Unmarshal.PushBack(unmarshal) + s.Handlers.UnmarshalError.PushBack(unmarshalError) + + out := &testData{} + r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, out) + err := r.Send() + if err == nil { + t.Fatalf("expect error, but got nil") + } + if e, a := 3, int(r.RetryCount); e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + if !retryer.shouldRetry { + t.Errorf("expect 'true' for ShouldRetry, but got %v", retryer.shouldRetry) + } +} + +type errReader struct { + err error +} + +func (reader *errReader) Read(b []byte) (int, error) { + return 0, reader.err +} + +func (reader *errReader) Close() error { + return nil +} + +func TestIsNoBodyReader(t *testing.T) { + cases := []struct { + reader io.ReadCloser + expect bool + }{ + {ioutil.NopCloser(bytes.NewReader([]byte("abc"))), false}, + {ioutil.NopCloser(bytes.NewReader(nil)), false}, + {nil, false}, + {request.NoBody, true}, + } + + for i, c := range cases { + if e, a := c.expect, request.NoBody == c.reader; e != a { + t.Errorf("%d, expect %t match, but was %t", i, e, a) + } + } +} + +func TestRequest_TemporaryRetry(t *testing.T) { + done := make(chan struct{}) + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Length", "1024") + w.WriteHeader(http.StatusOK) + + w.Write(make([]byte, 100)) + + f := w.(http.Flusher) + f.Flush() + + <-done + })) + + client := &http.Client{ + Timeout: 100 * time.Millisecond, + } + + svc := awstesting.NewClient(&aws.Config{ + Region: unit.Session.Config.Region, + MaxRetries: aws.Int(1), + HTTPClient: client, + DisableSSL: aws.Bool(true), + Endpoint: aws.String(server.URL), + }) + + req := svc.NewRequest(&request.Operation{ + Name: "name", HTTPMethod: "GET", HTTPPath: "/path", + }, &struct{}{}, &struct{}{}) + + req.Handlers.Unmarshal.PushBack(func(r *request.Request) { + defer req.HTTPResponse.Body.Close() + _, err := io.Copy(ioutil.Discard, req.HTTPResponse.Body) + r.Error = awserr.New(request.ErrCodeSerialization, "error", err) + }) + + err := req.Send() + if err == nil { + t.Errorf("expect error, got none") + } + close(done) + + aerr := err.(awserr.Error) + if e, a := request.ErrCodeSerialization, aerr.Code(); e != a { + t.Errorf("expect %q error code, got %q", e, a) + } + + if e, a := 1, req.RetryCount; e != a { + t.Errorf("expect %d retries, got %d", e, a) + } + + type temporary interface { + Temporary() bool + } + + terr := aerr.OrigErr().(temporary) + if !terr.Temporary() { + t.Errorf("expect temporary error, was not") + } +} + +func TestRequest_Presign(t *testing.T) { + presign := func(r *request.Request, expire time.Duration) (string, http.Header, error) { + u, err := r.Presign(expire) + return u, nil, err + } + presignRequest := func(r *request.Request, expire time.Duration) (string, http.Header, error) { + return r.PresignRequest(expire) + } + mustParseURL := func(v string) *url.URL { + u, err := url.Parse(v) + if err != nil { + panic(err) + } + return u + } + + cases := []struct { + Expire time.Duration + PresignFn func(*request.Request, time.Duration) (string, http.Header, error) + SignerFn func(*request.Request) + URL string + Header http.Header + Err string + }{ + { + PresignFn: presign, + Err: request.ErrCodeInvalidPresignExpire, + }, + { + PresignFn: presignRequest, + Err: request.ErrCodeInvalidPresignExpire, + }, + { + Expire: -1, + PresignFn: presign, + Err: request.ErrCodeInvalidPresignExpire, + }, + { + // Presign clear NotHoist + Expire: 1 * time.Minute, + PresignFn: func(r *request.Request, dur time.Duration) (string, http.Header, error) { + r.NotHoist = true + return presign(r, dur) + }, + SignerFn: func(r *request.Request) { + r.HTTPRequest.URL = mustParseURL("https://endpoint/presignedURL") + fmt.Println("url", r.HTTPRequest.URL.String()) + if r.NotHoist { + r.Error = fmt.Errorf("expect NotHoist to be cleared") + } + }, + URL: "https://endpoint/presignedURL", + }, + { + // PresignRequest does not clear NotHoist + Expire: 1 * time.Minute, + PresignFn: func(r *request.Request, dur time.Duration) (string, http.Header, error) { + r.NotHoist = true + return presignRequest(r, dur) + }, + SignerFn: func(r *request.Request) { + r.HTTPRequest.URL = mustParseURL("https://endpoint/presignedURL") + if !r.NotHoist { + r.Error = fmt.Errorf("expect NotHoist not to be cleared") + } + }, + URL: "https://endpoint/presignedURL", + }, + { + // PresignRequest returns signed headers + Expire: 1 * time.Minute, + PresignFn: presignRequest, + SignerFn: func(r *request.Request) { + r.HTTPRequest.URL = mustParseURL("https://endpoint/presignedURL") + r.HTTPRequest.Header.Set("UnsigndHeader", "abc") + r.SignedHeaderVals = http.Header{ + "X-Amzn-Header": []string{"abc", "123"}, + "X-Amzn-Header2": []string{"efg", "456"}, + } + }, + URL: "https://endpoint/presignedURL", + Header: http.Header{ + "X-Amzn-Header": []string{"abc", "123"}, + "X-Amzn-Header2": []string{"efg", "456"}, + }, + }, + } + + svc := awstesting.NewClient() + svc.Handlers.Clear() + for i, c := range cases { + req := svc.NewRequest(&request.Operation{ + Name: "name", HTTPMethod: "GET", HTTPPath: "/path", + }, &struct{}{}, &struct{}{}) + req.Handlers.Sign.PushBack(c.SignerFn) + + u, h, err := c.PresignFn(req, c.Expire) + if len(c.Err) != 0 { + if e, a := c.Err, err.Error(); !strings.Contains(a, e) { + t.Errorf("%d, expect %v to be in %v", i, e, a) + } + continue + } else if err != nil { + t.Errorf("%d, expect no error, got %v", i, err) + continue + } + if e, a := c.URL, u; e != a { + t.Errorf("%d, expect %v URL, got %v", i, e, a) + } + if e, a := c.Header, h; !reflect.DeepEqual(e, a) { + t.Errorf("%d, expect %v header got %v", i, e, a) + } + } +} + +func TestNew_EndpointWithDefaultPort(t *testing.T) { + endpoint := "https://estest.us-east-1.es.amazonaws.com:443" + expectedRequestHost := "estest.us-east-1.es.amazonaws.com" + + r := request.New( + aws.Config{}, + metadata.ClientInfo{Endpoint: endpoint}, + defaults.Handlers(), + client.DefaultRetryer{}, + &request.Operation{}, + nil, + nil, + ) + + if h := r.HTTPRequest.Host; h != expectedRequestHost { + t.Errorf("expect %v host, got %q", expectedRequestHost, h) + } +} + +func TestSanitizeHostForHeader(t *testing.T) { + cases := []struct { + url string + expectedRequestHost string + }{ + {"https://estest.us-east-1.es.amazonaws.com:443", "estest.us-east-1.es.amazonaws.com"}, + {"https://estest.us-east-1.es.amazonaws.com", "estest.us-east-1.es.amazonaws.com"}, + {"https://localhost:9200", "localhost:9200"}, + {"http://localhost:80", "localhost"}, + {"http://localhost:8080", "localhost:8080"}, + } + + for _, c := range cases { + r, _ := http.NewRequest("GET", c.url, nil) + request.SanitizeHostForHeader(r) + + if h := r.Host; h != c.expectedRequestHost { + t.Errorf("expect %v host, got %q", c.expectedRequestHost, h) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go new file mode 100644 index 0000000..f35fef2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go @@ -0,0 +1,161 @@ +package request + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" +) + +// Retryer is an interface to control retry logic for a given service. +// The default implementation used by most services is the client.DefaultRetryer +// structure, which contains basic retry logic using exponential backoff. +type Retryer interface { + RetryRules(*Request) time.Duration + ShouldRetry(*Request) bool + MaxRetries() int +} + +// WithRetryer sets a config Retryer value to the given Config returning it +// for chaining. +func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config { + cfg.Retryer = retryer + return cfg +} + +// retryableCodes is a collection of service response codes which are retry-able +// without any further action. +var retryableCodes = map[string]struct{}{ + "RequestError": {}, + "RequestTimeout": {}, + ErrCodeResponseTimeout: {}, + "RequestTimeoutException": {}, // Glacier's flavor of RequestTimeout +} + +var throttleCodes = map[string]struct{}{ + "ProvisionedThroughputExceededException": {}, + "Throttling": {}, + "ThrottlingException": {}, + "RequestLimitExceeded": {}, + "RequestThrottled": {}, + "TooManyRequestsException": {}, // Lambda functions + "PriorRequestNotComplete": {}, // Route53 +} + +// credsExpiredCodes is a collection of error codes which signify the credentials +// need to be refreshed. Expired tokens require refreshing of credentials, and +// resigning before the request can be retried. +var credsExpiredCodes = map[string]struct{}{ + "ExpiredToken": {}, + "ExpiredTokenException": {}, + "RequestExpired": {}, // EC2 Only +} + +func isCodeThrottle(code string) bool { + _, ok := throttleCodes[code] + return ok +} + +func isCodeRetryable(code string) bool { + if _, ok := retryableCodes[code]; ok { + return true + } + + return isCodeExpiredCreds(code) +} + +func isCodeExpiredCreds(code string) bool { + _, ok := credsExpiredCodes[code] + return ok +} + +var validParentCodes = map[string]struct{}{ + ErrCodeSerialization: {}, + ErrCodeRead: {}, +} + +type temporaryError interface { + Temporary() bool +} + +func isNestedErrorRetryable(parentErr awserr.Error) bool { + if parentErr == nil { + return false + } + + if _, ok := validParentCodes[parentErr.Code()]; !ok { + return false + } + + err := parentErr.OrigErr() + if err == nil { + return false + } + + if aerr, ok := err.(awserr.Error); ok { + return isCodeRetryable(aerr.Code()) + } + + if t, ok := err.(temporaryError); ok { + return t.Temporary() + } + + return isErrConnectionReset(err) +} + +// IsErrorRetryable returns whether the error is retryable, based on its Code. +// Returns false if error is nil. +func IsErrorRetryable(err error) bool { + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + return isCodeRetryable(aerr.Code()) || isNestedErrorRetryable(aerr) + } + } + return false +} + +// IsErrorThrottle returns whether the error is to be throttled based on its code. +// Returns false if error is nil. +func IsErrorThrottle(err error) bool { + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + return isCodeThrottle(aerr.Code()) + } + } + return false +} + +// IsErrorExpiredCreds returns whether the error code is a credential expiry error. +// Returns false if error is nil. +func IsErrorExpiredCreds(err error) bool { + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + return isCodeExpiredCreds(aerr.Code()) + } + } + return false +} + +// IsErrorRetryable returns whether the error is retryable, based on its Code. +// Returns false if the request has no Error set. +// +// Alias for the utility function IsErrorRetryable +func (r *Request) IsErrorRetryable() bool { + return IsErrorRetryable(r.Error) +} + +// IsErrorThrottle returns whether the error is to be throttled based on its code. +// Returns false if the request has no Error set +// +// Alias for the utility function IsErrorThrottle +func (r *Request) IsErrorThrottle() bool { + return IsErrorThrottle(r.Error) +} + +// IsErrorExpired returns whether the error code is a credential expiry error. +// Returns false if the request has no Error set. +// +// Alias for the utility function IsErrorExpiredCreds +func (r *Request) IsErrorExpired() bool { + return IsErrorExpiredCreds(r.Error) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/retryer_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer_test.go new file mode 100644 index 0000000..a878748 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer_test.go @@ -0,0 +1,62 @@ +package request + +import ( + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +func TestRequestThrottling(t *testing.T) { + req := Request{} + + req.Error = awserr.New("Throttling", "", nil) + if e, a := true, req.IsErrorThrottle(); e != a { + t.Errorf("expect %t to be throttled, was %t", e, a) + } +} + +type mockTempError bool + +func (e mockTempError) Error() string { + return fmt.Sprintf("mock temporary error: %t", e.Temporary()) +} +func (e mockTempError) Temporary() bool { + return bool(e) +} + +func TestIsErrorRetryable(t *testing.T) { + cases := []struct { + Err error + IsTemp bool + }{ + { + Err: awserr.New(ErrCodeSerialization, "temporary error", mockTempError(true)), + IsTemp: true, + }, + { + Err: awserr.New(ErrCodeSerialization, "temporary error", mockTempError(false)), + IsTemp: false, + }, + { + Err: awserr.New(ErrCodeSerialization, "some error", errors.New("blah")), + IsTemp: false, + }, + { + Err: awserr.New("SomeError", "some error", nil), + IsTemp: false, + }, + { + Err: awserr.New("RequestError", "some error", nil), + IsTemp: true, + }, + } + + for i, c := range cases { + retryable := IsErrorRetryable(c.Err) + if e, a := c.IsTemp, retryable; e != a { + t.Errorf("%d, expect %t temporary error, got %t", i, e, a) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go new file mode 100644 index 0000000..09a44eb --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go @@ -0,0 +1,94 @@ +package request + +import ( + "io" + "time" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +var timeoutErr = awserr.New( + ErrCodeResponseTimeout, + "read on body has reached the timeout limit", + nil, +) + +type readResult struct { + n int + err error +} + +// timeoutReadCloser will handle body reads that take too long. +// We will return a ErrReadTimeout error if a timeout occurs. +type timeoutReadCloser struct { + reader io.ReadCloser + duration time.Duration +} + +// Read will spin off a goroutine to call the reader's Read method. We will +// select on the timer's channel or the read's channel. Whoever completes first +// will be returned. +func (r *timeoutReadCloser) Read(b []byte) (int, error) { + timer := time.NewTimer(r.duration) + c := make(chan readResult, 1) + + go func() { + n, err := r.reader.Read(b) + timer.Stop() + c <- readResult{n: n, err: err} + }() + + select { + case data := <-c: + return data.n, data.err + case <-timer.C: + return 0, timeoutErr + } +} + +func (r *timeoutReadCloser) Close() error { + return r.reader.Close() +} + +const ( + // HandlerResponseTimeout is what we use to signify the name of the + // response timeout handler. + HandlerResponseTimeout = "ResponseTimeoutHandler" +) + +// adaptToResponseTimeoutError is a handler that will replace any top level error +// to a ErrCodeResponseTimeout, if its child is that. +func adaptToResponseTimeoutError(req *Request) { + if err, ok := req.Error.(awserr.Error); ok { + aerr, ok := err.OrigErr().(awserr.Error) + if ok && aerr.Code() == ErrCodeResponseTimeout { + req.Error = aerr + } + } +} + +// WithResponseReadTimeout is a request option that will wrap the body in a timeout read closer. +// This will allow for per read timeouts. If a timeout occurred, we will return the +// ErrCodeResponseTimeout. +// +// svc.PutObjectWithContext(ctx, params, request.WithTimeoutReadCloser(30 * time.Second) +func WithResponseReadTimeout(duration time.Duration) Option { + return func(r *Request) { + + var timeoutHandler = NamedHandler{ + HandlerResponseTimeout, + func(req *Request) { + req.HTTPResponse.Body = &timeoutReadCloser{ + reader: req.HTTPResponse.Body, + duration: duration, + } + }} + + // remove the handler so we are not stomping over any new durations. + r.Handlers.Send.RemoveByName(HandlerResponseTimeout) + r.Handlers.Send.PushBackNamed(timeoutHandler) + + r.Handlers.Unmarshal.PushBack(adaptToResponseTimeoutError) + r.Handlers.UnmarshalError.PushBack(adaptToResponseTimeoutError) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_benchmark_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_benchmark_test.go new file mode 100644 index 0000000..33e1b2d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_benchmark_test.go @@ -0,0 +1,76 @@ +package request_test + +import ( + "bytes" + "io/ioutil" + "net/http" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" +) + +func BenchmarkTimeoutReadCloser(b *testing.B) { + resp := ` + { + "Bar": "qux" + } + ` + + handlers := request.Handlers{} + + handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte(resp))), + } + }) + handlers.Sign.PushBackNamed(v4.SignRequestHandler) + handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + op := &request.Operation{ + Name: "op", + HTTPMethod: "POST", + HTTPPath: "/", + } + + meta := metadata.ClientInfo{ + ServiceName: "fooService", + SigningName: "foo", + SigningRegion: "foo", + Endpoint: "localhost", + APIVersion: "2001-01-01", + JSONVersion: "1.1", + TargetPrefix: "Foo", + } + + req := request.New( + *unit.Session.Config, + meta, + handlers, + client.DefaultRetryer{NumMaxRetries: 5}, + op, + &struct { + Foo *string + }{}, + &struct { + Bar *string + }{}, + ) + + req.ApplyOptions(request.WithResponseReadTimeout(15 * time.Second)) + for i := 0; i < b.N; i++ { + err := req.Send() + if err != nil { + b.Errorf("Expected no error, but received %v", err) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_test.go new file mode 100644 index 0000000..c814158 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer_test.go @@ -0,0 +1,118 @@ +package request + +import ( + "bytes" + "io" + "io/ioutil" + "net/http" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +type testReader struct { + duration time.Duration + count int +} + +func (r *testReader) Read(b []byte) (int, error) { + if r.count > 0 { + r.count-- + return len(b), nil + } + time.Sleep(r.duration) + return 0, io.EOF +} + +func (r *testReader) Close() error { + return nil +} + +func TestTimeoutReadCloser(t *testing.T) { + reader := timeoutReadCloser{ + reader: &testReader{ + duration: time.Second, + count: 5, + }, + duration: time.Millisecond, + } + b := make([]byte, 100) + _, err := reader.Read(b) + if err != nil { + t.Log(err) + } +} + +func TestTimeoutReadCloserSameDuration(t *testing.T) { + reader := timeoutReadCloser{ + reader: &testReader{ + duration: time.Millisecond, + count: 5, + }, + duration: time.Millisecond, + } + b := make([]byte, 100) + _, err := reader.Read(b) + if err != nil { + t.Log(err) + } +} + +func TestWithResponseReadTimeout(t *testing.T) { + r := Request{ + HTTPResponse: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader(nil)), + }, + } + r.ApplyOptions(WithResponseReadTimeout(time.Second)) + err := r.Send() + if err != nil { + t.Error(err) + } + v, ok := r.HTTPResponse.Body.(*timeoutReadCloser) + if !ok { + t.Error("Expected the body to be a timeoutReadCloser") + } + if v.duration != time.Second { + t.Errorf("Expected %v, but receive %v\n", time.Second, v.duration) + } +} + +func TestAdaptToResponseTimeout(t *testing.T) { + testCases := []struct { + childErr error + r Request + expectedRootCode string + }{ + { + childErr: awserr.New(ErrCodeResponseTimeout, "timeout!", nil), + r: Request{ + Error: awserr.New("ErrTest", "FooBar", awserr.New(ErrCodeResponseTimeout, "timeout!", nil)), + }, + expectedRootCode: ErrCodeResponseTimeout, + }, + { + childErr: awserr.New(ErrCodeResponseTimeout+"1", "timeout!", nil), + r: Request{ + Error: awserr.New("ErrTest", "FooBar", awserr.New(ErrCodeResponseTimeout+"1", "timeout!", nil)), + }, + expectedRootCode: "ErrTest", + }, + { + r: Request{ + Error: awserr.New("ErrTest", "FooBar", nil), + }, + expectedRootCode: "ErrTest", + }, + } + + for i, c := range testCases { + adaptToResponseTimeoutError(&c.r) + if aerr, ok := c.r.Error.(awserr.Error); !ok { + t.Errorf("Case %d: Expected 'awserr', but received %v", i+1, c.r.Error) + } else if aerr.Code() != c.expectedRootCode { + t.Errorf("Case %d: Expected %q, but received %s", i+1, c.expectedRootCode, aerr.Code()) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go b/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go new file mode 100644 index 0000000..4012462 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go @@ -0,0 +1,234 @@ +package request + +import ( + "bytes" + "fmt" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +const ( + // InvalidParameterErrCode is the error code for invalid parameters errors + InvalidParameterErrCode = "InvalidParameter" + // ParamRequiredErrCode is the error code for required parameter errors + ParamRequiredErrCode = "ParamRequiredError" + // ParamMinValueErrCode is the error code for fields with too low of a + // number value. + ParamMinValueErrCode = "ParamMinValueError" + // ParamMinLenErrCode is the error code for fields without enough elements. + ParamMinLenErrCode = "ParamMinLenError" +) + +// Validator provides a way for types to perform validation logic on their +// input values that external code can use to determine if a type's values +// are valid. +type Validator interface { + Validate() error +} + +// An ErrInvalidParams provides wrapping of invalid parameter errors found when +// validating API operation input parameters. +type ErrInvalidParams struct { + // Context is the base context of the invalid parameter group. + Context string + errs []ErrInvalidParam +} + +// Add adds a new invalid parameter error to the collection of invalid +// parameters. The context of the invalid parameter will be updated to reflect +// this collection. +func (e *ErrInvalidParams) Add(err ErrInvalidParam) { + err.SetContext(e.Context) + e.errs = append(e.errs, err) +} + +// AddNested adds the invalid parameter errors from another ErrInvalidParams +// value into this collection. The nested errors will have their nested context +// updated and base context to reflect the merging. +// +// Use for nested validations errors. +func (e *ErrInvalidParams) AddNested(nestedCtx string, nested ErrInvalidParams) { + for _, err := range nested.errs { + err.SetContext(e.Context) + err.AddNestedContext(nestedCtx) + e.errs = append(e.errs, err) + } +} + +// Len returns the number of invalid parameter errors +func (e ErrInvalidParams) Len() int { + return len(e.errs) +} + +// Code returns the code of the error +func (e ErrInvalidParams) Code() string { + return InvalidParameterErrCode +} + +// Message returns the message of the error +func (e ErrInvalidParams) Message() string { + return fmt.Sprintf("%d validation error(s) found.", len(e.errs)) +} + +// Error returns the string formatted form of the invalid parameters. +func (e ErrInvalidParams) Error() string { + w := &bytes.Buffer{} + fmt.Fprintf(w, "%s: %s\n", e.Code(), e.Message()) + + for _, err := range e.errs { + fmt.Fprintf(w, "- %s\n", err.Message()) + } + + return w.String() +} + +// OrigErr returns the invalid parameters as a awserr.BatchedErrors value +func (e ErrInvalidParams) OrigErr() error { + return awserr.NewBatchError( + InvalidParameterErrCode, e.Message(), e.OrigErrs()) +} + +// OrigErrs returns a slice of the invalid parameters +func (e ErrInvalidParams) OrigErrs() []error { + errs := make([]error, len(e.errs)) + for i := 0; i < len(errs); i++ { + errs[i] = e.errs[i] + } + + return errs +} + +// An ErrInvalidParam represents an invalid parameter error type. +type ErrInvalidParam interface { + awserr.Error + + // Field name the error occurred on. + Field() string + + // SetContext updates the context of the error. + SetContext(string) + + // AddNestedContext updates the error's context to include a nested level. + AddNestedContext(string) +} + +type errInvalidParam struct { + context string + nestedContext string + field string + code string + msg string +} + +// Code returns the error code for the type of invalid parameter. +func (e *errInvalidParam) Code() string { + return e.code +} + +// Message returns the reason the parameter was invalid, and its context. +func (e *errInvalidParam) Message() string { + return fmt.Sprintf("%s, %s.", e.msg, e.Field()) +} + +// Error returns the string version of the invalid parameter error. +func (e *errInvalidParam) Error() string { + return fmt.Sprintf("%s: %s", e.code, e.Message()) +} + +// OrigErr returns nil, Implemented for awserr.Error interface. +func (e *errInvalidParam) OrigErr() error { + return nil +} + +// Field Returns the field and context the error occurred. +func (e *errInvalidParam) Field() string { + field := e.context + if len(field) > 0 { + field += "." + } + if len(e.nestedContext) > 0 { + field += fmt.Sprintf("%s.", e.nestedContext) + } + field += e.field + + return field +} + +// SetContext updates the base context of the error. +func (e *errInvalidParam) SetContext(ctx string) { + e.context = ctx +} + +// AddNestedContext prepends a context to the field's path. +func (e *errInvalidParam) AddNestedContext(ctx string) { + if len(e.nestedContext) == 0 { + e.nestedContext = ctx + } else { + e.nestedContext = fmt.Sprintf("%s.%s", ctx, e.nestedContext) + } + +} + +// An ErrParamRequired represents an required parameter error. +type ErrParamRequired struct { + errInvalidParam +} + +// NewErrParamRequired creates a new required parameter error. +func NewErrParamRequired(field string) *ErrParamRequired { + return &ErrParamRequired{ + errInvalidParam{ + code: ParamRequiredErrCode, + field: field, + msg: fmt.Sprintf("missing required field"), + }, + } +} + +// An ErrParamMinValue represents a minimum value parameter error. +type ErrParamMinValue struct { + errInvalidParam + min float64 +} + +// NewErrParamMinValue creates a new minimum value parameter error. +func NewErrParamMinValue(field string, min float64) *ErrParamMinValue { + return &ErrParamMinValue{ + errInvalidParam: errInvalidParam{ + code: ParamMinValueErrCode, + field: field, + msg: fmt.Sprintf("minimum field value of %v", min), + }, + min: min, + } +} + +// MinValue returns the field's require minimum value. +// +// float64 is returned for both int and float min values. +func (e *ErrParamMinValue) MinValue() float64 { + return e.min +} + +// An ErrParamMinLen represents a minimum length parameter error. +type ErrParamMinLen struct { + errInvalidParam + min int +} + +// NewErrParamMinLen creates a new minimum length parameter error. +func NewErrParamMinLen(field string, min int) *ErrParamMinLen { + return &ErrParamMinLen{ + errInvalidParam: errInvalidParam{ + code: ParamMinLenErrCode, + field: field, + msg: fmt.Sprintf("minimum field size of %v", min), + }, + min: min, + } +} + +// MinLen returns the field's required minimum length. +func (e *ErrParamMinLen) MinLen() int { + return e.min +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go new file mode 100644 index 0000000..4601f88 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go @@ -0,0 +1,295 @@ +package request + +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/awsutil" +) + +// WaiterResourceNotReadyErrorCode is the error code returned by a waiter when +// the waiter's max attempts have been exhausted. +const WaiterResourceNotReadyErrorCode = "ResourceNotReady" + +// A WaiterOption is a function that will update the Waiter value's fields to +// configure the waiter. +type WaiterOption func(*Waiter) + +// WithWaiterMaxAttempts returns the maximum number of times the waiter should +// attempt to check the resource for the target state. +func WithWaiterMaxAttempts(max int) WaiterOption { + return func(w *Waiter) { + w.MaxAttempts = max + } +} + +// WaiterDelay will return a delay the waiter should pause between attempts to +// check the resource state. The passed in attempt is the number of times the +// Waiter has checked the resource state. +// +// Attempt is the number of attempts the Waiter has made checking the resource +// state. +type WaiterDelay func(attempt int) time.Duration + +// ConstantWaiterDelay returns a WaiterDelay that will always return a constant +// delay the waiter should use between attempts. It ignores the number of +// attempts made. +func ConstantWaiterDelay(delay time.Duration) WaiterDelay { + return func(attempt int) time.Duration { + return delay + } +} + +// WithWaiterDelay will set the Waiter to use the WaiterDelay passed in. +func WithWaiterDelay(delayer WaiterDelay) WaiterOption { + return func(w *Waiter) { + w.Delay = delayer + } +} + +// WithWaiterLogger returns a waiter option to set the logger a waiter +// should use to log warnings and errors to. +func WithWaiterLogger(logger aws.Logger) WaiterOption { + return func(w *Waiter) { + w.Logger = logger + } +} + +// WithWaiterRequestOptions returns a waiter option setting the request +// options for each request the waiter makes. Appends to waiter's request +// options already set. +func WithWaiterRequestOptions(opts ...Option) WaiterOption { + return func(w *Waiter) { + w.RequestOptions = append(w.RequestOptions, opts...) + } +} + +// A Waiter provides the functionality to perform a blocking call which will +// wait for a resource state to be satisfied by a service. +// +// This type should not be used directly. The API operations provided in the +// service packages prefixed with "WaitUntil" should be used instead. +type Waiter struct { + Name string + Acceptors []WaiterAcceptor + Logger aws.Logger + + MaxAttempts int + Delay WaiterDelay + + RequestOptions []Option + NewRequest func([]Option) (*Request, error) + SleepWithContext func(aws.Context, time.Duration) error +} + +// ApplyOptions updates the waiter with the list of waiter options provided. +func (w *Waiter) ApplyOptions(opts ...WaiterOption) { + for _, fn := range opts { + fn(w) + } +} + +// WaiterState are states the waiter uses based on WaiterAcceptor definitions +// to identify if the resource state the waiter is waiting on has occurred. +type WaiterState int + +// String returns the string representation of the waiter state. +func (s WaiterState) String() string { + switch s { + case SuccessWaiterState: + return "success" + case FailureWaiterState: + return "failure" + case RetryWaiterState: + return "retry" + default: + return "unknown waiter state" + } +} + +// States the waiter acceptors will use to identify target resource states. +const ( + SuccessWaiterState WaiterState = iota // waiter successful + FailureWaiterState // waiter failed + RetryWaiterState // waiter needs to be retried +) + +// WaiterMatchMode is the mode that the waiter will use to match the WaiterAcceptor +// definition's Expected attribute. +type WaiterMatchMode int + +// Modes the waiter will use when inspecting API response to identify target +// resource states. +const ( + PathAllWaiterMatch WaiterMatchMode = iota // match on all paths + PathWaiterMatch // match on specific path + PathAnyWaiterMatch // match on any path + PathListWaiterMatch // match on list of paths + StatusWaiterMatch // match on status code + ErrorWaiterMatch // match on error +) + +// String returns the string representation of the waiter match mode. +func (m WaiterMatchMode) String() string { + switch m { + case PathAllWaiterMatch: + return "pathAll" + case PathWaiterMatch: + return "path" + case PathAnyWaiterMatch: + return "pathAny" + case PathListWaiterMatch: + return "pathList" + case StatusWaiterMatch: + return "status" + case ErrorWaiterMatch: + return "error" + default: + return "unknown waiter match mode" + } +} + +// WaitWithContext will make requests for the API operation using NewRequest to +// build API requests. The request's response will be compared against the +// Waiter's Acceptors to determine the successful state of the resource the +// waiter is inspecting. +// +// The passed in context must not be nil. If it is nil a panic will occur. The +// Context will be used to cancel the waiter's pending requests and retry delays. +// Use aws.BackgroundContext if no context is available. +// +// The waiter will continue until the target state defined by the Acceptors, +// or the max attempts expires. +// +// Will return the WaiterResourceNotReadyErrorCode error code if the waiter's +// retryer ShouldRetry returns false. This normally will happen when the max +// wait attempts expires. +func (w Waiter) WaitWithContext(ctx aws.Context) error { + + for attempt := 1; ; attempt++ { + req, err := w.NewRequest(w.RequestOptions) + if err != nil { + waiterLogf(w.Logger, "unable to create request %v", err) + return err + } + req.Handlers.Build.PushBack(MakeAddToUserAgentFreeFormHandler("Waiter")) + err = req.Send() + + // See if any of the acceptors match the request's response, or error + for _, a := range w.Acceptors { + if matched, matchErr := a.match(w.Name, w.Logger, req, err); matched { + return matchErr + } + } + + // The Waiter should only check the resource state MaxAttempts times + // This is here instead of in the for loop above to prevent delaying + // unnecessary when the waiter will not retry. + if attempt == w.MaxAttempts { + break + } + + // Delay to wait before inspecting the resource again + delay := w.Delay(attempt) + if sleepFn := req.Config.SleepDelay; sleepFn != nil { + // Support SleepDelay for backwards compatibility and testing + sleepFn(delay) + } else { + sleepCtxFn := w.SleepWithContext + if sleepCtxFn == nil { + sleepCtxFn = aws.SleepWithContext + } + + if err := sleepCtxFn(ctx, delay); err != nil { + return awserr.New(CanceledErrorCode, "waiter context canceled", err) + } + } + } + + return awserr.New(WaiterResourceNotReadyErrorCode, "exceeded wait attempts", nil) +} + +// A WaiterAcceptor provides the information needed to wait for an API operation +// to complete. +type WaiterAcceptor struct { + State WaiterState + Matcher WaiterMatchMode + Argument string + Expected interface{} +} + +// match returns if the acceptor found a match with the passed in request +// or error. True is returned if the acceptor made a match, error is returned +// if there was an error attempting to perform the match. +func (a *WaiterAcceptor) match(name string, l aws.Logger, req *Request, err error) (bool, error) { + result := false + var vals []interface{} + + switch a.Matcher { + case PathAllWaiterMatch, PathWaiterMatch: + // Require all matches to be equal for result to match + vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) + if len(vals) == 0 { + break + } + result = true + for _, val := range vals { + if !awsutil.DeepEqual(val, a.Expected) { + result = false + break + } + } + case PathAnyWaiterMatch: + // Only a single match needs to equal for the result to match + vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument) + for _, val := range vals { + if awsutil.DeepEqual(val, a.Expected) { + result = true + break + } + } + case PathListWaiterMatch: + // ignored matcher + case StatusWaiterMatch: + s := a.Expected.(int) + result = s == req.HTTPResponse.StatusCode + case ErrorWaiterMatch: + if aerr, ok := err.(awserr.Error); ok { + result = aerr.Code() == a.Expected.(string) + } + default: + waiterLogf(l, "WARNING: Waiter %s encountered unexpected matcher: %s", + name, a.Matcher) + } + + if !result { + // If there was no matching result found there is nothing more to do + // for this response, retry the request. + return false, nil + } + + switch a.State { + case SuccessWaiterState: + // waiter completed + return true, nil + case FailureWaiterState: + // Waiter failure state triggered + return true, awserr.New(WaiterResourceNotReadyErrorCode, + "failed waiting for successful resource state", err) + case RetryWaiterState: + // clear the error and retry the operation + return false, nil + default: + waiterLogf(l, "WARNING: Waiter %s encountered unexpected state: %s", + name, a.State) + return false, nil + } +} + +func waiterLogf(logger aws.Logger, msg string, args ...interface{}) { + if logger != nil { + logger.Log(fmt.Sprintf(msg, args...)) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/waiter_test.go b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter_test.go new file mode 100644 index 0000000..db0f92d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter_test.go @@ -0,0 +1,654 @@ +package request_test + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "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/client" + "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" +) + +type mockClient struct { + *client.Client +} +type MockInput struct{} +type MockOutput struct { + States []*MockState +} +type MockState struct { + State *string +} + +func (c *mockClient) MockRequest(input *MockInput) (*request.Request, *MockOutput) { + op := &request.Operation{ + Name: "Mock", + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &MockInput{} + } + + output := &MockOutput{} + req := c.NewRequest(op, input, output) + req.Data = output + return req, output +} + +func BuildNewMockRequest(c *mockClient, in *MockInput) func([]request.Option) (*request.Request, error) { + return func(opts []request.Option) (*request.Request, error) { + req, _ := c.MockRequest(in) + req.ApplyOptions(opts...) + return req, nil + } +} + +func TestWaiterPathAll(t *testing.T) { + svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ + Region: aws.String("mock-region"), + })} + svc.Handlers.Send.Clear() // mock sending + svc.Handlers.Unmarshal.Clear() + svc.Handlers.UnmarshalMeta.Clear() + svc.Handlers.ValidateResponse.Clear() + + reqNum := 0 + resps := []*MockOutput{ + { // Request 1 + States: []*MockState{ + {State: aws.String("pending")}, + {State: aws.String("pending")}, + }, + }, + { // Request 2 + States: []*MockState{ + {State: aws.String("running")}, + {State: aws.String("pending")}, + }, + }, + { // Request 3 + States: []*MockState{ + {State: aws.String("running")}, + {State: aws.String("running")}, + }, + }, + } + + numBuiltReq := 0 + svc.Handlers.Build.PushBack(func(r *request.Request) { + numBuiltReq++ + }) + svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { + if reqNum >= len(resps) { + assert.Fail(t, "too many polling requests made") + return + } + r.Data = resps[reqNum] + reqNum++ + }) + + w := request.Waiter{ + MaxAttempts: 10, + Delay: request.ConstantWaiterDelay(0), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.PathAllWaiterMatch, + Argument: "States[].State", + Expected: "running", + }, + }, + NewRequest: BuildNewMockRequest(svc, &MockInput{}), + } + + err := w.WaitWithContext(aws.BackgroundContext()) + assert.NoError(t, err) + assert.Equal(t, 3, numBuiltReq) + assert.Equal(t, 3, reqNum) +} + +func TestWaiterPath(t *testing.T) { + svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ + Region: aws.String("mock-region"), + })} + svc.Handlers.Send.Clear() // mock sending + svc.Handlers.Unmarshal.Clear() + svc.Handlers.UnmarshalMeta.Clear() + svc.Handlers.ValidateResponse.Clear() + + reqNum := 0 + resps := []*MockOutput{ + { // Request 1 + States: []*MockState{ + {State: aws.String("pending")}, + {State: aws.String("pending")}, + }, + }, + { // Request 2 + States: []*MockState{ + {State: aws.String("running")}, + {State: aws.String("pending")}, + }, + }, + { // Request 3 + States: []*MockState{ + {State: aws.String("running")}, + {State: aws.String("running")}, + }, + }, + } + + numBuiltReq := 0 + svc.Handlers.Build.PushBack(func(r *request.Request) { + numBuiltReq++ + }) + svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { + if reqNum >= len(resps) { + assert.Fail(t, "too many polling requests made") + return + } + r.Data = resps[reqNum] + reqNum++ + }) + + w := request.Waiter{ + MaxAttempts: 10, + Delay: request.ConstantWaiterDelay(0), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.PathWaiterMatch, + Argument: "States[].State", + Expected: "running", + }, + }, + NewRequest: BuildNewMockRequest(svc, &MockInput{}), + } + + err := w.WaitWithContext(aws.BackgroundContext()) + assert.NoError(t, err) + assert.Equal(t, 3, numBuiltReq) + assert.Equal(t, 3, reqNum) +} + +func TestWaiterFailure(t *testing.T) { + svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ + Region: aws.String("mock-region"), + })} + svc.Handlers.Send.Clear() // mock sending + svc.Handlers.Unmarshal.Clear() + svc.Handlers.UnmarshalMeta.Clear() + svc.Handlers.ValidateResponse.Clear() + + reqNum := 0 + resps := []*MockOutput{ + { // Request 1 + States: []*MockState{ + {State: aws.String("pending")}, + {State: aws.String("pending")}, + }, + }, + { // Request 2 + States: []*MockState{ + {State: aws.String("running")}, + {State: aws.String("pending")}, + }, + }, + { // Request 3 + States: []*MockState{ + {State: aws.String("running")}, + {State: aws.String("stopping")}, + }, + }, + } + + numBuiltReq := 0 + svc.Handlers.Build.PushBack(func(r *request.Request) { + numBuiltReq++ + }) + svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { + if reqNum >= len(resps) { + assert.Fail(t, "too many polling requests made") + return + } + r.Data = resps[reqNum] + reqNum++ + }) + + w := request.Waiter{ + MaxAttempts: 10, + Delay: request.ConstantWaiterDelay(0), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.PathAllWaiterMatch, + Argument: "States[].State", + Expected: "running", + }, + { + State: request.FailureWaiterState, + Matcher: request.PathAnyWaiterMatch, + Argument: "States[].State", + Expected: "stopping", + }, + }, + NewRequest: BuildNewMockRequest(svc, &MockInput{}), + } + + err := w.WaitWithContext(aws.BackgroundContext()).(awserr.Error) + assert.Error(t, err) + assert.Equal(t, request.WaiterResourceNotReadyErrorCode, err.Code()) + assert.Equal(t, "failed waiting for successful resource state", err.Message()) + assert.Equal(t, 3, numBuiltReq) + assert.Equal(t, 3, reqNum) +} + +func TestWaiterError(t *testing.T) { + svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ + Region: aws.String("mock-region"), + })} + svc.Handlers.Send.Clear() // mock sending + svc.Handlers.Unmarshal.Clear() + svc.Handlers.UnmarshalMeta.Clear() + svc.Handlers.UnmarshalError.Clear() + svc.Handlers.ValidateResponse.Clear() + + reqNum := 0 + resps := []*MockOutput{ + { // Request 1 + States: []*MockState{ + {State: aws.String("pending")}, + {State: aws.String("pending")}, + }, + }, + { // Request 1, error case retry + }, + { // Request 2, error case failure + }, + { // Request 3 + States: []*MockState{ + {State: aws.String("running")}, + {State: aws.String("running")}, + }, + }, + } + reqErrs := make([]error, len(resps)) + reqErrs[1] = awserr.New("MockException", "mock exception message", nil) + reqErrs[2] = awserr.New("FailureException", "mock failure exception message", nil) + + numBuiltReq := 0 + svc.Handlers.Build.PushBack(func(r *request.Request) { + numBuiltReq++ + }) + svc.Handlers.Send.PushBack(func(r *request.Request) { + code := 200 + if reqNum == 1 { + code = 400 + } + r.HTTPResponse = &http.Response{ + StatusCode: code, + Status: http.StatusText(code), + Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + } + }) + svc.Handlers.Unmarshal.PushBack(func(r *request.Request) { + if reqNum >= len(resps) { + assert.Fail(t, "too many polling requests made") + return + } + r.Data = resps[reqNum] + reqNum++ + }) + svc.Handlers.UnmarshalMeta.PushBack(func(r *request.Request) { + // If there was an error unmarshal error will be called instead of unmarshal + // need to increment count here also + if err := reqErrs[reqNum]; err != nil { + r.Error = err + reqNum++ + } + }) + + w := request.Waiter{ + MaxAttempts: 10, + Delay: request.ConstantWaiterDelay(0), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.PathAllWaiterMatch, + Argument: "States[].State", + Expected: "running", + }, + { + State: request.RetryWaiterState, + Matcher: request.ErrorWaiterMatch, + Argument: "", + Expected: "MockException", + }, + { + State: request.FailureWaiterState, + Matcher: request.ErrorWaiterMatch, + Argument: "", + Expected: "FailureException", + }, + }, + NewRequest: BuildNewMockRequest(svc, &MockInput{}), + } + + err := w.WaitWithContext(aws.BackgroundContext()) + if err == nil { + t.Fatalf("expected error, but did not get one") + } + aerr := err.(awserr.Error) + if e, a := request.WaiterResourceNotReadyErrorCode, aerr.Code(); e != a { + t.Errorf("expect %q error code, got %q", e, a) + } + if e, a := 3, numBuiltReq; e != a { + t.Errorf("expect %d built requests got %d", e, a) + } + if e, a := 3, reqNum; e != a { + t.Errorf("expect %d reqNum got %d", e, a) + } +} + +func TestWaiterStatus(t *testing.T) { + svc := &mockClient{Client: awstesting.NewClient(&aws.Config{ + Region: aws.String("mock-region"), + })} + svc.Handlers.Send.Clear() // mock sending + svc.Handlers.Unmarshal.Clear() + svc.Handlers.UnmarshalMeta.Clear() + svc.Handlers.ValidateResponse.Clear() + + reqNum := 0 + svc.Handlers.Build.PushBack(func(r *request.Request) { + reqNum++ + }) + svc.Handlers.Send.PushBack(func(r *request.Request) { + code := 200 + if reqNum == 3 { + code = 404 + r.Error = awserr.New("NotFound", "Not Found", nil) + } + r.HTTPResponse = &http.Response{ + StatusCode: code, + Status: http.StatusText(code), + Body: ioutil.NopCloser(bytes.NewReader([]byte{})), + } + }) + + w := request.Waiter{ + MaxAttempts: 10, + Delay: request.ConstantWaiterDelay(0), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.StatusWaiterMatch, + Argument: "", + Expected: 404, + }, + }, + NewRequest: BuildNewMockRequest(svc, &MockInput{}), + } + + err := w.WaitWithContext(aws.BackgroundContext()) + assert.NoError(t, err) + assert.Equal(t, 3, reqNum) +} + +func TestWaiter_ApplyOptions(t *testing.T) { + w := request.Waiter{} + + logger := aws.NewDefaultLogger() + + w.ApplyOptions( + request.WithWaiterLogger(logger), + request.WithWaiterRequestOptions(request.WithLogLevel(aws.LogDebug)), + request.WithWaiterMaxAttempts(2), + request.WithWaiterDelay(request.ConstantWaiterDelay(5*time.Second)), + ) + + if e, a := logger, w.Logger; e != a { + t.Errorf("expect logger to be set, and match, was not, %v, %v", e, a) + } + + if len(w.RequestOptions) != 1 { + t.Fatalf("expect request options to be set to only a single option, %v", w.RequestOptions) + } + r := request.Request{} + r.ApplyOptions(w.RequestOptions...) + if e, a := aws.LogDebug, r.Config.LogLevel.Value(); e != a { + t.Errorf("expect %v loglevel got %v", e, a) + } + + if e, a := 2, w.MaxAttempts; e != a { + t.Errorf("expect %d retryer max attempts, got %d", e, a) + } + if e, a := 5*time.Second, w.Delay(0); e != a { + t.Errorf("expect %d retryer delay, got %d", e, a) + } +} + +func TestWaiter_WithContextCanceled(t *testing.T) { + c := awstesting.NewClient() + + ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})} + reqCount := 0 + + w := request.Waiter{ + Name: "TestWaiter", + MaxAttempts: 10, + Delay: request.ConstantWaiterDelay(1 * time.Millisecond), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.StatusWaiterMatch, + Expected: 200, + }, + }, + Logger: aws.NewDefaultLogger(), + NewRequest: func(opts []request.Option) (*request.Request, error) { + req := c.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) + req.HTTPResponse = &http.Response{StatusCode: http.StatusNotFound} + req.Handlers.Clear() + req.Data = struct{}{} + req.Handlers.Send.PushBack(func(r *request.Request) { + if reqCount == 1 { + ctx.Error = fmt.Errorf("context canceled") + close(ctx.DoneCh) + } + reqCount++ + }) + + return req, nil + }, + } + + w.SleepWithContext = func(c aws.Context, delay time.Duration) error { + context := c.(*awstesting.FakeContext) + select { + case <-context.DoneCh: + return context.Err() + default: + return nil + } + } + + err := w.WaitWithContext(ctx) + + if err == nil { + t.Fatalf("expect waiter to be canceled.") + } + aerr := err.(awserr.Error) + if e, a := request.CanceledErrorCode, aerr.Code(); e != a { + t.Errorf("expect %q error code, got %q", e, a) + } + if e, a := 2, reqCount; e != a { + t.Errorf("expect %d requests, got %d", e, a) + } +} + +func TestWaiter_WithContext(t *testing.T) { + c := awstesting.NewClient() + + ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})} + reqCount := 0 + + statuses := []int{http.StatusNotFound, http.StatusOK} + + w := request.Waiter{ + Name: "TestWaiter", + MaxAttempts: 10, + Delay: request.ConstantWaiterDelay(1 * time.Millisecond), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.StatusWaiterMatch, + Expected: 200, + }, + }, + Logger: aws.NewDefaultLogger(), + NewRequest: func(opts []request.Option) (*request.Request, error) { + req := c.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) + req.HTTPResponse = &http.Response{StatusCode: statuses[reqCount]} + req.Handlers.Clear() + req.Data = struct{}{} + req.Handlers.Send.PushBack(func(r *request.Request) { + if reqCount == 1 { + ctx.Error = fmt.Errorf("context canceled") + close(ctx.DoneCh) + } + reqCount++ + }) + + return req, nil + }, + } + + err := w.WaitWithContext(ctx) + + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if e, a := 2, reqCount; e != a { + t.Errorf("expect %d requests, got %d", e, a) + } +} + +func TestWaiter_AttemptsExpires(t *testing.T) { + c := awstesting.NewClient() + + ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})} + reqCount := 0 + + w := request.Waiter{ + Name: "TestWaiter", + MaxAttempts: 2, + Delay: request.ConstantWaiterDelay(1 * time.Millisecond), + SleepWithContext: aws.SleepWithContext, + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.StatusWaiterMatch, + Expected: 200, + }, + }, + Logger: aws.NewDefaultLogger(), + NewRequest: func(opts []request.Option) (*request.Request, error) { + req := c.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) + req.HTTPResponse = &http.Response{StatusCode: http.StatusNotFound} + req.Handlers.Clear() + req.Data = struct{}{} + req.Handlers.Send.PushBack(func(r *request.Request) { + reqCount++ + }) + + return req, nil + }, + } + + err := w.WaitWithContext(ctx) + + if err == nil { + t.Fatalf("expect error did not get one") + } + aerr := err.(awserr.Error) + if e, a := request.WaiterResourceNotReadyErrorCode, aerr.Code(); e != a { + t.Errorf("expect %q error code, got %q", e, a) + } + if e, a := 2, reqCount; e != a { + t.Errorf("expect %d requests, got %d", e, a) + } +} + +func TestWaiterNilInput(t *testing.T) { + // Code generation doesn't have a great way to verify the code is correct + // other than being run via unit tests in the SDK. This should be fixed + // So code generation can be validated independently. + + client := s3.New(unit.Session) + client.Handlers.Validate.Clear() + client.Handlers.Send.Clear() // mock sending + client.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &http.Response{ + StatusCode: http.StatusOK, + } + }) + client.Handlers.Unmarshal.Clear() + client.Handlers.UnmarshalMeta.Clear() + client.Handlers.ValidateResponse.Clear() + client.Config.SleepDelay = func(dur time.Duration) {} + + // Ensure waiters do not panic on nil input. It doesn't make sense to + // call a waiter without an input, Validation will + err := client.WaitUntilBucketExists(nil) + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } +} + +func TestWaiterWithContextNilInput(t *testing.T) { + // Code generation doesn't have a great way to verify the code is correct + // other than being run via unit tests in the SDK. This should be fixed + // So code generation can be validated independently. + + client := s3.New(unit.Session) + client.Handlers.Validate.Clear() + client.Handlers.Send.Clear() // mock sending + client.Handlers.Send.PushBack(func(r *request.Request) { + r.HTTPResponse = &http.Response{ + StatusCode: http.StatusOK, + } + }) + client.Handlers.Unmarshal.Clear() + client.Handlers.UnmarshalMeta.Clear() + client.Handlers.ValidateResponse.Clear() + + // Ensure waiters do not panic on nil input + ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})} + err := client.WaitUntilBucketExistsWithContext(ctx, nil, + request.WithWaiterDelay(request.ConstantWaiterDelay(0)), + request.WithWaiterMaxAttempts(1), + ) + if err != nil { + t.Fatalf("expect no error, but got %v", err) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/custom_ca_bundle_test.go b/vendor/github.com/aws/aws-sdk-go/aws/session/custom_ca_bundle_test.go new file mode 100644 index 0000000..a89c0af --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/custom_ca_bundle_test.go @@ -0,0 +1,243 @@ +package session + +import ( + "bytes" + "fmt" + "net" + "net/http" + "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/credentials" + "github.com/aws/aws-sdk-go/awstesting" +) + +var TLSBundleCertFile string +var TLSBundleKeyFile string +var TLSBundleCAFile string + +func TestMain(m *testing.M) { + var err error + + TLSBundleCertFile, TLSBundleKeyFile, TLSBundleCAFile, err = awstesting.CreateTLSBundleFiles() + if err != nil { + panic(err) + } + + fmt.Println("TestMain", TLSBundleCertFile, TLSBundleKeyFile) + + code := m.Run() + + err = awstesting.CleanupTLSBundleFiles(TLSBundleCertFile, TLSBundleKeyFile, TLSBundleCAFile) + if err != nil { + panic(err) + } + + os.Exit(code) +} + +func TestNewSession_WithCustomCABundle_Env(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + os.Setenv("AWS_CA_BUNDLE", TLSBundleCAFile) + + s, err := NewSession(&aws.Config{ + HTTPClient: &http.Client{}, + Endpoint: aws.String(endpoint), + Region: aws.String("mock-region"), + Credentials: credentials.AnonymousCredentials, + }) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if s == nil { + t.Fatalf("expect session to be created, got none") + } + + req, _ := http.NewRequest("GET", *s.Config.Endpoint, nil) + resp, err := s.Config.HTTPClient.Do(req) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if e, a := http.StatusOK, resp.StatusCode; e != a { + t.Errorf("expect %d status code, got %d", e, a) + } +} + +func TestNewSession_WithCustomCABundle_EnvNotExists(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_CA_BUNDLE", "file-not-exists") + + s, err := NewSession() + if err == nil { + t.Fatalf("expect error, got none") + } + if e, a := "LoadCustomCABundleError", err.(awserr.Error).Code(); e != a { + t.Errorf("expect %s error code, got %s", e, a) + } + if s != nil { + t.Errorf("expect nil session, got %v", s) + } +} + +func TestNewSession_WithCustomCABundle_Option(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + s, err := NewSessionWithOptions(Options{ + Config: aws.Config{ + HTTPClient: &http.Client{}, + Endpoint: aws.String(endpoint), + Region: aws.String("mock-region"), + Credentials: credentials.AnonymousCredentials, + }, + CustomCABundle: bytes.NewReader(awstesting.TLSBundleCA), + }) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if s == nil { + t.Fatalf("expect session to be created, got none") + } + + req, _ := http.NewRequest("GET", *s.Config.Endpoint, nil) + resp, err := s.Config.HTTPClient.Do(req) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if e, a := http.StatusOK, resp.StatusCode; e != a { + t.Errorf("expect %d status code, got %d", e, a) + } +} + +func TestNewSession_WithCustomCABundle_OptionPriority(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + os.Setenv("AWS_CA_BUNDLE", "file-not-exists") + + s, err := NewSessionWithOptions(Options{ + Config: aws.Config{ + HTTPClient: &http.Client{}, + Endpoint: aws.String(endpoint), + Region: aws.String("mock-region"), + Credentials: credentials.AnonymousCredentials, + }, + CustomCABundle: bytes.NewReader(awstesting.TLSBundleCA), + }) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if s == nil { + t.Fatalf("expect session to be created, got none") + } + + req, _ := http.NewRequest("GET", *s.Config.Endpoint, nil) + resp, err := s.Config.HTTPClient.Do(req) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if e, a := http.StatusOK, resp.StatusCode; e != a { + t.Errorf("expect %d status code, got %d", e, a) + } +} + +type mockRoundTripper struct{} + +func (m *mockRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { + return nil, nil +} + +func TestNewSession_WithCustomCABundle_UnsupportedTransport(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + s, err := NewSessionWithOptions(Options{ + Config: aws.Config{ + HTTPClient: &http.Client{ + Transport: &mockRoundTripper{}, + }, + }, + CustomCABundle: bytes.NewReader(awstesting.TLSBundleCA), + }) + if err == nil { + t.Fatalf("expect error, got none") + } + if e, a := "LoadCustomCABundleError", err.(awserr.Error).Code(); e != a { + t.Errorf("expect %s error code, got %s", e, a) + } + if s != nil { + t.Errorf("expect nil session, got %v", s) + } + aerrMsg := err.(awserr.Error).Message() + if e, a := "transport unsupported type", aerrMsg; !strings.Contains(a, e) { + t.Errorf("expect %s to be in %s", e, a) + } +} + +func TestNewSession_WithCustomCABundle_TransportSet(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + s, err := NewSessionWithOptions(Options{ + Config: aws.Config{ + Endpoint: aws.String(endpoint), + Region: aws.String("mock-region"), + Credentials: credentials.AnonymousCredentials, + HTTPClient: &http.Client{ + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).Dial, + TLSHandshakeTimeout: 2 * time.Second, + }, + }, + }, + CustomCABundle: bytes.NewReader(awstesting.TLSBundleCA), + }) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if s == nil { + t.Fatalf("expect session to be created, got none") + } + + req, _ := http.NewRequest("GET", *s.Config.Endpoint, nil) + resp, err := s.Config.HTTPClient.Do(req) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + if e, a := http.StatusOK, resp.StatusCode; e != a { + t.Errorf("expect %d status code, got %d", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/doc.go b/vendor/github.com/aws/aws-sdk-go/aws/session/doc.go new file mode 100644 index 0000000..ea7b886 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/doc.go @@ -0,0 +1,273 @@ +/* +Package session provides configuration for the SDK's service clients. + +Sessions can be shared across all service clients that share the same base +configuration. The Session is built from the SDK's default configuration and +request handlers. + +Sessions should be cached when possible, because creating a new Session will +load all configuration values from the environment, and config files each time +the Session is created. Sharing the Session value across all of your service +clients will ensure the configuration is loaded the fewest number of times possible. + +Concurrency + +Sessions are safe to use concurrently as long as the Session is not being +modified. The SDK will not modify the Session once the Session has been created. +Creating service clients concurrently from a shared Session is safe. + +Sessions from Shared Config + +Sessions can be created using the method above that will only load the +additional config if the AWS_SDK_LOAD_CONFIG environment variable is set. +Alternatively you can explicitly create a Session with shared config enabled. +To do this you can use NewSessionWithOptions to configure how the Session will +be created. Using the NewSessionWithOptions with SharedConfigState set to +SharedConfigEnable will create the session as if the AWS_SDK_LOAD_CONFIG +environment variable was set. + +Creating Sessions + +When creating Sessions optional aws.Config values can be passed in that will +override the default, or loaded config values the Session is being created +with. This allows you to provide additional, or case based, configuration +as needed. + +By default NewSession will only load credentials from the shared credentials +file (~/.aws/credentials). If the AWS_SDK_LOAD_CONFIG environment variable is +set to a truthy value the Session will be created from the configuration +values from the shared config (~/.aws/config) and shared credentials +(~/.aws/credentials) files. See the section Sessions from Shared Config for +more information. + +Create a Session with the default config and request handlers. With credentials +region, and profile loaded from the environment and shared config automatically. +Requires the AWS_PROFILE to be set, or "default" is used. + + // Create Session + sess := session.Must(session.NewSession()) + + // Create a Session with a custom region + sess := session.Must(session.NewSession(&aws.Config{ + Region: aws.String("us-east-1"), + })) + + // Create a S3 client instance from a session + sess := session.Must(session.NewSession()) + + svc := s3.New(sess) + +Create Session With Option Overrides + +In addition to NewSession, Sessions can be created using NewSessionWithOptions. +This func allows you to control and override how the Session will be created +through code instead of being driven by environment variables only. + +Use NewSessionWithOptions when you want to provide the config profile, or +override the shared config state (AWS_SDK_LOAD_CONFIG). + + // Equivalent to session.NewSession() + sess := session.Must(session.NewSessionWithOptions(session.Options{ + // Options + })) + + // Specify profile to load for the session's config + sess := session.Must(session.NewSessionWithOptions(session.Options{ + Profile: "profile_name", + })) + + // Specify profile for config and region for requests + sess := session.Must(session.NewSessionWithOptions(session.Options{ + Config: aws.Config{Region: aws.String("us-east-1")}, + Profile: "profile_name", + })) + + // Force enable Shared Config support + sess := session.Must(session.NewSessionWithOptions(session.Options{ + SharedConfigState: session.SharedConfigEnable, + })) + +Adding Handlers + +You can add handlers to a session for processing HTTP requests. All service +clients that use the session inherit the handlers. For example, the following +handler logs every request and its payload made by a service client: + + // Create a session, and add additional handlers for all service + // clients created with the Session to inherit. Adds logging handler. + sess := session.Must(session.NewSession()) + + sess.Handlers.Send.PushFront(func(r *request.Request) { + // Log every request made and its payload + logger.Println("Request: %s/%s, Payload: %s", + r.ClientInfo.ServiceName, r.Operation, r.Params) + }) + +Deprecated "New" function + +The New session function has been deprecated because it does not provide good +way to return errors that occur when loading the configuration files and values. +Because of this, NewSession was created so errors can be retrieved when +creating a session fails. + +Shared Config Fields + +By default the SDK will only load the shared credentials file's (~/.aws/credentials) +credentials values, and all other config is provided by the environment variables, +SDK defaults, and user provided aws.Config values. + +If the AWS_SDK_LOAD_CONFIG environment variable is set, or SharedConfigEnable +option is used to create the Session the full shared config values will be +loaded. This includes credentials, region, and support for assume role. In +addition the Session will load its configuration from both the shared config +file (~/.aws/config) and shared credentials file (~/.aws/credentials). Both +files have the same format. + +If both config files are present the configuration from both files will be +read. The Session will be created from configuration values from the shared +credentials file (~/.aws/credentials) over those in the shared config file (~/.aws/config). + +Credentials are the values the SDK should use for authenticating requests with +AWS Services. They arfrom a configuration file will need to include both +aws_access_key_id and aws_secret_access_key must be provided together in the +same file to be considered valid. The values will be ignored if not a complete +group. aws_session_token is an optional field that can be provided if both of +the other two fields are also provided. + + aws_access_key_id = AKID + aws_secret_access_key = SECRET + aws_session_token = TOKEN + +Assume Role values allow you to configure the SDK to assume an IAM role using +a set of credentials provided in a config file via the source_profile field. +Both "role_arn" and "source_profile" are required. The SDK supports assuming +a role with MFA token if the session option AssumeRoleTokenProvider +is set. + + role_arn = arn:aws:iam:::role/ + source_profile = profile_with_creds + external_id = 1234 + mfa_serial = + role_session_name = session_name + +Region is the region the SDK should use for looking up AWS service endpoints +and signing requests. + + region = us-east-1 + +Assume Role with MFA token + +To create a session with support for assuming an IAM role with MFA set the +session option AssumeRoleTokenProvider to a function that will prompt for the +MFA token code when the SDK assumes the role and refreshes the role's credentials. +This allows you to configure the SDK via the shared config to assumea role +with MFA tokens. + +In order for the SDK to assume a role with MFA the SharedConfigState +session option must be set to SharedConfigEnable, or AWS_SDK_LOAD_CONFIG +environment variable set. + +The shared configuration instructs the SDK to assume an IAM role with MFA +when the mfa_serial configuration field is set in the shared config +(~/.aws/config) or shared credentials (~/.aws/credentials) file. + +If mfa_serial is set in the configuration, the SDK will assume the role, and +the AssumeRoleTokenProvider session option is not set an an error will +be returned when creating the session. + + sess := session.Must(session.NewSessionWithOptions(session.Options{ + AssumeRoleTokenProvider: stscreds.StdinTokenProvider, + })) + + // Create service client value configured for credentials + // from assumed role. + svc := s3.New(sess) + +To setup assume role outside of a session see the stscrds.AssumeRoleProvider +documentation. + +Environment Variables + +When a Session is created several environment variables can be set to adjust +how the SDK functions, and what configuration data it loads when creating +Sessions. All environment values are optional, but some values like credentials +require multiple of the values to set or the partial values will be ignored. +All environment variable values are strings unless otherwise noted. + +Environment configuration values. If set both Access Key ID and Secret Access +Key must be provided. Session Token and optionally also be provided, but is +not required. + + # Access Key ID + AWS_ACCESS_KEY_ID=AKID + AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set. + + # Secret Access Key + AWS_SECRET_ACCESS_KEY=SECRET + AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set. + + # Session Token + AWS_SESSION_TOKEN=TOKEN + +Region value will instruct the SDK where to make service API requests to. If is +not provided in the environment the region must be provided before a service +client request is made. + + AWS_REGION=us-east-1 + + # AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set, + # and AWS_REGION is not also set. + AWS_DEFAULT_REGION=us-east-1 + +Profile name the SDK should load use when loading shared config from the +configuration files. If not provided "default" will be used as the profile name. + + AWS_PROFILE=my_profile + + # AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set, + # and AWS_PROFILE is not also set. + AWS_DEFAULT_PROFILE=my_profile + +SDK load config instructs the SDK to load the shared config in addition to +shared credentials. This also expands the configuration loaded so the shared +credentials will have parity with the shared config file. This also enables +Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE +env values as well. + + AWS_SDK_LOAD_CONFIG=1 + +Shared credentials file path can be set to instruct the SDK to use an alternative +file for the shared credentials. If not set the file will be loaded from +$HOME/.aws/credentials on Linux/Unix based systems, and +%USERPROFILE%\.aws\credentials on Windows. + + AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials + +Shared config file path can be set to instruct the SDK to use an alternative +file for the shared config. If not set the file will be loaded from +$HOME/.aws/config on Linux/Unix based systems, and +%USERPROFILE%\.aws\config on Windows. + + AWS_CONFIG_FILE=$HOME/my_shared_config + +Path to a custom Credentials Authority (CA) bundle PEM file that the SDK +will use instead of the default system's root CA bundle. Use this only +if you want to replace the CA bundle the SDK uses for TLS requests. + + AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle + +Enabling this option will attempt to merge the Transport into the SDK's HTTP +client. If the client's Transport is not a http.Transport an error will be +returned. If the Transport's TLS config is set this option will cause the SDK +to overwrite the Transport's TLS config's RootCAs value. If the CA bundle file +contains multiple certificates all of them will be loaded. + +The Session option CustomCABundle is also available when creating sessions +to also enable this feature. CustomCABundle session option field has priority +over the AWS_CA_BUNDLE environment variable, and will be used if both are set. + +Setting a custom HTTPClient in the aws.Config options will override this setting. +To use this option and custom HTTP client, the HTTP client needs to be provided +when creating the session. Not the service client. +*/ +package session diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go b/vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go new file mode 100644 index 0000000..f1adcf4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go @@ -0,0 +1,191 @@ +package session + +import ( + "os" + "strconv" + + "github.com/aws/aws-sdk-go/aws/credentials" +) + +// EnvProviderName provides a name of the provider when config is loaded from environment. +const EnvProviderName = "EnvConfigCredentials" + +// envConfig is a collection of environment values the SDK will read +// setup config from. All environment values are optional. But some values +// such as credentials require multiple values to be complete or the values +// will be ignored. +type envConfig struct { + // Environment configuration values. If set both Access Key ID and Secret Access + // Key must be provided. Session Token and optionally also be provided, but is + // not required. + // + // # Access Key ID + // AWS_ACCESS_KEY_ID=AKID + // AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set. + // + // # Secret Access Key + // AWS_SECRET_ACCESS_KEY=SECRET + // AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set. + // + // # Session Token + // AWS_SESSION_TOKEN=TOKEN + Creds credentials.Value + + // Region value will instruct the SDK where to make service API requests to. If is + // not provided in the environment the region must be provided before a service + // client request is made. + // + // AWS_REGION=us-east-1 + // + // # AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set, + // # and AWS_REGION is not also set. + // AWS_DEFAULT_REGION=us-east-1 + Region string + + // Profile name the SDK should load use when loading shared configuration from the + // shared configuration files. If not provided "default" will be used as the + // profile name. + // + // AWS_PROFILE=my_profile + // + // # AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set, + // # and AWS_PROFILE is not also set. + // AWS_DEFAULT_PROFILE=my_profile + Profile string + + // SDK load config instructs the SDK to load the shared config in addition to + // shared credentials. This also expands the configuration loaded from the shared + // credentials to have parity with the shared config file. This also enables + // Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE + // env values as well. + // + // AWS_SDK_LOAD_CONFIG=1 + EnableSharedConfig bool + + // Shared credentials file path can be set to instruct the SDK to use an alternate + // file for the shared credentials. If not set the file will be loaded from + // $HOME/.aws/credentials on Linux/Unix based systems, and + // %USERPROFILE%\.aws\credentials on Windows. + // + // AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials + SharedCredentialsFile string + + // Shared config file path can be set to instruct the SDK to use an alternate + // file for the shared config. If not set the file will be loaded from + // $HOME/.aws/config on Linux/Unix based systems, and + // %USERPROFILE%\.aws\config on Windows. + // + // AWS_CONFIG_FILE=$HOME/my_shared_config + SharedConfigFile string + + // Sets the path to a custom Credentials Authroity (CA) Bundle PEM file + // that the SDK will use instead of the system's root CA bundle. + // Only use this if you want to configure the SDK to use a custom set + // of CAs. + // + // Enabling this option will attempt to merge the Transport + // into the SDK's HTTP client. If the client's Transport is + // not a http.Transport an error will be returned. If the + // Transport's TLS config is set this option will cause the + // SDK to overwrite the Transport's TLS config's RootCAs value. + // + // Setting a custom HTTPClient in the aws.Config options will override this setting. + // To use this option and custom HTTP client, the HTTP client needs to be provided + // when creating the session. Not the service client. + // + // AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle + CustomCABundle string +} + +var ( + credAccessEnvKey = []string{ + "AWS_ACCESS_KEY_ID", + "AWS_ACCESS_KEY", + } + credSecretEnvKey = []string{ + "AWS_SECRET_ACCESS_KEY", + "AWS_SECRET_KEY", + } + credSessionEnvKey = []string{ + "AWS_SESSION_TOKEN", + } + + regionEnvKeys = []string{ + "AWS_REGION", + "AWS_DEFAULT_REGION", // Only read if AWS_SDK_LOAD_CONFIG is also set + } + profileEnvKeys = []string{ + "AWS_PROFILE", + "AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set + } + sharedCredsFileEnvKey = []string{ + "AWS_SHARED_CREDENTIALS_FILE", + } + sharedConfigFileEnvKey = []string{ + "AWS_CONFIG_FILE", + } +) + +// loadEnvConfig retrieves the SDK's environment configuration. +// See `envConfig` for the values that will be retrieved. +// +// If the environment variable `AWS_SDK_LOAD_CONFIG` is set to a truthy value +// the shared SDK config will be loaded in addition to the SDK's specific +// configuration values. +func loadEnvConfig() envConfig { + enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG")) + return envConfigLoad(enableSharedConfig) +} + +// loadEnvSharedConfig retrieves the SDK's environment configuration, and the +// SDK shared config. See `envConfig` for the values that will be retrieved. +// +// Loads the shared configuration in addition to the SDK's specific configuration. +// This will load the same values as `loadEnvConfig` if the `AWS_SDK_LOAD_CONFIG` +// environment variable is set. +func loadSharedEnvConfig() envConfig { + return envConfigLoad(true) +} + +func envConfigLoad(enableSharedConfig bool) envConfig { + cfg := envConfig{} + + cfg.EnableSharedConfig = enableSharedConfig + + setFromEnvVal(&cfg.Creds.AccessKeyID, credAccessEnvKey) + setFromEnvVal(&cfg.Creds.SecretAccessKey, credSecretEnvKey) + setFromEnvVal(&cfg.Creds.SessionToken, credSessionEnvKey) + + // Require logical grouping of credentials + if len(cfg.Creds.AccessKeyID) == 0 || len(cfg.Creds.SecretAccessKey) == 0 { + cfg.Creds = credentials.Value{} + } else { + cfg.Creds.ProviderName = EnvProviderName + } + + regionKeys := regionEnvKeys + profileKeys := profileEnvKeys + if !cfg.EnableSharedConfig { + regionKeys = regionKeys[:1] + profileKeys = profileKeys[:1] + } + + setFromEnvVal(&cfg.Region, regionKeys) + setFromEnvVal(&cfg.Profile, profileKeys) + + setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey) + setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey) + + cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE") + + return cfg +} + +func setFromEnvVal(dst *string, keys []string) { + for _, k := range keys { + if v := os.Getenv(k); len(v) > 0 { + *dst = v + break + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/env_config_test.go b/vendor/github.com/aws/aws-sdk-go/aws/session/env_config_test.go new file mode 100644 index 0000000..10e3662 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/env_config_test.go @@ -0,0 +1,279 @@ +package session + +import ( + "os" + "reflect" + "testing" + + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/awstesting" +) + +func TestLoadEnvConfig_Creds(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + cases := []struct { + Env map[string]string + Val credentials.Value + }{ + { + Env: map[string]string{ + "AWS_ACCESS_KEY": "AKID", + }, + Val: credentials.Value{}, + }, + { + Env: map[string]string{ + "AWS_ACCESS_KEY_ID": "AKID", + }, + Val: credentials.Value{}, + }, + { + Env: map[string]string{ + "AWS_SECRET_KEY": "SECRET", + }, + Val: credentials.Value{}, + }, + { + Env: map[string]string{ + "AWS_SECRET_ACCESS_KEY": "SECRET", + }, + Val: credentials.Value{}, + }, + { + Env: map[string]string{ + "AWS_ACCESS_KEY_ID": "AKID", + "AWS_SECRET_ACCESS_KEY": "SECRET", + }, + Val: credentials.Value{ + AccessKeyID: "AKID", SecretAccessKey: "SECRET", + ProviderName: "EnvConfigCredentials", + }, + }, + { + Env: map[string]string{ + "AWS_ACCESS_KEY": "AKID", + "AWS_SECRET_KEY": "SECRET", + }, + Val: credentials.Value{ + AccessKeyID: "AKID", SecretAccessKey: "SECRET", + ProviderName: "EnvConfigCredentials", + }, + }, + { + Env: map[string]string{ + "AWS_ACCESS_KEY": "AKID", + "AWS_SECRET_KEY": "SECRET", + "AWS_SESSION_TOKEN": "TOKEN", + }, + Val: credentials.Value{ + AccessKeyID: "AKID", SecretAccessKey: "SECRET", SessionToken: "TOKEN", + ProviderName: "EnvConfigCredentials", + }, + }, + } + + for _, c := range cases { + os.Clearenv() + + for k, v := range c.Env { + os.Setenv(k, v) + } + + cfg := loadEnvConfig() + if !reflect.DeepEqual(c.Val, cfg.Creds) { + t.Errorf("expect credentials to match.\n%s", + awstesting.SprintExpectActual(c.Val, cfg.Creds)) + } + } +} + +func TestLoadEnvConfig(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + cases := []struct { + Env map[string]string + UseSharedConfigCall bool + Config envConfig + }{ + { + Env: map[string]string{ + "AWS_REGION": "region", + "AWS_PROFILE": "profile", + }, + Config: envConfig{ + Region: "region", Profile: "profile", + }, + }, + { + Env: map[string]string{ + "AWS_REGION": "region", + "AWS_DEFAULT_REGION": "default_region", + "AWS_PROFILE": "profile", + "AWS_DEFAULT_PROFILE": "default_profile", + }, + Config: envConfig{ + Region: "region", Profile: "profile", + }, + }, + { + Env: map[string]string{ + "AWS_REGION": "region", + "AWS_DEFAULT_REGION": "default_region", + "AWS_PROFILE": "profile", + "AWS_DEFAULT_PROFILE": "default_profile", + "AWS_SDK_LOAD_CONFIG": "1", + }, + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, + }, + { + Env: map[string]string{ + "AWS_DEFAULT_REGION": "default_region", + "AWS_DEFAULT_PROFILE": "default_profile", + }, + }, + { + Env: map[string]string{ + "AWS_DEFAULT_REGION": "default_region", + "AWS_DEFAULT_PROFILE": "default_profile", + "AWS_SDK_LOAD_CONFIG": "1", + }, + Config: envConfig{ + Region: "default_region", Profile: "default_profile", + EnableSharedConfig: true, + }, + }, + { + Env: map[string]string{ + "AWS_REGION": "region", + "AWS_PROFILE": "profile", + }, + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, + UseSharedConfigCall: true, + }, + { + Env: map[string]string{ + "AWS_REGION": "region", + "AWS_DEFAULT_REGION": "default_region", + "AWS_PROFILE": "profile", + "AWS_DEFAULT_PROFILE": "default_profile", + }, + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, + UseSharedConfigCall: true, + }, + { + Env: map[string]string{ + "AWS_REGION": "region", + "AWS_DEFAULT_REGION": "default_region", + "AWS_PROFILE": "profile", + "AWS_DEFAULT_PROFILE": "default_profile", + "AWS_SDK_LOAD_CONFIG": "1", + }, + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, + UseSharedConfigCall: true, + }, + { + Env: map[string]string{ + "AWS_DEFAULT_REGION": "default_region", + "AWS_DEFAULT_PROFILE": "default_profile", + }, + Config: envConfig{ + Region: "default_region", Profile: "default_profile", + EnableSharedConfig: true, + }, + UseSharedConfigCall: true, + }, + { + Env: map[string]string{ + "AWS_DEFAULT_REGION": "default_region", + "AWS_DEFAULT_PROFILE": "default_profile", + "AWS_SDK_LOAD_CONFIG": "1", + }, + Config: envConfig{ + Region: "default_region", Profile: "default_profile", + EnableSharedConfig: true, + }, + UseSharedConfigCall: true, + }, + { + Env: map[string]string{ + "AWS_CA_BUNDLE": "custom_ca_bundle", + }, + Config: envConfig{ + CustomCABundle: "custom_ca_bundle", + }, + }, + { + Env: map[string]string{ + "AWS_CA_BUNDLE": "custom_ca_bundle", + }, + Config: envConfig{ + CustomCABundle: "custom_ca_bundle", + EnableSharedConfig: true, + }, + UseSharedConfigCall: true, + }, + { + Env: map[string]string{ + "AWS_SHARED_CREDENTIALS_FILE": "/path/to/credentials/file", + "AWS_CONFIG_FILE": "/path/to/config/file", + }, + Config: envConfig{ + SharedCredentialsFile: "/path/to/credentials/file", + SharedConfigFile: "/path/to/config/file", + }, + }, + } + + for _, c := range cases { + os.Clearenv() + + for k, v := range c.Env { + os.Setenv(k, v) + } + + var cfg envConfig + if c.UseSharedConfigCall { + cfg = loadSharedEnvConfig() + } else { + cfg = loadEnvConfig() + } + + if !reflect.DeepEqual(c.Config, cfg) { + t.Errorf("expect config to match.\n%s", + awstesting.SprintExpectActual(c.Config, cfg)) + } + } +} + +func TestSetEnvValue(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("empty_key", "") + os.Setenv("second_key", "2") + os.Setenv("third_key", "3") + + var dst string + setFromEnvVal(&dst, []string{ + "empty_key", "first_key", "second_key", "third_key", + }) + + if e, a := "2", dst; e != a { + t.Errorf("expect %s value from environment, got %s", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/session.go b/vendor/github.com/aws/aws-sdk-go/aws/session/session.go new file mode 100644 index 0000000..9f75d5a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/session.go @@ -0,0 +1,606 @@ +package session + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + + "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/corehandlers" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/credentials/stscreds" + "github.com/aws/aws-sdk-go/aws/defaults" + "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/aws/aws-sdk-go/aws/request" +) + +// A Session provides a central location to create service clients from and +// store configurations and request handlers for those services. +// +// Sessions are safe to create service clients concurrently, but it is not safe +// to mutate the Session concurrently. +// +// The Session satisfies the service client's client.ClientConfigProvider. +type Session struct { + Config *aws.Config + Handlers request.Handlers +} + +// New creates a new instance of the handlers merging in the provided configs +// on top of the SDK's default configurations. Once the Session is created it +// can be mutated to modify the Config or Handlers. The Session is safe to be +// read concurrently, but it should not be written to concurrently. +// +// If the AWS_SDK_LOAD_CONFIG environment is set to a truthy value, the New +// method could now encounter an error when loading the configuration. When +// The environment variable is set, and an error occurs, New will return a +// session that will fail all requests reporting the error that occurred while +// loading the session. Use NewSession to get the error when creating the +// session. +// +// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value +// the shared config file (~/.aws/config) will also be loaded, in addition to +// the shared credentials file (~/.aws/credentials). Values set in both the +// shared config, and shared credentials will be taken from the shared +// credentials file. +// +// Deprecated: Use NewSession functions to create sessions instead. NewSession +// has the same functionality as New except an error can be returned when the +// func is called instead of waiting to receive an error until a request is made. +func New(cfgs ...*aws.Config) *Session { + // load initial config from environment + envCfg := loadEnvConfig() + + if envCfg.EnableSharedConfig { + s, err := newSession(Options{}, envCfg, cfgs...) + if err != nil { + // Old session.New expected all errors to be discovered when + // a request is made, and would report the errors then. This + // needs to be replicated if an error occurs while creating + // the session. + msg := "failed to create session with AWS_SDK_LOAD_CONFIG enabled. " + + "Use session.NewSession to handle errors occurring during session creation." + + // Session creation failed, need to report the error and prevent + // any requests from succeeding. + s = &Session{Config: defaults.Config()} + s.Config.MergeIn(cfgs...) + s.Config.Logger.Log("ERROR:", msg, "Error:", err) + s.Handlers.Validate.PushBack(func(r *request.Request) { + r.Error = err + }) + } + return s + } + + return deprecatedNewSession(cfgs...) +} + +// NewSession returns a new Session created from SDK defaults, config files, +// environment, and user provided config files. Once the Session is created +// it can be mutated to modify the Config or Handlers. The Session is safe to +// be read concurrently, but it should not be written to concurrently. +// +// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value +// the shared config file (~/.aws/config) will also be loaded in addition to +// the shared credentials file (~/.aws/credentials). Values set in both the +// shared config, and shared credentials will be taken from the shared +// credentials file. Enabling the Shared Config will also allow the Session +// to be built with retrieving credentials with AssumeRole set in the config. +// +// See the NewSessionWithOptions func for information on how to override or +// control through code how the Session will be created. Such as specifying the +// config profile, and controlling if shared config is enabled or not. +func NewSession(cfgs ...*aws.Config) (*Session, error) { + opts := Options{} + opts.Config.MergeIn(cfgs...) + + return NewSessionWithOptions(opts) +} + +// SharedConfigState provides the ability to optionally override the state +// of the session's creation based on the shared config being enabled or +// disabled. +type SharedConfigState int + +const ( + // SharedConfigStateFromEnv does not override any state of the + // AWS_SDK_LOAD_CONFIG env var. It is the default value of the + // SharedConfigState type. + SharedConfigStateFromEnv SharedConfigState = iota + + // SharedConfigDisable overrides the AWS_SDK_LOAD_CONFIG env var value + // and disables the shared config functionality. + SharedConfigDisable + + // SharedConfigEnable overrides the AWS_SDK_LOAD_CONFIG env var value + // and enables the shared config functionality. + SharedConfigEnable +) + +// Options provides the means to control how a Session is created and what +// configuration values will be loaded. +// +type Options struct { + // Provides config values for the SDK to use when creating service clients + // and making API requests to services. Any value set in with this field + // will override the associated value provided by the SDK defaults, + // environment or config files where relevant. + // + // If not set, configuration values from from SDK defaults, environment, + // config will be used. + Config aws.Config + + // Overrides the config profile the Session should be created from. If not + // set the value of the environment variable will be loaded (AWS_PROFILE, + // or AWS_DEFAULT_PROFILE if the Shared Config is enabled). + // + // If not set and environment variables are not set the "default" + // (DefaultSharedConfigProfile) will be used as the profile to load the + // session config from. + Profile string + + // Instructs how the Session will be created based on the AWS_SDK_LOAD_CONFIG + // environment variable. By default a Session will be created using the + // value provided by the AWS_SDK_LOAD_CONFIG environment variable. + // + // Setting this value to SharedConfigEnable or SharedConfigDisable + // will allow you to override the AWS_SDK_LOAD_CONFIG environment variable + // and enable or disable the shared config functionality. + SharedConfigState SharedConfigState + + // Ordered list of files the session will load configuration from. + // It will override environment variable AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE. + SharedConfigFiles []string + + // When the SDK's shared config is configured to assume a role with MFA + // this option is required in order to provide the mechanism that will + // retrieve the MFA token. There is no default value for this field. If + // it is not set an error will be returned when creating the session. + // + // This token provider will be called when ever the assumed role's + // credentials need to be refreshed. Within the context of service clients + // all sharing the same session the SDK will ensure calls to the token + // provider are atomic. When sharing a token provider across multiple + // sessions additional synchronization logic is needed to ensure the + // token providers do not introduce race conditions. It is recommend to + // share the session where possible. + // + // stscreds.StdinTokenProvider is a basic implementation that will prompt + // from stdin for the MFA token code. + // + // This field is only used if the shared configuration is enabled, and + // the config enables assume role wit MFA via the mfa_serial field. + AssumeRoleTokenProvider func() (string, error) + + // Reader for a custom Credentials Authority (CA) bundle in PEM format that + // the SDK will use instead of the default system's root CA bundle. Use this + // only if you want to replace the CA bundle the SDK uses for TLS requests. + // + // Enabling this option will attempt to merge the Transport into the SDK's HTTP + // client. If the client's Transport is not a http.Transport an error will be + // returned. If the Transport's TLS config is set this option will cause the SDK + // to overwrite the Transport's TLS config's RootCAs value. If the CA + // bundle reader contains multiple certificates all of them will be loaded. + // + // The Session option CustomCABundle is also available when creating sessions + // to also enable this feature. CustomCABundle session option field has priority + // over the AWS_CA_BUNDLE environment variable, and will be used if both are set. + CustomCABundle io.Reader +} + +// NewSessionWithOptions returns a new Session created from SDK defaults, config files, +// environment, and user provided config files. This func uses the Options +// values to configure how the Session is created. +// +// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value +// the shared config file (~/.aws/config) will also be loaded in addition to +// the shared credentials file (~/.aws/credentials). Values set in both the +// shared config, and shared credentials will be taken from the shared +// credentials file. Enabling the Shared Config will also allow the Session +// to be built with retrieving credentials with AssumeRole set in the config. +// +// // Equivalent to session.New +// sess := session.Must(session.NewSessionWithOptions(session.Options{})) +// +// // Specify profile to load for the session's config +// sess := session.Must(session.NewSessionWithOptions(session.Options{ +// Profile: "profile_name", +// })) +// +// // Specify profile for config and region for requests +// sess := session.Must(session.NewSessionWithOptions(session.Options{ +// Config: aws.Config{Region: aws.String("us-east-1")}, +// Profile: "profile_name", +// })) +// +// // Force enable Shared Config support +// sess := session.Must(session.NewSessionWithOptions(session.Options{ +// SharedConfigState: session.SharedConfigEnable, +// })) +func NewSessionWithOptions(opts Options) (*Session, error) { + var envCfg envConfig + if opts.SharedConfigState == SharedConfigEnable { + envCfg = loadSharedEnvConfig() + } else { + envCfg = loadEnvConfig() + } + + if len(opts.Profile) > 0 { + envCfg.Profile = opts.Profile + } + + switch opts.SharedConfigState { + case SharedConfigDisable: + envCfg.EnableSharedConfig = false + case SharedConfigEnable: + envCfg.EnableSharedConfig = true + } + + if len(envCfg.SharedCredentialsFile) == 0 { + envCfg.SharedCredentialsFile = defaults.SharedCredentialsFilename() + } + if len(envCfg.SharedConfigFile) == 0 { + envCfg.SharedConfigFile = defaults.SharedConfigFilename() + } + + // Only use AWS_CA_BUNDLE if session option is not provided. + if len(envCfg.CustomCABundle) != 0 && opts.CustomCABundle == nil { + f, err := os.Open(envCfg.CustomCABundle) + if err != nil { + return nil, awserr.New("LoadCustomCABundleError", + "failed to open custom CA bundle PEM file", err) + } + defer f.Close() + opts.CustomCABundle = f + } + + return newSession(opts, envCfg, &opts.Config) +} + +// Must is a helper function to ensure the Session is valid and there was no +// error when calling a NewSession function. +// +// This helper is intended to be used in variable initialization to load the +// Session and configuration at startup. Such as: +// +// var sess = session.Must(session.NewSession()) +func Must(sess *Session, err error) *Session { + if err != nil { + panic(err) + } + + return sess +} + +func deprecatedNewSession(cfgs ...*aws.Config) *Session { + cfg := defaults.Config() + handlers := defaults.Handlers() + + // Apply the passed in configs so the configuration can be applied to the + // default credential chain + cfg.MergeIn(cfgs...) + if cfg.EndpointResolver == nil { + // An endpoint resolver is required for a session to be able to provide + // endpoints for service client configurations. + cfg.EndpointResolver = endpoints.DefaultResolver() + } + cfg.Credentials = defaults.CredChain(cfg, handlers) + + // Reapply any passed in configs to override credentials if set + cfg.MergeIn(cfgs...) + + s := &Session{ + Config: cfg, + Handlers: handlers, + } + + initHandlers(s) + + return s +} + +func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, error) { + cfg := defaults.Config() + handlers := defaults.Handlers() + + // Get a merged version of the user provided config to determine if + // credentials were. + userCfg := &aws.Config{} + userCfg.MergeIn(cfgs...) + + // Ordered config files will be loaded in with later files overwriting + // previous config file values. + var cfgFiles []string + if opts.SharedConfigFiles != nil { + cfgFiles = opts.SharedConfigFiles + } else { + cfgFiles = []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile} + if !envCfg.EnableSharedConfig { + // The shared config file (~/.aws/config) is only loaded if instructed + // to load via the envConfig.EnableSharedConfig (AWS_SDK_LOAD_CONFIG). + cfgFiles = cfgFiles[1:] + } + } + + // Load additional config from file(s) + sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles) + if err != nil { + return nil, err + } + + if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil { + return nil, err + } + + s := &Session{ + Config: cfg, + Handlers: handlers, + } + + initHandlers(s) + + // Setup HTTP client with custom cert bundle if enabled + if opts.CustomCABundle != nil { + if err := loadCustomCABundle(s, opts.CustomCABundle); err != nil { + return nil, err + } + } + + return s, nil +} + +func loadCustomCABundle(s *Session, bundle io.Reader) error { + var t *http.Transport + switch v := s.Config.HTTPClient.Transport.(type) { + case *http.Transport: + t = v + default: + if s.Config.HTTPClient.Transport != nil { + return awserr.New("LoadCustomCABundleError", + "unable to load custom CA bundle, HTTPClient's transport unsupported type", nil) + } + } + if t == nil { + t = &http.Transport{} + } + + p, err := loadCertPool(bundle) + if err != nil { + return err + } + if t.TLSClientConfig == nil { + t.TLSClientConfig = &tls.Config{} + } + t.TLSClientConfig.RootCAs = p + + s.Config.HTTPClient.Transport = t + + return nil +} + +func loadCertPool(r io.Reader) (*x509.CertPool, error) { + b, err := ioutil.ReadAll(r) + if err != nil { + return nil, awserr.New("LoadCustomCABundleError", + "failed to read custom CA bundle PEM file", err) + } + + p := x509.NewCertPool() + if !p.AppendCertsFromPEM(b) { + return nil, awserr.New("LoadCustomCABundleError", + "failed to load custom CA bundle PEM file", err) + } + + return p, nil +} + +func mergeConfigSrcs(cfg, userCfg *aws.Config, envCfg envConfig, sharedCfg sharedConfig, handlers request.Handlers, sessOpts Options) error { + // Merge in user provided configuration + cfg.MergeIn(userCfg) + + // Region if not already set by user + if len(aws.StringValue(cfg.Region)) == 0 { + if len(envCfg.Region) > 0 { + cfg.WithRegion(envCfg.Region) + } else if envCfg.EnableSharedConfig && len(sharedCfg.Region) > 0 { + cfg.WithRegion(sharedCfg.Region) + } + } + + // Configure credentials if not already set + if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil { + if len(envCfg.Creds.AccessKeyID) > 0 { + cfg.Credentials = credentials.NewStaticCredentialsFromCreds( + envCfg.Creds, + ) + } else if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.RoleARN) > 0 && sharedCfg.AssumeRoleSource != nil { + cfgCp := *cfg + cfgCp.Credentials = credentials.NewStaticCredentialsFromCreds( + sharedCfg.AssumeRoleSource.Creds, + ) + if len(sharedCfg.AssumeRole.MFASerial) > 0 && sessOpts.AssumeRoleTokenProvider == nil { + // AssumeRole Token provider is required if doing Assume Role + // with MFA. + return AssumeRoleTokenProviderNotSetError{} + } + cfg.Credentials = stscreds.NewCredentials( + &Session{ + Config: &cfgCp, + Handlers: handlers.Copy(), + }, + sharedCfg.AssumeRole.RoleARN, + func(opt *stscreds.AssumeRoleProvider) { + opt.RoleSessionName = sharedCfg.AssumeRole.RoleSessionName + + // Assume role with external ID + if len(sharedCfg.AssumeRole.ExternalID) > 0 { + opt.ExternalID = aws.String(sharedCfg.AssumeRole.ExternalID) + } + + // Assume role with MFA + if len(sharedCfg.AssumeRole.MFASerial) > 0 { + opt.SerialNumber = aws.String(sharedCfg.AssumeRole.MFASerial) + opt.TokenProvider = sessOpts.AssumeRoleTokenProvider + } + }, + ) + } else if len(sharedCfg.Creds.AccessKeyID) > 0 { + cfg.Credentials = credentials.NewStaticCredentialsFromCreds( + sharedCfg.Creds, + ) + } else { + // Fallback to default credentials provider, include mock errors + // for the credential chain so user can identify why credentials + // failed to be retrieved. + cfg.Credentials = credentials.NewCredentials(&credentials.ChainProvider{ + VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors), + Providers: []credentials.Provider{ + &credProviderError{Err: awserr.New("EnvAccessKeyNotFound", "failed to find credentials in the environment.", nil)}, + &credProviderError{Err: awserr.New("SharedCredsLoad", fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil)}, + defaults.RemoteCredProvider(*cfg, handlers), + }, + }) + } + } + + return nil +} + +// AssumeRoleTokenProviderNotSetError is an error returned when creating a session when the +// MFAToken option is not set when shared config is configured load assume a +// role with an MFA token. +type AssumeRoleTokenProviderNotSetError struct{} + +// Code is the short id of the error. +func (e AssumeRoleTokenProviderNotSetError) Code() string { + return "AssumeRoleTokenProviderNotSetError" +} + +// Message is the description of the error +func (e AssumeRoleTokenProviderNotSetError) Message() string { + return fmt.Sprintf("assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.") +} + +// OrigErr is the underlying error that caused the failure. +func (e AssumeRoleTokenProviderNotSetError) OrigErr() error { + return nil +} + +// Error satisfies the error interface. +func (e AssumeRoleTokenProviderNotSetError) Error() string { + return awserr.SprintError(e.Code(), e.Message(), "", nil) +} + +type credProviderError struct { + Err error +} + +var emptyCreds = credentials.Value{} + +func (c credProviderError) Retrieve() (credentials.Value, error) { + return credentials.Value{}, c.Err +} +func (c credProviderError) IsExpired() bool { + return true +} + +func initHandlers(s *Session) { + // Add the Validate parameter handler if it is not disabled. + s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler) + if !aws.BoolValue(s.Config.DisableParamValidation) { + s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler) + } +} + +// Copy creates and returns a copy of the current Session, coping the config +// and handlers. If any additional configs are provided they will be merged +// on top of the Session's copied config. +// +// // Create a copy of the current Session, configured for the us-west-2 region. +// sess.Copy(&aws.Config{Region: aws.String("us-west-2")}) +func (s *Session) Copy(cfgs ...*aws.Config) *Session { + newSession := &Session{ + Config: s.Config.Copy(cfgs...), + Handlers: s.Handlers.Copy(), + } + + initHandlers(newSession) + + return newSession +} + +// ClientConfig satisfies the client.ConfigProvider interface and is used to +// configure the service client instances. Passing the Session to the service +// client's constructor (New) will use this method to configure the client. +func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config { + // Backwards compatibility, the error will be eaten if user calls ClientConfig + // directly. All SDK services will use ClientconfigWithError. + cfg, _ := s.clientConfigWithErr(serviceName, cfgs...) + + return cfg +} + +func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (client.Config, error) { + s = s.Copy(cfgs...) + + var resolved endpoints.ResolvedEndpoint + var err error + + region := aws.StringValue(s.Config.Region) + + if endpoint := aws.StringValue(s.Config.Endpoint); len(endpoint) != 0 { + resolved.URL = endpoints.AddScheme(endpoint, aws.BoolValue(s.Config.DisableSSL)) + resolved.SigningRegion = region + } else { + resolved, err = s.Config.EndpointResolver.EndpointFor( + serviceName, region, + func(opt *endpoints.Options) { + opt.DisableSSL = aws.BoolValue(s.Config.DisableSSL) + opt.UseDualStack = aws.BoolValue(s.Config.UseDualStack) + + // Support the condition where the service is modeled but its + // endpoint metadata is not available. + opt.ResolveUnknownService = true + }, + ) + } + + return client.Config{ + Config: s.Config, + Handlers: s.Handlers, + Endpoint: resolved.URL, + SigningRegion: resolved.SigningRegion, + SigningName: resolved.SigningName, + }, err +} + +// ClientConfigNoResolveEndpoint is the same as ClientConfig with the exception +// that the EndpointResolver will not be used to resolve the endpoint. The only +// endpoint set must come from the aws.Config.Endpoint field. +func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Config { + s = s.Copy(cfgs...) + + var resolved endpoints.ResolvedEndpoint + + region := aws.StringValue(s.Config.Region) + + if ep := aws.StringValue(s.Config.Endpoint); len(ep) > 0 { + resolved.URL = endpoints.AddScheme(ep, aws.BoolValue(s.Config.DisableSSL)) + resolved.SigningRegion = region + } + + return client.Config{ + Config: s.Config, + Handlers: s.Handlers, + Endpoint: resolved.URL, + SigningRegion: resolved.SigningRegion, + SigningName: resolved.SigningName, + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/session_test.go b/vendor/github.com/aws/aws-sdk-go/aws/session/session_test.go new file mode 100644 index 0000000..9612b31 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/session_test.go @@ -0,0 +1,446 @@ +package session + +import ( + "bytes" + "fmt" + "net/http" + "net/http/httptest" + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/defaults" + "github.com/aws/aws-sdk-go/aws/endpoints" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/service/s3" +) + +func TestNewDefaultSession(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + s := New(&aws.Config{Region: aws.String("region")}) + + assert.Equal(t, "region", *s.Config.Region) + assert.Equal(t, http.DefaultClient, s.Config.HTTPClient) + assert.NotNil(t, s.Config.Logger) + assert.Equal(t, aws.LogOff, *s.Config.LogLevel) +} + +func TestNew_WithCustomCreds(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + customCreds := credentials.NewStaticCredentials("AKID", "SECRET", "TOKEN") + s := New(&aws.Config{Credentials: customCreds}) + + assert.Equal(t, customCreds, s.Config.Credentials) +} + +type mockLogger struct { + *bytes.Buffer +} + +func (w mockLogger) Log(args ...interface{}) { + fmt.Fprintln(w, args...) +} + +func TestNew_WithSessionLoadError(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_CONFIG_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "assume_role_invalid_source_profile") + + logger := bytes.Buffer{} + s := New(&aws.Config{Logger: &mockLogger{&logger}}) + + assert.NotNil(t, s) + + svc := s3.New(s) + _, err := svc.ListBuckets(&s3.ListBucketsInput{}) + + assert.Error(t, err) + assert.Contains(t, logger.String(), "ERROR: failed to create session with AWS_SDK_LOAD_CONFIG enabled") + assert.Contains(t, err.Error(), SharedConfigAssumeRoleError{ + RoleARN: "assume_role_invalid_source_profile_role_arn", + }.Error()) +} + +func TestSessionCopy(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_REGION", "orig_region") + + s := Session{ + Config: defaults.Config(), + Handlers: defaults.Handlers(), + } + + newSess := s.Copy(&aws.Config{Region: aws.String("new_region")}) + + assert.Equal(t, "orig_region", *s.Config.Region) + assert.Equal(t, "new_region", *newSess.Config.Region) +} + +func TestSessionClientConfig(t *testing.T) { + s, err := NewSession(&aws.Config{ + Credentials: credentials.AnonymousCredentials, + Region: aws.String("orig_region"), + EndpointResolver: endpoints.ResolverFunc( + func(service, region string, opts ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) { + if e, a := "mock-service", service; e != a { + t.Errorf("expect %q service, got %q", e, a) + } + if e, a := "other-region", region; e != a { + t.Errorf("expect %q region, got %q", e, a) + } + return endpoints.ResolvedEndpoint{ + URL: "https://" + service + "." + region + ".amazonaws.com", + SigningRegion: region, + }, nil + }, + ), + }) + assert.NoError(t, err) + + cfg := s.ClientConfig("mock-service", &aws.Config{Region: aws.String("other-region")}) + + assert.Equal(t, "https://mock-service.other-region.amazonaws.com", cfg.Endpoint) + assert.Equal(t, "other-region", cfg.SigningRegion) + assert.Equal(t, "other-region", *cfg.Config.Region) +} + +func TestNewSession_NoCredentials(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + s, err := NewSession() + assert.NoError(t, err) + + assert.NotNil(t, s.Config.Credentials) + assert.NotEqual(t, credentials.AnonymousCredentials, s.Config.Credentials) +} + +func TestNewSessionWithOptions_OverrideProfile(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "other_profile") + + s, err := NewSessionWithOptions(Options{ + Profile: "full_profile", + }) + assert.NoError(t, err) + + assert.Equal(t, "full_profile_region", *s.Config.Region) + + creds, err := s.Config.Credentials.Get() + assert.NoError(t, err) + assert.Equal(t, "full_profile_akid", creds.AccessKeyID) + assert.Equal(t, "full_profile_secret", creds.SecretAccessKey) + assert.Empty(t, creds.SessionToken) + assert.Contains(t, creds.ProviderName, "SharedConfigCredentials") +} + +func TestNewSessionWithOptions_OverrideSharedConfigEnable(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_SDK_LOAD_CONFIG", "0") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "full_profile") + + s, err := NewSessionWithOptions(Options{ + SharedConfigState: SharedConfigEnable, + }) + assert.NoError(t, err) + + assert.Equal(t, "full_profile_region", *s.Config.Region) + + creds, err := s.Config.Credentials.Get() + assert.NoError(t, err) + assert.Equal(t, "full_profile_akid", creds.AccessKeyID) + assert.Equal(t, "full_profile_secret", creds.SecretAccessKey) + assert.Empty(t, creds.SessionToken) + assert.Contains(t, creds.ProviderName, "SharedConfigCredentials") +} + +func TestNewSessionWithOptions_OverrideSharedConfigDisable(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "full_profile") + + s, err := NewSessionWithOptions(Options{ + SharedConfigState: SharedConfigDisable, + }) + assert.NoError(t, err) + + assert.Empty(t, *s.Config.Region) + + creds, err := s.Config.Credentials.Get() + assert.NoError(t, err) + assert.Equal(t, "full_profile_akid", creds.AccessKeyID) + assert.Equal(t, "full_profile_secret", creds.SecretAccessKey) + assert.Empty(t, creds.SessionToken) + assert.Contains(t, creds.ProviderName, "SharedConfigCredentials") +} + +func TestNewSessionWithOptions_OverrideSharedConfigFiles(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "config_file_load_order") + + s, err := NewSessionWithOptions(Options{ + SharedConfigFiles: []string{testConfigOtherFilename}, + }) + assert.NoError(t, err) + + assert.Equal(t, "shared_config_other_region", *s.Config.Region) + + creds, err := s.Config.Credentials.Get() + assert.NoError(t, err) + assert.Equal(t, "shared_config_other_akid", creds.AccessKeyID) + assert.Equal(t, "shared_config_other_secret", creds.SecretAccessKey) + assert.Empty(t, creds.SessionToken) + assert.Contains(t, creds.ProviderName, "SharedConfigCredentials") +} + +func TestNewSessionWithOptions_Overrides(t *testing.T) { + cases := []struct { + InEnvs map[string]string + InProfile string + OutRegion string + OutCreds credentials.Value + }{ + { + InEnvs: map[string]string{ + "AWS_SDK_LOAD_CONFIG": "0", + "AWS_SHARED_CREDENTIALS_FILE": testConfigFilename, + "AWS_PROFILE": "other_profile", + }, + InProfile: "full_profile", + OutRegion: "full_profile_region", + OutCreds: credentials.Value{ + AccessKeyID: "full_profile_akid", + SecretAccessKey: "full_profile_secret", + ProviderName: "SharedConfigCredentials", + }, + }, + { + InEnvs: map[string]string{ + "AWS_SDK_LOAD_CONFIG": "0", + "AWS_SHARED_CREDENTIALS_FILE": testConfigFilename, + "AWS_REGION": "env_region", + "AWS_ACCESS_KEY": "env_akid", + "AWS_SECRET_ACCESS_KEY": "env_secret", + "AWS_PROFILE": "other_profile", + }, + InProfile: "full_profile", + OutRegion: "env_region", + OutCreds: credentials.Value{ + AccessKeyID: "env_akid", + SecretAccessKey: "env_secret", + ProviderName: "EnvConfigCredentials", + }, + }, + { + InEnvs: map[string]string{ + "AWS_SDK_LOAD_CONFIG": "0", + "AWS_SHARED_CREDENTIALS_FILE": testConfigFilename, + "AWS_CONFIG_FILE": testConfigOtherFilename, + "AWS_PROFILE": "shared_profile", + }, + InProfile: "config_file_load_order", + OutRegion: "shared_config_region", + OutCreds: credentials.Value{ + AccessKeyID: "shared_config_akid", + SecretAccessKey: "shared_config_secret", + ProviderName: "SharedConfigCredentials", + }, + }, + } + + for _, c := range cases { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + for k, v := range c.InEnvs { + os.Setenv(k, v) + } + + s, err := NewSessionWithOptions(Options{ + Profile: c.InProfile, + SharedConfigState: SharedConfigEnable, + }) + assert.NoError(t, err) + + creds, err := s.Config.Credentials.Get() + assert.NoError(t, err) + assert.Equal(t, c.OutRegion, *s.Config.Region) + assert.Equal(t, c.OutCreds.AccessKeyID, creds.AccessKeyID) + assert.Equal(t, c.OutCreds.SecretAccessKey, creds.SecretAccessKey) + assert.Equal(t, c.OutCreds.SessionToken, creds.SessionToken) + assert.Contains(t, creds.ProviderName, c.OutCreds.ProviderName) + } +} + +const assumeRoleRespMsg = ` + + + + arn:aws:sts::account_id:assumed-role/role/session_name + AKID:session_name + + + AKID + SECRET + SESSION_TOKEN + %s + + + + request-id + + +` + +func TestSesisonAssumeRole(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_REGION", "us-east-1") + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "assume_role_w_creds") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(fmt.Sprintf(assumeRoleRespMsg, time.Now().Add(15*time.Minute).Format("2006-01-02T15:04:05Z")))) + })) + + s, err := NewSession(&aws.Config{Endpoint: aws.String(server.URL), DisableSSL: aws.Bool(true)}) + + creds, err := s.Config.Credentials.Get() + assert.NoError(t, err) + assert.Equal(t, "AKID", creds.AccessKeyID) + assert.Equal(t, "SECRET", creds.SecretAccessKey) + assert.Equal(t, "SESSION_TOKEN", creds.SessionToken) + assert.Contains(t, creds.ProviderName, "AssumeRoleProvider") +} + +func TestSessionAssumeRole_WithMFA(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_REGION", "us-east-1") + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "assume_role_w_creds") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, r.FormValue("SerialNumber"), "0123456789") + assert.Equal(t, r.FormValue("TokenCode"), "tokencode") + + w.Write([]byte(fmt.Sprintf(assumeRoleRespMsg, time.Now().Add(15*time.Minute).Format("2006-01-02T15:04:05Z")))) + })) + + customProviderCalled := false + sess, err := NewSessionWithOptions(Options{ + Profile: "assume_role_w_mfa", + Config: aws.Config{ + Region: aws.String("us-east-1"), + Endpoint: aws.String(server.URL), + DisableSSL: aws.Bool(true), + }, + SharedConfigState: SharedConfigEnable, + AssumeRoleTokenProvider: func() (string, error) { + customProviderCalled = true + + return "tokencode", nil + }, + }) + assert.NoError(t, err) + + creds, err := sess.Config.Credentials.Get() + assert.NoError(t, err) + assert.True(t, customProviderCalled) + + assert.Equal(t, "AKID", creds.AccessKeyID) + assert.Equal(t, "SECRET", creds.SecretAccessKey) + assert.Equal(t, "SESSION_TOKEN", creds.SessionToken) + assert.Contains(t, creds.ProviderName, "AssumeRoleProvider") +} + +func TestSessionAssumeRole_WithMFA_NoTokenProvider(t *testing.T) { + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_REGION", "us-east-1") + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "assume_role_w_creds") + + _, err := NewSessionWithOptions(Options{ + Profile: "assume_role_w_mfa", + SharedConfigState: SharedConfigEnable, + }) + assert.Equal(t, err, AssumeRoleTokenProviderNotSetError{}) +} + +func TestSessionAssumeRole_DisableSharedConfig(t *testing.T) { + // Backwards compatibility with Shared config disabled + // assume role should not be built into the config. + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_SDK_LOAD_CONFIG", "0") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "assume_role_w_creds") + + s, err := NewSession() + assert.NoError(t, err) + + creds, err := s.Config.Credentials.Get() + assert.NoError(t, err) + assert.Equal(t, "assume_role_w_creds_akid", creds.AccessKeyID) + assert.Equal(t, "assume_role_w_creds_secret", creds.SecretAccessKey) + assert.Contains(t, creds.ProviderName, "SharedConfigCredentials") +} + +func TestSessionAssumeRole_InvalidSourceProfile(t *testing.T) { + // Backwards compatibility with Shared config disabled + // assume role should not be built into the config. + oldEnv := initSessionTestEnv() + defer awstesting.PopEnv(oldEnv) + + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) + os.Setenv("AWS_PROFILE", "assume_role_invalid_source_profile") + + s, err := NewSession() + assert.Error(t, err) + assert.Contains(t, err.Error(), "SharedConfigAssumeRoleError: failed to load assume role") + assert.Nil(t, s) +} + +func initSessionTestEnv() (oldEnv []string) { + oldEnv = awstesting.StashEnv() + os.Setenv("AWS_CONFIG_FILE", "file_not_exists") + os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "file_not_exists") + + return oldEnv +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go new file mode 100644 index 0000000..09c8e5b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go @@ -0,0 +1,295 @@ +package session + +import ( + "fmt" + "io/ioutil" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/go-ini/ini" +) + +const ( + // Static Credentials group + accessKeyIDKey = `aws_access_key_id` // group required + secretAccessKey = `aws_secret_access_key` // group required + sessionTokenKey = `aws_session_token` // optional + + // Assume Role Credentials group + roleArnKey = `role_arn` // group required + sourceProfileKey = `source_profile` // group required + externalIDKey = `external_id` // optional + mfaSerialKey = `mfa_serial` // optional + roleSessionNameKey = `role_session_name` // optional + + // Additional Config fields + regionKey = `region` + + // DefaultSharedConfigProfile is the default profile to be used when + // loading configuration from the config files if another profile name + // is not provided. + DefaultSharedConfigProfile = `default` +) + +type assumeRoleConfig struct { + RoleARN string + SourceProfile string + ExternalID string + MFASerial string + RoleSessionName string +} + +// sharedConfig represents the configuration fields of the SDK config files. +type sharedConfig struct { + // Credentials values from the config file. Both aws_access_key_id + // and aws_secret_access_key must be provided together in the same file + // to be considered valid. The values will be ignored if not a complete group. + // aws_session_token is an optional field that can be provided if both of the + // other two fields are also provided. + // + // aws_access_key_id + // aws_secret_access_key + // aws_session_token + Creds credentials.Value + + AssumeRole assumeRoleConfig + AssumeRoleSource *sharedConfig + + // Region is the region the SDK should use for looking up AWS service endpoints + // and signing requests. + // + // region + Region string +} + +type sharedConfigFile struct { + Filename string + IniData *ini.File +} + +// loadSharedConfig retrieves the configuration from the list of files +// using the profile provided. The order the files are listed will determine +// precedence. Values in subsequent files will overwrite values defined in +// earlier files. +// +// For example, given two files A and B. Both define credentials. If the order +// of the files are A then B, B's credential values will be used instead of A's. +// +// See sharedConfig.setFromFile for information how the config files +// will be loaded. +func loadSharedConfig(profile string, filenames []string) (sharedConfig, error) { + if len(profile) == 0 { + profile = DefaultSharedConfigProfile + } + + files, err := loadSharedConfigIniFiles(filenames) + if err != nil { + return sharedConfig{}, err + } + + cfg := sharedConfig{} + if err = cfg.setFromIniFiles(profile, files); err != nil { + return sharedConfig{}, err + } + + if len(cfg.AssumeRole.SourceProfile) > 0 { + if err := cfg.setAssumeRoleSource(profile, files); err != nil { + return sharedConfig{}, err + } + } + + return cfg, nil +} + +func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) { + files := make([]sharedConfigFile, 0, len(filenames)) + + for _, filename := range filenames { + b, err := ioutil.ReadFile(filename) + if err != nil { + // Skip files which can't be opened and read for whatever reason + continue + } + + f, err := ini.Load(b) + if err != nil { + return nil, SharedConfigLoadError{Filename: filename, Err: err} + } + + files = append(files, sharedConfigFile{ + Filename: filename, IniData: f, + }) + } + + return files, nil +} + +func (cfg *sharedConfig) setAssumeRoleSource(origProfile string, files []sharedConfigFile) error { + var assumeRoleSrc sharedConfig + + // Multiple level assume role chains are not support + if cfg.AssumeRole.SourceProfile == origProfile { + assumeRoleSrc = *cfg + assumeRoleSrc.AssumeRole = assumeRoleConfig{} + } else { + err := assumeRoleSrc.setFromIniFiles(cfg.AssumeRole.SourceProfile, files) + if err != nil { + return err + } + } + + if len(assumeRoleSrc.Creds.AccessKeyID) == 0 { + return SharedConfigAssumeRoleError{RoleARN: cfg.AssumeRole.RoleARN} + } + + cfg.AssumeRoleSource = &assumeRoleSrc + + return nil +} + +func (cfg *sharedConfig) setFromIniFiles(profile string, files []sharedConfigFile) error { + // Trim files from the list that don't exist. + for _, f := range files { + if err := cfg.setFromIniFile(profile, f); err != nil { + if _, ok := err.(SharedConfigProfileNotExistsError); ok { + // Ignore proviles missings + continue + } + return err + } + } + + return nil +} + +// setFromFile loads the configuration from the file using +// the profile provided. A sharedConfig pointer type value is used so that +// multiple config file loadings can be chained. +// +// Only loads complete logically grouped values, and will not set fields in cfg +// for incomplete grouped values in the config. Such as credentials. For example +// if a config file only includes aws_access_key_id but no aws_secret_access_key +// the aws_access_key_id will be ignored. +func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) error { + section, err := file.IniData.GetSection(profile) + if err != nil { + // Fallback to to alternate profile name: profile + section, err = file.IniData.GetSection(fmt.Sprintf("profile %s", profile)) + if err != nil { + return SharedConfigProfileNotExistsError{Profile: profile, Err: err} + } + } + + // Shared Credentials + akid := section.Key(accessKeyIDKey).String() + secret := section.Key(secretAccessKey).String() + if len(akid) > 0 && len(secret) > 0 { + cfg.Creds = credentials.Value{ + AccessKeyID: akid, + SecretAccessKey: secret, + SessionToken: section.Key(sessionTokenKey).String(), + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename), + } + } + + // Assume Role + roleArn := section.Key(roleArnKey).String() + srcProfile := section.Key(sourceProfileKey).String() + if len(roleArn) > 0 && len(srcProfile) > 0 { + cfg.AssumeRole = assumeRoleConfig{ + RoleARN: roleArn, + SourceProfile: srcProfile, + ExternalID: section.Key(externalIDKey).String(), + MFASerial: section.Key(mfaSerialKey).String(), + RoleSessionName: section.Key(roleSessionNameKey).String(), + } + } + + // Region + if v := section.Key(regionKey).String(); len(v) > 0 { + cfg.Region = v + } + + return nil +} + +// SharedConfigLoadError is an error for the shared config file failed to load. +type SharedConfigLoadError struct { + Filename string + Err error +} + +// Code is the short id of the error. +func (e SharedConfigLoadError) Code() string { + return "SharedConfigLoadError" +} + +// Message is the description of the error +func (e SharedConfigLoadError) Message() string { + return fmt.Sprintf("failed to load config file, %s", e.Filename) +} + +// OrigErr is the underlying error that caused the failure. +func (e SharedConfigLoadError) OrigErr() error { + return e.Err +} + +// Error satisfies the error interface. +func (e SharedConfigLoadError) Error() string { + return awserr.SprintError(e.Code(), e.Message(), "", e.Err) +} + +// SharedConfigProfileNotExistsError is an error for the shared config when +// the profile was not find in the config file. +type SharedConfigProfileNotExistsError struct { + Profile string + Err error +} + +// Code is the short id of the error. +func (e SharedConfigProfileNotExistsError) Code() string { + return "SharedConfigProfileNotExistsError" +} + +// Message is the description of the error +func (e SharedConfigProfileNotExistsError) Message() string { + return fmt.Sprintf("failed to get profile, %s", e.Profile) +} + +// OrigErr is the underlying error that caused the failure. +func (e SharedConfigProfileNotExistsError) OrigErr() error { + return e.Err +} + +// Error satisfies the error interface. +func (e SharedConfigProfileNotExistsError) Error() string { + return awserr.SprintError(e.Code(), e.Message(), "", e.Err) +} + +// SharedConfigAssumeRoleError is an error for the shared config when the +// profile contains assume role information, but that information is invalid +// or not complete. +type SharedConfigAssumeRoleError struct { + RoleARN string +} + +// Code is the short id of the error. +func (e SharedConfigAssumeRoleError) Code() string { + return "SharedConfigAssumeRoleError" +} + +// Message is the description of the error +func (e SharedConfigAssumeRoleError) Message() string { + return fmt.Sprintf("failed to load assume role for %s, source profile has no shared credentials", + e.RoleARN) +} + +// OrigErr is the underlying error that caused the failure. +func (e SharedConfigAssumeRoleError) OrigErr() error { + return nil +} + +// Error satisfies the error interface. +func (e SharedConfigAssumeRoleError) Error() string { + return awserr.SprintError(e.Code(), e.Message(), "", nil) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config_test.go b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config_test.go new file mode 100644 index 0000000..3a07b8d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config_test.go @@ -0,0 +1,274 @@ +package session + +import ( + "fmt" + "path/filepath" + "testing" + + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/go-ini/ini" + "github.com/stretchr/testify/assert" +) + +var ( + testConfigFilename = filepath.Join("testdata", "shared_config") + testConfigOtherFilename = filepath.Join("testdata", "shared_config_other") +) + +func TestLoadSharedConfig(t *testing.T) { + cases := []struct { + Filenames []string + Profile string + Expected sharedConfig + Err error + }{ + { + Filenames: []string{"file_not_exists"}, + Profile: "default", + }, + { + Filenames: []string{testConfigFilename}, + Expected: sharedConfig{ + Region: "default_region", + }, + }, + { + Filenames: []string{testConfigOtherFilename, testConfigFilename}, + Profile: "config_file_load_order", + Expected: sharedConfig{ + Region: "shared_config_region", + Creds: credentials.Value{ + AccessKeyID: "shared_config_akid", + SecretAccessKey: "shared_config_secret", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), + }, + }, + }, + { + Filenames: []string{testConfigFilename, testConfigOtherFilename}, + Profile: "config_file_load_order", + Expected: sharedConfig{ + Region: "shared_config_other_region", + Creds: credentials.Value{ + AccessKeyID: "shared_config_other_akid", + SecretAccessKey: "shared_config_other_secret", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigOtherFilename), + }, + }, + }, + { + Filenames: []string{testConfigOtherFilename, testConfigFilename}, + Profile: "assume_role", + Expected: sharedConfig{ + AssumeRole: assumeRoleConfig{ + RoleARN: "assume_role_role_arn", + SourceProfile: "complete_creds", + }, + AssumeRoleSource: &sharedConfig{ + Creds: credentials.Value{ + AccessKeyID: "complete_creds_akid", + SecretAccessKey: "complete_creds_secret", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), + }, + }, + }, + }, + { + Filenames: []string{testConfigOtherFilename, testConfigFilename}, + Profile: "assume_role_invalid_source_profile", + Expected: sharedConfig{ + AssumeRole: assumeRoleConfig{ + RoleARN: "assume_role_invalid_source_profile_role_arn", + SourceProfile: "profile_not_exists", + }, + }, + Err: SharedConfigAssumeRoleError{RoleARN: "assume_role_invalid_source_profile_role_arn"}, + }, + { + Filenames: []string{testConfigOtherFilename, testConfigFilename}, + Profile: "assume_role_w_creds", + Expected: sharedConfig{ + Creds: credentials.Value{ + AccessKeyID: "assume_role_w_creds_akid", + SecretAccessKey: "assume_role_w_creds_secret", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), + }, + AssumeRole: assumeRoleConfig{ + RoleARN: "assume_role_w_creds_role_arn", + SourceProfile: "assume_role_w_creds", + ExternalID: "1234", + RoleSessionName: "assume_role_w_creds_session_name", + }, + AssumeRoleSource: &sharedConfig{ + Creds: credentials.Value{ + AccessKeyID: "assume_role_w_creds_akid", + SecretAccessKey: "assume_role_w_creds_secret", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), + }, + }, + }, + }, + { + Filenames: []string{testConfigOtherFilename, testConfigFilename}, + Profile: "assume_role_wo_creds", + Expected: sharedConfig{ + AssumeRole: assumeRoleConfig{ + RoleARN: "assume_role_wo_creds_role_arn", + SourceProfile: "assume_role_wo_creds", + }, + }, + Err: SharedConfigAssumeRoleError{RoleARN: "assume_role_wo_creds_role_arn"}, + }, + { + Filenames: []string{filepath.Join("testdata", "shared_config_invalid_ini")}, + Profile: "profile_name", + Err: SharedConfigLoadError{Filename: filepath.Join("testdata", "shared_config_invalid_ini")}, + }, + } + + for i, c := range cases { + cfg, err := loadSharedConfig(c.Profile, c.Filenames) + if c.Err != nil { + assert.Contains(t, err.Error(), c.Err.Error(), "expected error, %d", i) + continue + } + + assert.NoError(t, err, "unexpected error, %d", i) + assert.Equal(t, c.Expected, cfg, "not equal, %d", i) + } +} + +func TestLoadSharedConfigFromFile(t *testing.T) { + filename := testConfigFilename + f, err := ini.Load(filename) + if err != nil { + t.Fatalf("failed to load test config file, %s, %v", filename, err) + } + iniFile := sharedConfigFile{IniData: f, Filename: filename} + + cases := []struct { + Profile string + Expected sharedConfig + Err error + }{ + { + Profile: "default", + Expected: sharedConfig{Region: "default_region"}, + }, + { + Profile: "alt_profile_name", + Expected: sharedConfig{Region: "alt_profile_name_region"}, + }, + { + Profile: "short_profile_name_first", + Expected: sharedConfig{Region: "short_profile_name_first_short"}, + }, + { + Profile: "partial_creds", + Expected: sharedConfig{}, + }, + { + Profile: "complete_creds", + Expected: sharedConfig{ + Creds: credentials.Value{ + AccessKeyID: "complete_creds_akid", + SecretAccessKey: "complete_creds_secret", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), + }, + }, + }, + { + Profile: "complete_creds_with_token", + Expected: sharedConfig{ + Creds: credentials.Value{ + AccessKeyID: "complete_creds_with_token_akid", + SecretAccessKey: "complete_creds_with_token_secret", + SessionToken: "complete_creds_with_token_token", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), + }, + }, + }, + { + Profile: "full_profile", + Expected: sharedConfig{ + Creds: credentials.Value{ + AccessKeyID: "full_profile_akid", + SecretAccessKey: "full_profile_secret", + ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", testConfigFilename), + }, + Region: "full_profile_region", + }, + }, + { + Profile: "partial_assume_role", + Expected: sharedConfig{}, + }, + { + Profile: "assume_role", + Expected: sharedConfig{ + AssumeRole: assumeRoleConfig{ + RoleARN: "assume_role_role_arn", + SourceProfile: "complete_creds", + }, + }, + }, + { + Profile: "assume_role_w_mfa", + Expected: sharedConfig{ + AssumeRole: assumeRoleConfig{ + RoleARN: "assume_role_role_arn", + SourceProfile: "complete_creds", + MFASerial: "0123456789", + }, + }, + }, + { + Profile: "does_not_exists", + Err: SharedConfigProfileNotExistsError{Profile: "does_not_exists"}, + }, + } + + for i, c := range cases { + cfg := sharedConfig{} + + err := cfg.setFromIniFile(c.Profile, iniFile) + if c.Err != nil { + assert.Contains(t, err.Error(), c.Err.Error(), "expected error, %d", i) + continue + } + + assert.NoError(t, err, "unexpected error, %d", i) + assert.Equal(t, c.Expected, cfg, "not equal, %d", i) + } +} + +func TestLoadSharedConfigIniFiles(t *testing.T) { + cases := []struct { + Filenames []string + Expected []sharedConfigFile + }{ + { + Filenames: []string{"not_exists", testConfigFilename}, + Expected: []sharedConfigFile{ + {Filename: testConfigFilename}, + }, + }, + { + Filenames: []string{testConfigFilename, testConfigOtherFilename}, + Expected: []sharedConfigFile{ + {Filename: testConfigFilename}, + {Filename: testConfigOtherFilename}, + }, + }, + } + + for i, c := range cases { + files, err := loadSharedConfigIniFiles(c.Filenames) + assert.NoError(t, err, "unexpected error, %d", i) + assert.Equal(t, len(c.Expected), len(files), "expected num files, %d", i) + + for i, expectedFile := range c.Expected { + assert.Equal(t, expectedFile.Filename, files[i].Filename) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_1_5_test.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_1_5_test.go new file mode 100644 index 0000000..2e591c2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_1_5_test.go @@ -0,0 +1,86 @@ +// +build go1.5 + +package v4_test + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting/unit" +) + +func TestStandaloneSign(t *testing.T) { + creds := unit.Session.Config.Credentials + signer := v4.NewSigner(creds) + + for _, c := range standaloneSignCases { + host := fmt.Sprintf("https://%s.%s.%s.amazonaws.com", + c.SubDomain, c.Region, c.Service) + + req, err := http.NewRequest("GET", host, nil) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + + // URL.EscapedPath() will be used by the signer to get the + // escaped form of the request's URI path. + req.URL.Path = c.OrigURI + req.URL.RawQuery = c.OrigQuery + + _, err = signer.Sign(req, nil, c.Service, c.Region, time.Unix(0, 0)) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + + actual := req.Header.Get("Authorization") + if e, a := c.ExpSig, actual; e != a { + t.Errorf("expected %v, but recieved %v", e, a) + } + if e, a := c.OrigURI, req.URL.Path; e != a { + t.Errorf("expected %v, but recieved %v", e, a) + } + if e, a := c.EscapedURI, req.URL.EscapedPath(); e != a { + t.Errorf("expected %v, but recieved %v", e, a) + } + } +} + +func TestStandaloneSign_RawPath(t *testing.T) { + creds := unit.Session.Config.Credentials + signer := v4.NewSigner(creds) + + for _, c := range standaloneSignCases { + host := fmt.Sprintf("https://%s.%s.%s.amazonaws.com", + c.SubDomain, c.Region, c.Service) + + req, err := http.NewRequest("GET", host, nil) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + + // URL.EscapedPath() will be used by the signer to get the + // escaped form of the request's URI path. + req.URL.Path = c.OrigURI + req.URL.RawPath = c.EscapedURI + req.URL.RawQuery = c.OrigQuery + + _, err = signer.Sign(req, nil, c.Service, c.Region, time.Unix(0, 0)) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + + actual := req.Header.Get("Authorization") + if e, a := c.ExpSig, actual; e != a { + t.Errorf("expected %v, but recieved %v", e, a) + } + if e, a := c.OrigURI, req.URL.Path; e != a { + t.Errorf("expected %v, but recieved %v", e, a) + } + if e, a := c.EscapedURI, req.URL.EscapedPath(); e != a { + t.Errorf("expected %v, but recieved %v", e, a) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_test.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_test.go new file mode 100644 index 0000000..93d664b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/functional_test.go @@ -0,0 +1,254 @@ +package v4_test + +import ( + "net/http" + "net/url" + "reflect" + "strings" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/service/s3" +) + +var standaloneSignCases = []struct { + OrigURI string + OrigQuery string + Region, Service, SubDomain string + ExpSig string + EscapedURI string +}{ + { + OrigURI: `/logs-*/_search`, + OrigQuery: `pretty=true`, + Region: "us-west-2", Service: "es", SubDomain: "hostname-clusterkey", + EscapedURI: `/logs-%2A/_search`, + ExpSig: `AWS4-HMAC-SHA256 Credential=AKID/19700101/us-west-2/es/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=79d0760751907af16f64a537c1242416dacf51204a7dd5284492d15577973b91`, + }, +} + +func TestPresignHandler(t *testing.T) { + svc := s3.New(unit.Session) + req, _ := svc.PutObjectRequest(&s3.PutObjectInput{ + Bucket: aws.String("bucket"), + Key: aws.String("key"), + ContentDisposition: aws.String("a+b c$d"), + ACL: aws.String("public-read"), + }) + req.Time = time.Unix(0, 0) + urlstr, err := req.Presign(5 * time.Minute) + + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + expectedHost := "bucket.s3.mock-region.amazonaws.com" + expectedDate := "19700101T000000Z" + expectedHeaders := "content-disposition;host;x-amz-acl" + expectedSig := "a46583256431b09eb45ba4af2e6286d96a9835ed13721023dc8076dfdcb90fcb" + expectedCred := "AKID/19700101/mock-region/s3/aws4_request" + + u, _ := url.Parse(urlstr) + urlQ := u.Query() + if e, a := expectedHost, u.Host; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedSig, urlQ.Get("X-Amz-Signature"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedCred, urlQ.Get("X-Amz-Credential"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedHeaders, urlQ.Get("X-Amz-SignedHeaders"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedDate, urlQ.Get("X-Amz-Date"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "300", urlQ.Get("X-Amz-Expires"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "UNSIGNED-PAYLOAD", urlQ.Get("X-Amz-Content-Sha256"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + + if e, a := "+", urlstr; strings.Contains(a, e) { // + encoded as %20 + t.Errorf("expect %v not to be in %v", e, a) + } +} + +func TestPresignRequest(t *testing.T) { + svc := s3.New(unit.Session) + req, _ := svc.PutObjectRequest(&s3.PutObjectInput{ + Bucket: aws.String("bucket"), + Key: aws.String("key"), + ContentDisposition: aws.String("a+b c$d"), + ACL: aws.String("public-read"), + }) + req.Time = time.Unix(0, 0) + urlstr, headers, err := req.PresignRequest(5 * time.Minute) + + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + expectedHost := "bucket.s3.mock-region.amazonaws.com" + expectedDate := "19700101T000000Z" + expectedHeaders := "content-disposition;host;x-amz-acl" + expectedSig := "a46583256431b09eb45ba4af2e6286d96a9835ed13721023dc8076dfdcb90fcb" + expectedCred := "AKID/19700101/mock-region/s3/aws4_request" + expectedHeaderMap := http.Header{ + "x-amz-acl": []string{"public-read"}, + "content-disposition": []string{"a+b c$d"}, + } + + u, _ := url.Parse(urlstr) + urlQ := u.Query() + if e, a := expectedHost, u.Host; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedSig, urlQ.Get("X-Amz-Signature"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedCred, urlQ.Get("X-Amz-Credential"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedHeaders, urlQ.Get("X-Amz-SignedHeaders"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedDate, urlQ.Get("X-Amz-Date"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedHeaderMap, headers; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "300", urlQ.Get("X-Amz-Expires"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "UNSIGNED-PAYLOAD", urlQ.Get("X-Amz-Content-Sha256"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + + if e, a := "+", urlstr; strings.Contains(a, e) { // + encoded as %20 + t.Errorf("expect %v not to be in %v", e, a) + } +} + +func TestStandaloneSign_CustomURIEscape(t *testing.T) { + var expectSig = `AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/es/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=6601e883cc6d23871fd6c2a394c5677ea2b8c82b04a6446786d64cd74f520967` + + creds := unit.Session.Config.Credentials + signer := v4.NewSigner(creds, func(s *v4.Signer) { + s.DisableURIPathEscaping = true + }) + + host := "https://subdomain.us-east-1.es.amazonaws.com" + req, err := http.NewRequest("GET", host, nil) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + req.URL.Path = `/log-*/_search` + req.URL.Opaque = "//subdomain.us-east-1.es.amazonaws.com/log-%2A/_search" + + _, err = signer.Sign(req, nil, "es", "us-east-1", time.Unix(0, 0)) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + actual := req.Header.Get("Authorization") + if e, a := expectSig, actual; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestStandaloneSign_WithPort(t *testing.T) { + + cases := []struct { + description string + url string + expectedSig string + }{ + { + "default HTTPS port", + "https://estest.us-east-1.es.amazonaws.com:443/_search", + "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/es/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=e573fc9aa3a156b720976419319be98fb2824a3abc2ddd895ecb1d1611c6a82d", + }, + { + "default HTTP port", + "http://example.com:80/_search", + "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/es/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=54ebe60c4ae03a40948b849e13c333523235f38002e2807059c64a9a8c7cb951", + }, + { + "non-standard HTTP port", + "http://example.com:9200/_search", + "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/es/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=cd9d926a460f8d3b58b57beadbd87666dc667e014c0afaa4cea37b2867f51b4f", + }, + { + "non-standard HTTPS port", + "https://example.com:9200/_search", + "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/es/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=cd9d926a460f8d3b58b57beadbd87666dc667e014c0afaa4cea37b2867f51b4f", + }, + } + + for _, c := range cases { + signer := v4.NewSigner(unit.Session.Config.Credentials) + req, _ := http.NewRequest("GET", c.url, nil) + _, err := signer.Sign(req, nil, "es", "us-east-1", time.Unix(0, 0)) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + actual := req.Header.Get("Authorization") + if e, a := c.expectedSig, actual; e != a { + t.Errorf("%s, expect %v, got %v", c.description, e, a) + } + } +} + +func TestStandalonePresign_WithPort(t *testing.T) { + + cases := []struct { + description string + url string + expectedSig string + }{ + { + "default HTTPS port", + "https://estest.us-east-1.es.amazonaws.com:443/_search", + "0abcf61a351063441296febf4b485734d780634fba8cf1e7d9769315c35255d6", + }, + { + "default HTTP port", + "http://example.com:80/_search", + "fce9976dd6c849c21adfa6d3f3e9eefc651d0e4a2ccd740d43efddcccfdc8179", + }, + { + "non-standard HTTP port", + "http://example.com:9200/_search", + "f33c25a81c735e42bef35ed5e9f720c43940562e3e616ff0777bf6dde75249b0", + }, + { + "non-standard HTTPS port", + "https://example.com:9200/_search", + "f33c25a81c735e42bef35ed5e9f720c43940562e3e616ff0777bf6dde75249b0", + }, + } + + for _, c := range cases { + signer := v4.NewSigner(unit.Session.Config.Credentials) + req, _ := http.NewRequest("GET", c.url, nil) + _, err := signer.Presign(req, nil, "es", "us-east-1", 5 * time.Minute, time.Unix(0, 0)) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + actual := req.URL.Query().Get("X-Amz-Signature") + if e, a := c.expectedSig, actual; e != a { + t.Errorf("%s, expect %v, got %v", c.description, e, a) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go new file mode 100644 index 0000000..244c86d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go @@ -0,0 +1,82 @@ +package v4 + +import ( + "net/http" + "strings" +) + +// validator houses a set of rule needed for validation of a +// string value +type rules []rule + +// rule interface allows for more flexible rules and just simply +// checks whether or not a value adheres to that rule +type rule interface { + IsValid(value string) bool +} + +// IsValid will iterate through all rules and see if any rules +// apply to the value and supports nested rules +func (r rules) IsValid(value string) bool { + for _, rule := range r { + if rule.IsValid(value) { + return true + } + } + return false +} + +// mapRule generic rule for maps +type mapRule map[string]struct{} + +// IsValid for the map rule satisfies whether it exists in the map +func (m mapRule) IsValid(value string) bool { + _, ok := m[value] + return ok +} + +// whitelist is a generic rule for whitelisting +type whitelist struct { + rule +} + +// IsValid for whitelist checks if the value is within the whitelist +func (w whitelist) IsValid(value string) bool { + return w.rule.IsValid(value) +} + +// blacklist is a generic rule for blacklisting +type blacklist struct { + rule +} + +// IsValid for whitelist checks if the value is within the whitelist +func (b blacklist) IsValid(value string) bool { + return !b.rule.IsValid(value) +} + +type patterns []string + +// IsValid for patterns checks each pattern and returns if a match has +// been found +func (p patterns) IsValid(value string) bool { + for _, pattern := range p { + if strings.HasPrefix(http.CanonicalHeaderKey(value), pattern) { + return true + } + } + return false +} + +// inclusiveRules rules allow for rules to depend on one another +type inclusiveRules []rule + +// IsValid will return true if all rules are true +func (r inclusiveRules) IsValid(value string) bool { + for _, rule := range r { + if !rule.IsValid(value) { + return false + } + } + return true +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules_test.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules_test.go new file mode 100644 index 0000000..f4be951 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules_test.go @@ -0,0 +1,77 @@ +package v4 + +import ( + "testing" +) + +func TestRuleCheckWhitelist(t *testing.T) { + w := whitelist{ + mapRule{ + "Cache-Control": struct{}{}, + }, + } + + if !w.IsValid("Cache-Control") { + t.Error("expected true value") + } + if w.IsValid("Cache-") { + t.Error("expected false value") + } +} + +func TestRuleCheckBlacklist(t *testing.T) { + b := blacklist{ + mapRule{ + "Cache-Control": struct{}{}, + }, + } + + if b.IsValid("Cache-Control") { + t.Error("expected false value") + } + if !b.IsValid("Cache-") { + t.Error("expected true value") + } +} + +func TestRuleCheckPattern(t *testing.T) { + p := patterns{"X-Amz-Meta-"} + + if !p.IsValid("X-Amz-Meta-") { + t.Error("expected true value") + } + if !p.IsValid("X-Amz-Meta-Star") { + t.Error("expected true value") + } + if p.IsValid("Cache-") { + t.Error("expected false value") + } +} + +func TestRuleComplexWhitelist(t *testing.T) { + w := rules{ + whitelist{ + mapRule{ + "Cache-Control": struct{}{}, + }, + }, + patterns{"X-Amz-Meta-"}, + } + + r := rules{ + inclusiveRules{patterns{"X-Amz-"}, blacklist{w}}, + } + + if !r.IsValid("X-Amz-Blah") { + t.Error("expected true value") + } + if r.IsValid("X-Amz-Meta-") { + t.Error("expected false value") + } + if r.IsValid("X-Amz-Meta-Star") { + t.Error("expected false value") + } + if r.IsValid("Cache-Control") { + t.Error("expected false value") + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/options.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/options.go new file mode 100644 index 0000000..6aa2ed2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/options.go @@ -0,0 +1,7 @@ +package v4 + +// WithUnsignedPayload will enable and set the UnsignedPayload field to +// true of the signer. +func WithUnsignedPayload(v4 *Signer) { + v4.UnsignedPayload = true +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go new file mode 100644 index 0000000..bd082e9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go @@ -0,0 +1,24 @@ +// +build go1.5 + +package v4 + +import ( + "net/url" + "strings" +) + +func getURIPath(u *url.URL) string { + var uri string + + if len(u.Opaque) > 0 { + uri = "/" + strings.Join(strings.Split(u.Opaque, "/")[3:], "/") + } else { + uri = u.EscapedPath() + } + + if len(uri) == 0 { + uri = "/" + } + + return uri +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go new file mode 100644 index 0000000..ccc88b4 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go @@ -0,0 +1,767 @@ +// Package v4 implements signing for AWS V4 signer +// +// Provides request signing for request that need to be signed with +// AWS V4 Signatures. +// +// Standalone Signer +// +// Generally using the signer outside of the SDK should not require any additional +// logic when using Go v1.5 or higher. The signer does this by taking advantage +// of the URL.EscapedPath method. If your request URI requires additional escaping +// you many need to use the URL.Opaque to define what the raw URI should be sent +// to the service as. +// +// The signer will first check the URL.Opaque field, and use its value if set. +// The signer does require the URL.Opaque field to be set in the form of: +// +// "///" +// +// // e.g. +// "//example.com/some/path" +// +// The leading "//" and hostname are required or the URL.Opaque escaping will +// not work correctly. +// +// If URL.Opaque is not set the signer will fallback to the URL.EscapedPath() +// method and using the returned value. If you're using Go v1.4 you must set +// URL.Opaque if the URI path needs escaping. If URL.Opaque is not set with +// Go v1.5 the signer will fallback to URL.Path. +// +// AWS v4 signature validation requires that the canonical string's URI path +// element must be the URI escaped form of the HTTP request's path. +// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html +// +// The Go HTTP client will perform escaping automatically on the request. Some +// of these escaping may cause signature validation errors because the HTTP +// request differs from the URI path or query that the signature was generated. +// https://golang.org/pkg/net/url/#URL.EscapedPath +// +// Because of this, it is recommended that when using the signer outside of the +// SDK that explicitly escaping the request prior to being signed is preferable, +// and will help prevent signature validation errors. This can be done by setting +// the URL.Opaque or URL.RawPath. The SDK will use URL.Opaque first and then +// call URL.EscapedPath() if Opaque is not set. +// +// If signing a request intended for HTTP2 server, and you're using Go 1.6.2 +// through 1.7.4 you should use the URL.RawPath as the pre-escaped form of the +// request URL. https://github.com/golang/go/issues/16847 points to a bug in +// Go pre 1.8 that fails to make HTTP2 requests using absolute URL in the HTTP +// message. URL.Opaque generally will force Go to make requests with absolute URL. +// URL.RawPath does not do this, but RawPath must be a valid escaping of Path +// or url.EscapedPath will ignore the RawPath escaping. +// +// Test `TestStandaloneSign` provides a complete example of using the signer +// outside of the SDK and pre-escaping the URI path. +package v4 + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/rest" +) + +const ( + authHeaderPrefix = "AWS4-HMAC-SHA256" + timeFormat = "20060102T150405Z" + shortTimeFormat = "20060102" + + // emptyStringSHA256 is a SHA256 of an empty string + emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` +) + +var ignoredHeaders = rules{ + blacklist{ + mapRule{ + "Authorization": struct{}{}, + "User-Agent": struct{}{}, + "X-Amzn-Trace-Id": struct{}{}, + }, + }, +} + +// requiredSignedHeaders is a whitelist for build canonical headers. +var requiredSignedHeaders = rules{ + whitelist{ + mapRule{ + "Cache-Control": struct{}{}, + "Content-Disposition": struct{}{}, + "Content-Encoding": struct{}{}, + "Content-Language": struct{}{}, + "Content-Md5": struct{}{}, + "Content-Type": struct{}{}, + "Expires": struct{}{}, + "If-Match": struct{}{}, + "If-Modified-Since": struct{}{}, + "If-None-Match": struct{}{}, + "If-Unmodified-Since": struct{}{}, + "Range": struct{}{}, + "X-Amz-Acl": struct{}{}, + "X-Amz-Copy-Source": struct{}{}, + "X-Amz-Copy-Source-If-Match": struct{}{}, + "X-Amz-Copy-Source-If-Modified-Since": struct{}{}, + "X-Amz-Copy-Source-If-None-Match": struct{}{}, + "X-Amz-Copy-Source-If-Unmodified-Since": struct{}{}, + "X-Amz-Copy-Source-Range": struct{}{}, + "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": struct{}{}, + "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": struct{}{}, + "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": struct{}{}, + "X-Amz-Grant-Full-control": struct{}{}, + "X-Amz-Grant-Read": struct{}{}, + "X-Amz-Grant-Read-Acp": struct{}{}, + "X-Amz-Grant-Write": struct{}{}, + "X-Amz-Grant-Write-Acp": struct{}{}, + "X-Amz-Metadata-Directive": struct{}{}, + "X-Amz-Mfa": struct{}{}, + "X-Amz-Request-Payer": struct{}{}, + "X-Amz-Server-Side-Encryption": struct{}{}, + "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": struct{}{}, + "X-Amz-Server-Side-Encryption-Customer-Algorithm": struct{}{}, + "X-Amz-Server-Side-Encryption-Customer-Key": struct{}{}, + "X-Amz-Server-Side-Encryption-Customer-Key-Md5": struct{}{}, + "X-Amz-Storage-Class": struct{}{}, + "X-Amz-Website-Redirect-Location": struct{}{}, + }, + }, + patterns{"X-Amz-Meta-"}, +} + +// allowedHoisting is a whitelist for build query headers. The boolean value +// represents whether or not it is a pattern. +var allowedQueryHoisting = inclusiveRules{ + blacklist{requiredSignedHeaders}, + patterns{"X-Amz-"}, +} + +// Signer applies AWS v4 signing to given request. Use this to sign requests +// that need to be signed with AWS V4 Signatures. +type Signer struct { + // The authentication credentials the request will be signed against. + // This value must be set to sign requests. + Credentials *credentials.Credentials + + // Sets the log level the signer should use when reporting information to + // the logger. If the logger is nil nothing will be logged. See + // aws.LogLevelType for more information on available logging levels + // + // By default nothing will be logged. + Debug aws.LogLevelType + + // The logger loging information will be written to. If there the logger + // is nil, nothing will be logged. + Logger aws.Logger + + // Disables the Signer's moving HTTP header key/value pairs from the HTTP + // request header to the request's query string. This is most commonly used + // with pre-signed requests preventing headers from being added to the + // request's query string. + DisableHeaderHoisting bool + + // Disables the automatic escaping of the URI path of the request for the + // siganture's canonical string's path. For services that do not need additional + // escaping then use this to disable the signer escaping the path. + // + // S3 is an example of a service that does not need additional escaping. + // + // http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html + DisableURIPathEscaping bool + + // Disales the automatical setting of the HTTP request's Body field with the + // io.ReadSeeker passed in to the signer. This is useful if you're using a + // custom wrapper around the body for the io.ReadSeeker and want to preserve + // the Body value on the Request.Body. + // + // This does run the risk of signing a request with a body that will not be + // sent in the request. Need to ensure that the underlying data of the Body + // values are the same. + DisableRequestBodyOverwrite bool + + // currentTimeFn returns the time value which represents the current time. + // This value should only be used for testing. If it is nil the default + // time.Now will be used. + currentTimeFn func() time.Time + + // UnsignedPayload will prevent signing of the payload. This will only + // work for services that have support for this. + UnsignedPayload bool +} + +// NewSigner returns a Signer pointer configured with the credentials and optional +// option values provided. If not options are provided the Signer will use its +// default configuration. +func NewSigner(credentials *credentials.Credentials, options ...func(*Signer)) *Signer { + v4 := &Signer{ + Credentials: credentials, + } + + for _, option := range options { + option(v4) + } + + return v4 +} + +type signingCtx struct { + ServiceName string + Region string + Request *http.Request + Body io.ReadSeeker + Query url.Values + Time time.Time + ExpireTime time.Duration + SignedHeaderVals http.Header + + DisableURIPathEscaping bool + + credValues credentials.Value + isPresign bool + formattedTime string + formattedShortTime string + unsignedPayload bool + + bodyDigest string + signedHeaders string + canonicalHeaders string + canonicalString string + credentialString string + stringToSign string + signature string + authorization string +} + +// Sign signs AWS v4 requests with the provided body, service name, region the +// request is made to, and time the request is signed at. The signTime allows +// you to specify that a request is signed for the future, and cannot be +// used until then. +// +// Returns a list of HTTP headers that were included in the signature or an +// error if signing the request failed. Generally for signed requests this value +// is not needed as the full request context will be captured by the http.Request +// value. It is included for reference though. +// +// Sign will set the request's Body to be the `body` parameter passed in. If +// the body is not already an io.ReadCloser, it will be wrapped within one. If +// a `nil` body parameter passed to Sign, the request's Body field will be +// also set to nil. Its important to note that this functionality will not +// change the request's ContentLength of the request. +// +// Sign differs from Presign in that it will sign the request using HTTP +// header values. This type of signing is intended for http.Request values that +// will not be shared, or are shared in a way the header values on the request +// will not be lost. +// +// The requests body is an io.ReadSeeker so the SHA256 of the body can be +// generated. To bypass the signer computing the hash you can set the +// "X-Amz-Content-Sha256" header with a precomputed value. The signer will +// only compute the hash if the request header value is empty. +func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region string, signTime time.Time) (http.Header, error) { + return v4.signWithBody(r, body, service, region, 0, false, signTime) +} + +// Presign signs AWS v4 requests with the provided body, service name, region +// the request is made to, and time the request is signed at. The signTime +// allows you to specify that a request is signed for the future, and cannot +// be used until then. +// +// Returns a list of HTTP headers that were included in the signature or an +// error if signing the request failed. For presigned requests these headers +// and their values must be included on the HTTP request when it is made. This +// is helpful to know what header values need to be shared with the party the +// presigned request will be distributed to. +// +// Presign differs from Sign in that it will sign the request using query string +// instead of header values. This allows you to share the Presigned Request's +// URL with third parties, or distribute it throughout your system with minimal +// dependencies. +// +// Presign also takes an exp value which is the duration the +// signed request will be valid after the signing time. This is allows you to +// set when the request will expire. +// +// The requests body is an io.ReadSeeker so the SHA256 of the body can be +// generated. To bypass the signer computing the hash you can set the +// "X-Amz-Content-Sha256" header with a precomputed value. The signer will +// only compute the hash if the request header value is empty. +// +// Presigning a S3 request will not compute the body's SHA256 hash by default. +// This is done due to the general use case for S3 presigned URLs is to share +// PUT/GET capabilities. If you would like to include the body's SHA256 in the +// presigned request's signature you can set the "X-Amz-Content-Sha256" +// HTTP header and that will be included in the request's signature. +func (v4 Signer) Presign(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) { + return v4.signWithBody(r, body, service, region, exp, true, signTime) +} + +func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, isPresign bool, signTime time.Time) (http.Header, error) { + currentTimeFn := v4.currentTimeFn + if currentTimeFn == nil { + currentTimeFn = time.Now + } + + ctx := &signingCtx{ + Request: r, + Body: body, + Query: r.URL.Query(), + Time: signTime, + ExpireTime: exp, + isPresign: isPresign, + ServiceName: service, + Region: region, + DisableURIPathEscaping: v4.DisableURIPathEscaping, + unsignedPayload: v4.UnsignedPayload, + } + + for key := range ctx.Query { + sort.Strings(ctx.Query[key]) + } + + if ctx.isRequestSigned() { + ctx.Time = currentTimeFn() + ctx.handlePresignRemoval() + } + + var err error + ctx.credValues, err = v4.Credentials.Get() + if err != nil { + return http.Header{}, err + } + + ctx.sanitizeHostForHeader() + ctx.assignAmzQueryValues() + ctx.build(v4.DisableHeaderHoisting) + + // If the request is not presigned the body should be attached to it. This + // prevents the confusion of wanting to send a signed request without + // the body the request was signed for attached. + if !(v4.DisableRequestBodyOverwrite || ctx.isPresign) { + var reader io.ReadCloser + if body != nil { + var ok bool + if reader, ok = body.(io.ReadCloser); !ok { + reader = ioutil.NopCloser(body) + } + } + r.Body = reader + } + + if v4.Debug.Matches(aws.LogDebugWithSigning) { + v4.logSigningInfo(ctx) + } + + return ctx.SignedHeaderVals, nil +} + +func (ctx *signingCtx) sanitizeHostForHeader() { + request.SanitizeHostForHeader(ctx.Request) +} + +func (ctx *signingCtx) handlePresignRemoval() { + if !ctx.isPresign { + return + } + + // The credentials have expired for this request. The current signing + // is invalid, and needs to be request because the request will fail. + ctx.removePresign() + + // Update the request's query string to ensure the values stays in + // sync in the case retrieving the new credentials fails. + ctx.Request.URL.RawQuery = ctx.Query.Encode() +} + +func (ctx *signingCtx) assignAmzQueryValues() { + if ctx.isPresign { + ctx.Query.Set("X-Amz-Algorithm", authHeaderPrefix) + if ctx.credValues.SessionToken != "" { + ctx.Query.Set("X-Amz-Security-Token", ctx.credValues.SessionToken) + } else { + ctx.Query.Del("X-Amz-Security-Token") + } + + return + } + + if ctx.credValues.SessionToken != "" { + ctx.Request.Header.Set("X-Amz-Security-Token", ctx.credValues.SessionToken) + } +} + +// SignRequestHandler is a named request handler the SDK will use to sign +// service client request with using the V4 signature. +var SignRequestHandler = request.NamedHandler{ + Name: "v4.SignRequestHandler", Fn: SignSDKRequest, +} + +// SignSDKRequest signs an AWS request with the V4 signature. This +// request handler should only be used with the SDK's built in service client's +// API operation requests. +// +// This function should not be used on its on its own, but in conjunction with +// an AWS service client's API operation call. To sign a standalone request +// not created by a service client's API operation method use the "Sign" or +// "Presign" functions of the "Signer" type. +// +// If the credentials of the request's config are set to +// credentials.AnonymousCredentials the request will not be signed. +func SignSDKRequest(req *request.Request) { + signSDKRequestWithCurrTime(req, time.Now) +} + +// BuildNamedHandler will build a generic handler for signing. +func BuildNamedHandler(name string, opts ...func(*Signer)) request.NamedHandler { + return request.NamedHandler{ + Name: name, + Fn: func(req *request.Request) { + signSDKRequestWithCurrTime(req, time.Now, opts...) + }, + } +} + +func signSDKRequestWithCurrTime(req *request.Request, curTimeFn func() time.Time, opts ...func(*Signer)) { + // If the request does not need to be signed ignore the signing of the + // request if the AnonymousCredentials object is used. + if req.Config.Credentials == credentials.AnonymousCredentials { + return + } + + region := req.ClientInfo.SigningRegion + if region == "" { + region = aws.StringValue(req.Config.Region) + } + + name := req.ClientInfo.SigningName + if name == "" { + name = req.ClientInfo.ServiceName + } + + v4 := NewSigner(req.Config.Credentials, func(v4 *Signer) { + v4.Debug = req.Config.LogLevel.Value() + v4.Logger = req.Config.Logger + v4.DisableHeaderHoisting = req.NotHoist + v4.currentTimeFn = curTimeFn + if name == "s3" { + // S3 service should not have any escaping applied + v4.DisableURIPathEscaping = true + } + // Prevents setting the HTTPRequest's Body. Since the Body could be + // wrapped in a custom io.Closer that we do not want to be stompped + // on top of by the signer. + v4.DisableRequestBodyOverwrite = true + }) + + for _, opt := range opts { + opt(v4) + } + + signingTime := req.Time + if !req.LastSignedAt.IsZero() { + signingTime = req.LastSignedAt + } + + signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(), + name, region, req.ExpireTime, req.ExpireTime > 0, signingTime, + ) + if err != nil { + req.Error = err + req.SignedHeaderVals = nil + return + } + + req.SignedHeaderVals = signedHeaders + req.LastSignedAt = curTimeFn() +} + +const logSignInfoMsg = `DEBUG: Request Signature: +---[ CANONICAL STRING ]----------------------------- +%s +---[ STRING TO SIGN ]-------------------------------- +%s%s +-----------------------------------------------------` +const logSignedURLMsg = ` +---[ SIGNED URL ]------------------------------------ +%s` + +func (v4 *Signer) logSigningInfo(ctx *signingCtx) { + signedURLMsg := "" + if ctx.isPresign { + signedURLMsg = fmt.Sprintf(logSignedURLMsg, ctx.Request.URL.String()) + } + msg := fmt.Sprintf(logSignInfoMsg, ctx.canonicalString, ctx.stringToSign, signedURLMsg) + v4.Logger.Log(msg) +} + +func (ctx *signingCtx) build(disableHeaderHoisting bool) { + ctx.buildTime() // no depends + ctx.buildCredentialString() // no depends + + ctx.buildBodyDigest() + + unsignedHeaders := ctx.Request.Header + if ctx.isPresign { + if !disableHeaderHoisting { + urlValues := url.Values{} + urlValues, unsignedHeaders = buildQuery(allowedQueryHoisting, unsignedHeaders) // no depends + for k := range urlValues { + ctx.Query[k] = urlValues[k] + } + } + } + + ctx.buildCanonicalHeaders(ignoredHeaders, unsignedHeaders) + ctx.buildCanonicalString() // depends on canon headers / signed headers + ctx.buildStringToSign() // depends on canon string + ctx.buildSignature() // depends on string to sign + + if ctx.isPresign { + ctx.Request.URL.RawQuery += "&X-Amz-Signature=" + ctx.signature + } else { + parts := []string{ + authHeaderPrefix + " Credential=" + ctx.credValues.AccessKeyID + "/" + ctx.credentialString, + "SignedHeaders=" + ctx.signedHeaders, + "Signature=" + ctx.signature, + } + ctx.Request.Header.Set("Authorization", strings.Join(parts, ", ")) + } +} + +func (ctx *signingCtx) buildTime() { + ctx.formattedTime = ctx.Time.UTC().Format(timeFormat) + ctx.formattedShortTime = ctx.Time.UTC().Format(shortTimeFormat) + + if ctx.isPresign { + duration := int64(ctx.ExpireTime / time.Second) + ctx.Query.Set("X-Amz-Date", ctx.formattedTime) + ctx.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10)) + } else { + ctx.Request.Header.Set("X-Amz-Date", ctx.formattedTime) + } +} + +func (ctx *signingCtx) buildCredentialString() { + ctx.credentialString = strings.Join([]string{ + ctx.formattedShortTime, + ctx.Region, + ctx.ServiceName, + "aws4_request", + }, "/") + + if ctx.isPresign { + ctx.Query.Set("X-Amz-Credential", ctx.credValues.AccessKeyID+"/"+ctx.credentialString) + } +} + +func buildQuery(r rule, header http.Header) (url.Values, http.Header) { + query := url.Values{} + unsignedHeaders := http.Header{} + for k, h := range header { + if r.IsValid(k) { + query[k] = h + } else { + unsignedHeaders[k] = h + } + } + + return query, unsignedHeaders +} +func (ctx *signingCtx) buildCanonicalHeaders(r rule, header http.Header) { + var headers []string + headers = append(headers, "host") + for k, v := range header { + canonicalKey := http.CanonicalHeaderKey(k) + if !r.IsValid(canonicalKey) { + continue // ignored header + } + if ctx.SignedHeaderVals == nil { + ctx.SignedHeaderVals = make(http.Header) + } + + lowerCaseKey := strings.ToLower(k) + if _, ok := ctx.SignedHeaderVals[lowerCaseKey]; ok { + // include additional values + ctx.SignedHeaderVals[lowerCaseKey] = append(ctx.SignedHeaderVals[lowerCaseKey], v...) + continue + } + + headers = append(headers, lowerCaseKey) + ctx.SignedHeaderVals[lowerCaseKey] = v + } + sort.Strings(headers) + + ctx.signedHeaders = strings.Join(headers, ";") + + if ctx.isPresign { + ctx.Query.Set("X-Amz-SignedHeaders", ctx.signedHeaders) + } + + headerValues := make([]string, len(headers)) + for i, k := range headers { + if k == "host" { + if ctx.Request.Host != "" { + headerValues[i] = "host:" + ctx.Request.Host + } else { + headerValues[i] = "host:" + ctx.Request.URL.Host + } + } else { + headerValues[i] = k + ":" + + strings.Join(ctx.SignedHeaderVals[k], ",") + } + } + stripExcessSpaces(headerValues) + ctx.canonicalHeaders = strings.Join(headerValues, "\n") +} + +func (ctx *signingCtx) buildCanonicalString() { + ctx.Request.URL.RawQuery = strings.Replace(ctx.Query.Encode(), "+", "%20", -1) + + uri := getURIPath(ctx.Request.URL) + + if !ctx.DisableURIPathEscaping { + uri = rest.EscapePath(uri, false) + } + + ctx.canonicalString = strings.Join([]string{ + ctx.Request.Method, + uri, + ctx.Request.URL.RawQuery, + ctx.canonicalHeaders + "\n", + ctx.signedHeaders, + ctx.bodyDigest, + }, "\n") +} + +func (ctx *signingCtx) buildStringToSign() { + ctx.stringToSign = strings.Join([]string{ + authHeaderPrefix, + ctx.formattedTime, + ctx.credentialString, + hex.EncodeToString(makeSha256([]byte(ctx.canonicalString))), + }, "\n") +} + +func (ctx *signingCtx) buildSignature() { + secret := ctx.credValues.SecretAccessKey + date := makeHmac([]byte("AWS4"+secret), []byte(ctx.formattedShortTime)) + region := makeHmac(date, []byte(ctx.Region)) + service := makeHmac(region, []byte(ctx.ServiceName)) + credentials := makeHmac(service, []byte("aws4_request")) + signature := makeHmac(credentials, []byte(ctx.stringToSign)) + ctx.signature = hex.EncodeToString(signature) +} + +func (ctx *signingCtx) buildBodyDigest() { + hash := ctx.Request.Header.Get("X-Amz-Content-Sha256") + if hash == "" { + if ctx.unsignedPayload || (ctx.isPresign && ctx.ServiceName == "s3") { + hash = "UNSIGNED-PAYLOAD" + } else if ctx.Body == nil { + hash = emptyStringSHA256 + } else { + hash = hex.EncodeToString(makeSha256Reader(ctx.Body)) + } + if ctx.unsignedPayload || ctx.ServiceName == "s3" || ctx.ServiceName == "glacier" { + ctx.Request.Header.Set("X-Amz-Content-Sha256", hash) + } + } + ctx.bodyDigest = hash +} + +// isRequestSigned returns if the request is currently signed or presigned +func (ctx *signingCtx) isRequestSigned() bool { + if ctx.isPresign && ctx.Query.Get("X-Amz-Signature") != "" { + return true + } + if ctx.Request.Header.Get("Authorization") != "" { + return true + } + + return false +} + +// unsign removes signing flags for both signed and presigned requests. +func (ctx *signingCtx) removePresign() { + ctx.Query.Del("X-Amz-Algorithm") + ctx.Query.Del("X-Amz-Signature") + ctx.Query.Del("X-Amz-Security-Token") + ctx.Query.Del("X-Amz-Date") + ctx.Query.Del("X-Amz-Expires") + ctx.Query.Del("X-Amz-Credential") + ctx.Query.Del("X-Amz-SignedHeaders") +} + +func makeHmac(key []byte, data []byte) []byte { + hash := hmac.New(sha256.New, key) + hash.Write(data) + return hash.Sum(nil) +} + +func makeSha256(data []byte) []byte { + hash := sha256.New() + hash.Write(data) + return hash.Sum(nil) +} + +func makeSha256Reader(reader io.ReadSeeker) []byte { + hash := sha256.New() + start, _ := reader.Seek(0, 1) + defer reader.Seek(start, 0) + + io.Copy(hash, reader) + return hash.Sum(nil) +} + +const doubleSpace = " " + +// stripExcessSpaces will rewrite the passed in slice's string values to not +// contain muliple side-by-side spaces. +func stripExcessSpaces(vals []string) { + var j, k, l, m, spaces int + for i, str := range vals { + // Trim trailing spaces + for j = len(str) - 1; j >= 0 && str[j] == ' '; j-- { + } + + // Trim leading spaces + for k = 0; k < j && str[k] == ' '; k++ { + } + str = str[k : j+1] + + // Strip multiple spaces. + j = strings.Index(str, doubleSpace) + if j < 0 { + vals[i] = str + continue + } + + buf := []byte(str) + for k, m, l = j, j, len(buf); k < l; k++ { + if buf[k] == ' ' { + if spaces == 0 { + // First space. + buf[m] = buf[k] + m++ + } + spaces++ + } else { + // End of multiple spaces. + spaces = 0 + buf[m] = buf[k] + m++ + } + } + + vals[i] = string(buf[:m]) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4_test.go b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4_test.go new file mode 100644 index 0000000..45d0eb8 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4_test.go @@ -0,0 +1,644 @@ +package v4 + +import ( + "bytes" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/awstesting" +) + +func TestStripExcessHeaders(t *testing.T) { + vals := []string{ + "", + "123", + "1 2 3", + "1 2 3 ", + " 1 2 3", + "1 2 3", + "1 23", + "1 2 3", + "1 2 ", + " 1 2 ", + "12 3", + "12 3 1", + "12 3 1", + "12 3 1abc123", + } + + expected := []string{ + "", + "123", + "1 2 3", + "1 2 3", + "1 2 3", + "1 2 3", + "1 23", + "1 2 3", + "1 2", + "1 2", + "12 3", + "12 3 1", + "12 3 1", + "12 3 1abc123", + } + + stripExcessSpaces(vals) + for i := 0; i < len(vals); i++ { + if e, a := expected[i], vals[i]; e != a { + t.Errorf("%d, expect %v, got %v", i, e, a) + } + } +} + +func buildRequest(serviceName, region, body string) (*http.Request, io.ReadSeeker) { + endpoint := "https://" + serviceName + "." + region + ".amazonaws.com" + reader := strings.NewReader(body) + req, _ := http.NewRequest("POST", endpoint, reader) + req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()" + req.Header.Add("X-Amz-Target", "prefix.Operation") + req.Header.Add("Content-Type", "application/x-amz-json-1.0") + req.Header.Add("Content-Length", string(len(body))) + req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* (+)") + req.Header.Add("X-Amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)") + req.Header.Add("X-amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)") + return req, reader +} + +func buildSigner() Signer { + return Signer{ + Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), + } +} + +func removeWS(text string) string { + text = strings.Replace(text, " ", "", -1) + text = strings.Replace(text, "\n", "", -1) + text = strings.Replace(text, "\t", "", -1) + return text +} + +func assertEqual(t *testing.T, expected, given string) { + if removeWS(expected) != removeWS(given) { + t.Errorf("\nExpected: %s\nGiven: %s", expected, given) + } +} + +func TestPresignRequest(t *testing.T) { + req, body := buildRequest("dynamodb", "us-east-1", "{}") + + signer := buildSigner() + signer.Presign(req, body, "dynamodb", "us-east-1", 300*time.Second, time.Unix(0, 0)) + + expectedDate := "19700101T000000Z" + expectedHeaders := "content-length;content-type;host;x-amz-meta-other-header;x-amz-meta-other-header_with_underscore" + expectedSig := "ea7856749041f727690c580569738282e99c79355fe0d8f125d3b5535d2ece83" + expectedCred := "AKID/19700101/us-east-1/dynamodb/aws4_request" + expectedTarget := "prefix.Operation" + + q := req.URL.Query() + if e, a := expectedSig, q.Get("X-Amz-Signature"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedCred, q.Get("X-Amz-Credential"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedHeaders, q.Get("X-Amz-SignedHeaders"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedDate, q.Get("X-Amz-Date"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if a := q.Get("X-Amz-Meta-Other-Header"); len(a) != 0 { + t.Errorf("expect %v to be empty", a) + } + if e, a := expectedTarget, q.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestPresignBodyWithArrayRequest(t *testing.T) { + req, body := buildRequest("dynamodb", "us-east-1", "{}") + req.URL.RawQuery = "Foo=z&Foo=o&Foo=m&Foo=a" + + signer := buildSigner() + signer.Presign(req, body, "dynamodb", "us-east-1", 300*time.Second, time.Unix(0, 0)) + + expectedDate := "19700101T000000Z" + expectedHeaders := "content-length;content-type;host;x-amz-meta-other-header;x-amz-meta-other-header_with_underscore" + expectedSig := "fef6002062400bbf526d70f1a6456abc0fb2e213fe1416012737eebd42a62924" + expectedCred := "AKID/19700101/us-east-1/dynamodb/aws4_request" + expectedTarget := "prefix.Operation" + + q := req.URL.Query() + if e, a := expectedSig, q.Get("X-Amz-Signature"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedCred, q.Get("X-Amz-Credential"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedHeaders, q.Get("X-Amz-SignedHeaders"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedDate, q.Get("X-Amz-Date"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if a := q.Get("X-Amz-Meta-Other-Header"); len(a) != 0 { + t.Errorf("expect %v to be empty, was not", a) + } + if e, a := expectedTarget, q.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestSignRequest(t *testing.T) { + req, body := buildRequest("dynamodb", "us-east-1", "{}") + signer := buildSigner() + signer.Sign(req, body, "dynamodb", "us-east-1", time.Unix(0, 0)) + + expectedDate := "19700101T000000Z" + expectedSig := "AWS4-HMAC-SHA256 Credential=AKID/19700101/us-east-1/dynamodb/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date;x-amz-meta-other-header;x-amz-meta-other-header_with_underscore;x-amz-security-token;x-amz-target, Signature=ea766cabd2ec977d955a3c2bae1ae54f4515d70752f2207618396f20aa85bd21" + + q := req.Header + if e, a := expectedSig, q.Get("Authorization"); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := expectedDate, q.Get("X-Amz-Date"); e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestSignBodyS3(t *testing.T) { + req, body := buildRequest("s3", "us-east-1", "hello") + signer := buildSigner() + signer.Sign(req, body, "s3", "us-east-1", time.Now()) + hash := req.Header.Get("X-Amz-Content-Sha256") + if e, a := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestSignBodyGlacier(t *testing.T) { + req, body := buildRequest("glacier", "us-east-1", "hello") + signer := buildSigner() + signer.Sign(req, body, "glacier", "us-east-1", time.Now()) + hash := req.Header.Get("X-Amz-Content-Sha256") + if e, a := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", hash; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestPresignEmptyBodyS3(t *testing.T) { + req, body := buildRequest("s3", "us-east-1", "hello") + signer := buildSigner() + signer.Presign(req, body, "s3", "us-east-1", 5*time.Minute, time.Now()) + hash := req.Header.Get("X-Amz-Content-Sha256") + if e, a := "UNSIGNED-PAYLOAD", hash; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestSignPrecomputedBodyChecksum(t *testing.T) { + req, body := buildRequest("dynamodb", "us-east-1", "hello") + req.Header.Set("X-Amz-Content-Sha256", "PRECOMPUTED") + signer := buildSigner() + signer.Sign(req, body, "dynamodb", "us-east-1", time.Now()) + hash := req.Header.Get("X-Amz-Content-Sha256") + if e, a := "PRECOMPUTED", hash; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestAnonymousCredentials(t *testing.T) { + svc := awstesting.NewClient(&aws.Config{Credentials: credentials.AnonymousCredentials}) + r := svc.NewRequest( + &request.Operation{ + Name: "BatchGetItem", + HTTPMethod: "POST", + HTTPPath: "/", + }, + nil, + nil, + ) + SignSDKRequest(r) + + urlQ := r.HTTPRequest.URL.Query() + if a := urlQ.Get("X-Amz-Signature"); len(a) != 0 { + t.Errorf("expect %v to be empty, was not", a) + } + if a := urlQ.Get("X-Amz-Credential"); len(a) != 0 { + t.Errorf("expect %v to be empty, was not", a) + } + if a := urlQ.Get("X-Amz-SignedHeaders"); len(a) != 0 { + t.Errorf("expect %v to be empty, was not", a) + } + if a := urlQ.Get("X-Amz-Date"); len(a) != 0 { + t.Errorf("expect %v to be empty, was not", a) + } + + hQ := r.HTTPRequest.Header + if a := hQ.Get("Authorization"); len(a) != 0 { + t.Errorf("expect %v to be empty, was not", a) + } + if a := hQ.Get("X-Amz-Date"); len(a) != 0 { + t.Errorf("expect %v to be empty, was not", a) + } +} + +func TestIgnoreResignRequestWithValidCreds(t *testing.T) { + svc := awstesting.NewClient(&aws.Config{ + Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), + Region: aws.String("us-west-2"), + }) + r := svc.NewRequest( + &request.Operation{ + Name: "BatchGetItem", + HTTPMethod: "POST", + HTTPPath: "/", + }, + nil, + nil, + ) + + SignSDKRequest(r) + sig := r.HTTPRequest.Header.Get("Authorization") + + signSDKRequestWithCurrTime(r, func() time.Time { + // Simulate one second has passed so that signature's date changes + // when it is resigned. + return time.Now().Add(1 * time.Second) + }) + if e, a := sig, r.HTTPRequest.Header.Get("Authorization"); e == a { + t.Errorf("expect %v to be %v, but was not", e, a) + } +} + +func TestIgnorePreResignRequestWithValidCreds(t *testing.T) { + svc := awstesting.NewClient(&aws.Config{ + Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"), + Region: aws.String("us-west-2"), + }) + r := svc.NewRequest( + &request.Operation{ + Name: "BatchGetItem", + HTTPMethod: "POST", + HTTPPath: "/", + }, + nil, + nil, + ) + r.ExpireTime = time.Minute * 10 + + SignSDKRequest(r) + sig := r.HTTPRequest.URL.Query().Get("X-Amz-Signature") + + signSDKRequestWithCurrTime(r, func() time.Time { + // Simulate one second has passed so that signature's date changes + // when it is resigned. + return time.Now().Add(1 * time.Second) + }) + if e, a := sig, r.HTTPRequest.URL.Query().Get("X-Amz-Signature"); e == a { + t.Errorf("expect %v to be %v, but was not", e, a) + } +} + +func TestResignRequestExpiredCreds(t *testing.T) { + creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") + svc := awstesting.NewClient(&aws.Config{Credentials: creds}) + r := svc.NewRequest( + &request.Operation{ + Name: "BatchGetItem", + HTTPMethod: "POST", + HTTPPath: "/", + }, + nil, + nil, + ) + SignSDKRequest(r) + querySig := r.HTTPRequest.Header.Get("Authorization") + var origSignedHeaders string + for _, p := range strings.Split(querySig, ", ") { + if strings.HasPrefix(p, "SignedHeaders=") { + origSignedHeaders = p[len("SignedHeaders="):] + break + } + } + if a := origSignedHeaders; len(a) == 0 { + t.Errorf("expect not to be empty, but was") + } + if e, a := origSignedHeaders, "authorization"; strings.Contains(a, e) { + t.Errorf("expect %v to not be in %v, but was", e, a) + } + origSignedAt := r.LastSignedAt + + creds.Expire() + + signSDKRequestWithCurrTime(r, func() time.Time { + // Simulate one second has passed so that signature's date changes + // when it is resigned. + return time.Now().Add(1 * time.Second) + }) + updatedQuerySig := r.HTTPRequest.Header.Get("Authorization") + if e, a := querySig, updatedQuerySig; e == a { + t.Errorf("expect %v to be %v, was not", e, a) + } + + var updatedSignedHeaders string + for _, p := range strings.Split(updatedQuerySig, ", ") { + if strings.HasPrefix(p, "SignedHeaders=") { + updatedSignedHeaders = p[len("SignedHeaders="):] + break + } + } + if a := updatedSignedHeaders; len(a) == 0 { + t.Errorf("expect not to be empty, but was") + } + if e, a := updatedQuerySig, "authorization"; strings.Contains(a, e) { + t.Errorf("expect %v to not be in %v, but was", e, a) + } + if e, a := origSignedAt, r.LastSignedAt; e == a { + t.Errorf("expect %v to be %v, was not", e, a) + } +} + +func TestPreResignRequestExpiredCreds(t *testing.T) { + provider := &credentials.StaticProvider{Value: credentials.Value{ + AccessKeyID: "AKID", + SecretAccessKey: "SECRET", + SessionToken: "SESSION", + }} + creds := credentials.NewCredentials(provider) + svc := awstesting.NewClient(&aws.Config{Credentials: creds}) + r := svc.NewRequest( + &request.Operation{ + Name: "BatchGetItem", + HTTPMethod: "POST", + HTTPPath: "/", + }, + nil, + nil, + ) + r.ExpireTime = time.Minute * 10 + + SignSDKRequest(r) + querySig := r.HTTPRequest.URL.Query().Get("X-Amz-Signature") + signedHeaders := r.HTTPRequest.URL.Query().Get("X-Amz-SignedHeaders") + if a := signedHeaders; len(a) == 0 { + t.Errorf("expect not to be empty, but was") + } + origSignedAt := r.LastSignedAt + + creds.Expire() + + signSDKRequestWithCurrTime(r, func() time.Time { + // Simulate the request occurred 15 minutes in the past + return time.Now().Add(-48 * time.Hour) + }) + if e, a := querySig, r.HTTPRequest.URL.Query().Get("X-Amz-Signature"); e == a { + t.Errorf("expect %v to be %v, was not", e, a) + } + resignedHeaders := r.HTTPRequest.URL.Query().Get("X-Amz-SignedHeaders") + if e, a := signedHeaders, resignedHeaders; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := signedHeaders, "x-amz-signedHeaders"; strings.Contains(a, e) { + t.Errorf("expect %v to not be in %v, but was", e, a) + } + if e, a := origSignedAt, r.LastSignedAt; e == a { + t.Errorf("expect %v to be %v, was not", e, a) + } +} + +func TestResignRequestExpiredRequest(t *testing.T) { + creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") + svc := awstesting.NewClient(&aws.Config{Credentials: creds}) + r := svc.NewRequest( + &request.Operation{ + Name: "BatchGetItem", + HTTPMethod: "POST", + HTTPPath: "/", + }, + nil, + nil, + ) + + SignSDKRequest(r) + querySig := r.HTTPRequest.Header.Get("Authorization") + origSignedAt := r.LastSignedAt + + signSDKRequestWithCurrTime(r, func() time.Time { + // Simulate the request occurred 15 minutes in the past + return time.Now().Add(15 * time.Minute) + }) + if e, a := querySig, r.HTTPRequest.Header.Get("Authorization"); e == a { + t.Errorf("expect %v to be %v, was not", e, a) + } + if e, a := origSignedAt, r.LastSignedAt; e == a { + t.Errorf("expect %v to be %v, was not", e, a) + } +} + +func TestSignWithRequestBody(t *testing.T) { + creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") + signer := NewSigner(creds) + + expectBody := []byte("abc123") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + r.Body.Close() + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if e, a := expectBody, b; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } + w.WriteHeader(http.StatusOK) + })) + + req, err := http.NewRequest("POST", server.URL, nil) + + _, err = signer.Sign(req, bytes.NewReader(expectBody), "service", "region", time.Now()) + if err != nil { + t.Errorf("expect not no error, got %v", err) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Errorf("expect not no error, got %v", err) + } + if e, a := http.StatusOK, resp.StatusCode; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestSignWithRequestBody_Overwrite(t *testing.T) { + creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") + signer := NewSigner(creds) + + var expectBody []byte + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + r.Body.Close() + if err != nil { + t.Errorf("expect not no error, got %v", err) + } + if e, a := len(expectBody), len(b); e != a { + t.Errorf("expect %v, got %v", e, a) + } + w.WriteHeader(http.StatusOK) + })) + + req, err := http.NewRequest("GET", server.URL, strings.NewReader("invalid body")) + + _, err = signer.Sign(req, nil, "service", "region", time.Now()) + req.ContentLength = 0 + + if err != nil { + t.Errorf("expect not no error, got %v", err) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Errorf("expect not no error, got %v", err) + } + if e, a := http.StatusOK, resp.StatusCode; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestBuildCanonicalRequest(t *testing.T) { + req, body := buildRequest("dynamodb", "us-east-1", "{}") + req.URL.RawQuery = "Foo=z&Foo=o&Foo=m&Foo=a" + ctx := &signingCtx{ + ServiceName: "dynamodb", + Region: "us-east-1", + Request: req, + Body: body, + Query: req.URL.Query(), + Time: time.Now(), + ExpireTime: 5 * time.Second, + } + + ctx.buildCanonicalString() + expected := "https://example.org/bucket/key-._~,!@#$%^&*()?Foo=z&Foo=o&Foo=m&Foo=a" + if e, a := expected, ctx.Request.URL.String(); e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestSignWithBody_ReplaceRequestBody(t *testing.T) { + creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") + req, seekerBody := buildRequest("dynamodb", "us-east-1", "{}") + req.Body = ioutil.NopCloser(bytes.NewReader([]byte{})) + + s := NewSigner(creds) + origBody := req.Body + + _, err := s.Sign(req, seekerBody, "dynamodb", "us-east-1", time.Now()) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if req.Body == origBody { + t.Errorf("expeect request body to not be origBody") + } + + if req.Body == nil { + t.Errorf("expect request body to be changed but was nil") + } +} + +func TestSignWithBody_NoReplaceRequestBody(t *testing.T) { + creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") + req, seekerBody := buildRequest("dynamodb", "us-east-1", "{}") + req.Body = ioutil.NopCloser(bytes.NewReader([]byte{})) + + s := NewSigner(creds, func(signer *Signer) { + signer.DisableRequestBodyOverwrite = true + }) + + origBody := req.Body + + _, err := s.Sign(req, seekerBody, "dynamodb", "us-east-1", time.Now()) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if req.Body != origBody { + t.Errorf("expect request body to not be chagned") + } +} + +func TestRequestHost(t *testing.T) { + req, body := buildRequest("dynamodb", "us-east-1", "{}") + req.URL.RawQuery = "Foo=z&Foo=o&Foo=m&Foo=a" + req.Host = "myhost" + ctx := &signingCtx{ + ServiceName: "dynamodb", + Region: "us-east-1", + Request: req, + Body: body, + Query: req.URL.Query(), + Time: time.Now(), + ExpireTime: 5 * time.Second, + } + + ctx.buildCanonicalHeaders(ignoredHeaders, ctx.Request.Header) + if !strings.Contains(ctx.canonicalHeaders, "host:"+req.Host) { + t.Errorf("canonical host header invalid") + } +} + +func BenchmarkPresignRequest(b *testing.B) { + signer := buildSigner() + req, body := buildRequest("dynamodb", "us-east-1", "{}") + for i := 0; i < b.N; i++ { + signer.Presign(req, body, "dynamodb", "us-east-1", 300*time.Second, time.Now()) + } +} + +func BenchmarkSignRequest(b *testing.B) { + signer := buildSigner() + req, body := buildRequest("dynamodb", "us-east-1", "{}") + for i := 0; i < b.N; i++ { + signer.Sign(req, body, "dynamodb", "us-east-1", time.Now()) + } +} + +var stripExcessSpaceCases = []string{ + `AWS4-HMAC-SHA256 Credential=AKIDFAKEIDFAKEID/20160628/us-west-2/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=1234567890abcdef1234567890abcdef1234567890abcdef`, + `123 321 123 321`, + ` 123 321 123 321 `, + ` 123 321 123 321 `, + "123", + "1 2 3", + " 1 2 3", + "1 2 3", + "1 23", + "1 2 3", + "1 2 ", + " 1 2 ", + "12 3", + "12 3 1", + "12 3 1", + "12 3 1abc123", +} + +func BenchmarkStripExcessSpaces(b *testing.B) { + for i := 0; i < b.N; i++ { + // Make sure to start with a copy of the cases + cases := append([]string{}, stripExcessSpaceCases...) + stripExcessSpaces(cases) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/types.go b/vendor/github.com/aws/aws-sdk-go/aws/types.go new file mode 100644 index 0000000..0e2d864 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/types.go @@ -0,0 +1,118 @@ +package aws + +import ( + "io" + "sync" +) + +// ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser. Should +// only be used with an io.Reader that is also an io.Seeker. Doing so may +// cause request signature errors, or request body's not sent for GET, HEAD +// and DELETE HTTP methods. +// +// Deprecated: Should only be used with io.ReadSeeker. If using for +// S3 PutObject to stream content use s3manager.Uploader instead. +func ReadSeekCloser(r io.Reader) ReaderSeekerCloser { + return ReaderSeekerCloser{r} +} + +// ReaderSeekerCloser represents a reader that can also delegate io.Seeker and +// io.Closer interfaces to the underlying object if they are available. +type ReaderSeekerCloser struct { + r io.Reader +} + +// Read reads from the reader up to size of p. The number of bytes read, and +// error if it occurred will be returned. +// +// If the reader is not an io.Reader zero bytes read, and nil error will be returned. +// +// Performs the same functionality as io.Reader Read +func (r ReaderSeekerCloser) Read(p []byte) (int, error) { + switch t := r.r.(type) { + case io.Reader: + return t.Read(p) + } + return 0, nil +} + +// Seek sets the offset for the next Read to offset, interpreted according to +// whence: 0 means relative to the origin of the file, 1 means relative to the +// current offset, and 2 means relative to the end. Seek returns the new offset +// and an error, if any. +// +// If the ReaderSeekerCloser is not an io.Seeker nothing will be done. +func (r ReaderSeekerCloser) Seek(offset int64, whence int) (int64, error) { + switch t := r.r.(type) { + case io.Seeker: + return t.Seek(offset, whence) + } + return int64(0), nil +} + +// IsSeeker returns if the underlying reader is also a seeker. +func (r ReaderSeekerCloser) IsSeeker() bool { + _, ok := r.r.(io.Seeker) + return ok +} + +// Close closes the ReaderSeekerCloser. +// +// If the ReaderSeekerCloser is not an io.Closer nothing will be done. +func (r ReaderSeekerCloser) Close() error { + switch t := r.r.(type) { + case io.Closer: + return t.Close() + } + return nil +} + +// A WriteAtBuffer provides a in memory buffer supporting the io.WriterAt interface +// Can be used with the s3manager.Downloader to download content to a buffer +// in memory. Safe to use concurrently. +type WriteAtBuffer struct { + buf []byte + m sync.Mutex + + // GrowthCoeff defines the growth rate of the internal buffer. By + // default, the growth rate is 1, where expanding the internal + // buffer will allocate only enough capacity to fit the new expected + // length. + GrowthCoeff float64 +} + +// NewWriteAtBuffer creates a WriteAtBuffer with an internal buffer +// provided by buf. +func NewWriteAtBuffer(buf []byte) *WriteAtBuffer { + return &WriteAtBuffer{buf: buf} +} + +// WriteAt writes a slice of bytes to a buffer starting at the position provided +// The number of bytes written will be returned, or error. Can overwrite previous +// written slices if the write ats overlap. +func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) { + pLen := len(p) + expLen := pos + int64(pLen) + b.m.Lock() + defer b.m.Unlock() + if int64(len(b.buf)) < expLen { + if int64(cap(b.buf)) < expLen { + if b.GrowthCoeff < 1 { + b.GrowthCoeff = 1 + } + newBuf := make([]byte, expLen, int64(b.GrowthCoeff*float64(expLen))) + copy(newBuf, b.buf) + b.buf = newBuf + } + b.buf = b.buf[:expLen] + } + copy(b.buf[pos:], p) + return pLen, nil +} + +// Bytes returns a slice of bytes written to the buffer. +func (b *WriteAtBuffer) Bytes() []byte { + b.m.Lock() + defer b.m.Unlock() + return b.buf +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/types_test.go b/vendor/github.com/aws/aws-sdk-go/aws/types_test.go new file mode 100644 index 0000000..e399ef5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/types_test.go @@ -0,0 +1,92 @@ +package aws + +import ( + "bytes" + "math/rand" + "testing" +) + +func TestWriteAtBuffer(t *testing.T) { + b := &WriteAtBuffer{} + + n, err := b.WriteAt([]byte{1}, 0) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + if e, a := 1, n; e != a { + t.Errorf("expected %d, but recieved %d", e, a) + } + + n, err = b.WriteAt([]byte{1, 1, 1}, 5) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + if e, a := 3, n; e != a { + t.Errorf("expected %d, but recieved %d", e, a) + } + + n, err = b.WriteAt([]byte{2}, 1) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + if e, a := 1, n; e != a { + t.Errorf("expected %d, but recieved %d", e, a) + } + + n, err = b.WriteAt([]byte{3}, 2) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + if e, a := 1, n; e != a { + t.Errorf("expected %d, but received %d", e, a) + } + + if !bytes.Equal([]byte{1, 2, 3, 0, 0, 1, 1, 1}, b.Bytes()) { + t.Errorf("expected %v, but received %v", []byte{1, 2, 3, 0, 0, 1, 1, 1}, b.Bytes()) + } +} + +func BenchmarkWriteAtBuffer(b *testing.B) { + buf := &WriteAtBuffer{} + r := rand.New(rand.NewSource(1)) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + to := r.Intn(10) * 4096 + bs := make([]byte, to) + buf.WriteAt(bs, r.Int63n(10)*4096) + } +} + +func BenchmarkWriteAtBufferOrderedWrites(b *testing.B) { + // test the performance of a WriteAtBuffer when written in an + // ordered fashion. This is similar to the behavior of the + // s3.Downloader, since downloads the first chunk of the file, then + // the second, and so on. + // + // This test simulates a 150MB file being written in 30 ordered 5MB chunks. + chunk := int64(5e6) + max := chunk * 30 + // we'll write the same 5MB chunk every time + tmp := make([]byte, chunk) + for i := 0; i < b.N; i++ { + buf := &WriteAtBuffer{} + for i := int64(0); i < max; i += chunk { + buf.WriteAt(tmp, i) + } + } +} + +func BenchmarkWriteAtBufferParallel(b *testing.B) { + buf := &WriteAtBuffer{} + r := rand.New(rand.NewSource(1)) + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + to := r.Intn(10) * 4096 + bs := make([]byte, to) + buf.WriteAt(bs, r.Int63n(10)*4096) + } + }) +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/url.go b/vendor/github.com/aws/aws-sdk-go/aws/url.go new file mode 100644 index 0000000..6192b24 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/url.go @@ -0,0 +1,12 @@ +// +build go1.8 + +package aws + +import "net/url" + +// URLHostname will extract the Hostname without port from the URL value. +// +// Wrapper of net/url#URL.Hostname for backwards Go version compatibility. +func URLHostname(url *url.URL) string { + return url.Hostname() +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/url_1_7.go b/vendor/github.com/aws/aws-sdk-go/aws/url_1_7.go new file mode 100644 index 0000000..0210d27 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/url_1_7.go @@ -0,0 +1,29 @@ +// +build !go1.8 + +package aws + +import ( + "net/url" + "strings" +) + +// URLHostname will extract the Hostname without port from the URL value. +// +// Copy of Go 1.8's net/url#URL.Hostname functionality. +func URLHostname(url *url.URL) string { + return stripPort(url.Host) + +} + +// stripPort is copy of Go 1.8 url#URL.Hostname functionality. +// https://golang.org/src/net/url/url.go +func stripPort(hostport string) string { + colon := strings.IndexByte(hostport, ':') + if colon == -1 { + return hostport + } + if i := strings.IndexByte(hostport, ']'); i != -1 { + return strings.TrimPrefix(hostport[:i], "[") + } + return hostport[:colon] +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go new file mode 100644 index 0000000..b74e08a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -0,0 +1,8 @@ +// Package aws provides core functionality for making requests to AWS services. +package aws + +// SDKName is the name of this AWS SDK +const SDKName = "aws-sdk-go" + +// SDKVersion is the version of this SDK +const SDKVersion = "1.12.46" diff --git a/vendor/github.com/aws/aws-sdk-go/buildspec.yml b/vendor/github.com/aws/aws-sdk-go/buildspec.yml new file mode 100644 index 0000000..427208e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/buildspec.yml @@ -0,0 +1,21 @@ +version: 0.2 + +phases: + build: + commands: + - echo Build started on `date` + - export GOPATH=/go + - export SDK_CB_ROOT=`pwd` + - export SDK_GO_ROOT=/go/src/github.com/aws/aws-sdk-go + - mkdir -p /go/src/github.com/aws + - ln -s $SDK_CB_ROOT $SDK_GO_ROOT + - cd $SDK_GO_ROOT + - make unit + - cd $SDK_CB_ROOT + - #echo Compiling the Go code... + post_build: + commands: + - echo Build completed on `date` +#artifacts: +# files: +# - hello diff --git a/vendor/github.com/aws/aws-sdk-go/doc.go b/vendor/github.com/aws/aws-sdk-go/doc.go new file mode 100644 index 0000000..3e077e5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/doc.go @@ -0,0 +1,405 @@ +// Package sdk is the official AWS SDK for the Go programming language. +// +// The AWS SDK for Go provides APIs and utilities that developers can use to +// build Go applications that use AWS services, such as Amazon Elastic Compute +// Cloud (Amazon EC2) and Amazon Simple Storage Service (Amazon S3). +// +// The SDK removes the complexity of coding directly against a web service +// interface. It hides a lot of the lower-level plumbing, such as authentication, +// request retries, and error handling. +// +// The SDK also includes helpful utilities on top of the AWS APIs that add additional +// capabilities and functionality. For example, the Amazon S3 Download and Upload +// Manager will automatically split up large objects into multiple parts and +// transfer them concurrently. +// +// See the s3manager package documentation for more information. +// https://docs.aws.amazon.com/sdk-for-go/api/service/s3/s3manager/ +// +// Getting More Information +// +// Checkout the Getting Started Guide and API Reference Docs detailed the SDK's +// components and details on each AWS client the SDK supports. +// +// The Getting Started Guide provides examples and detailed description of how +// to get setup with the SDK. +// https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/welcome.html +// +// The API Reference Docs include a detailed breakdown of the SDK's components +// such as utilities and AWS clients. Use this as a reference of the Go types +// included with the SDK, such as AWS clients, API operations, and API parameters. +// https://docs.aws.amazon.com/sdk-for-go/api/ +// +// 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 for more information. +// https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html +// +// See the session package documentation for more information on how to use Session +// with the SDK. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/session/ +// +// See the Config type in the aws package for more information on configuration +// options. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config +// +// 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. +// +// // 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 package documentation for more information on credential +// providers included with the SDK, and how to customize the SDK's usage of +// credentials. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/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. +// +// sess := session.Must(session.NewSessionWithOptions(session.Options{ +// SharedConfigState: session.SharedConfigEnable, +// })) +// +// 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. +// +// sess := session.Must(session.NewSession(&aws.Config{ +// Region: aws.String(endpoints.UsWest2RegionID), +// })) +// +// See the endpoints package for the AWS Regions and Endpoints metadata. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/endpoints/ +// +// 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. +// +// svc := s3.New(sess, &aws.Config{ +// Region: aws.String(ednpoints.UsWest2RegionID), +// }) +// +// See the Config type in the aws package for more information and additional +// options such as setting the Endpoint, and other service client configuration options. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config +// +// 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. +// +// 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. +// +// 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. +// +// 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. +// +// 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) +// } +package sdk diff --git a/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config.go b/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config.go new file mode 100644 index 0000000..ebcbc2b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config.go @@ -0,0 +1,40 @@ +package shareddefaults + +import ( + "os" + "path/filepath" + "runtime" +) + +// 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 filepath.Join(UserHomeDir(), ".aws", "credentials") +} + +// 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 filepath.Join(UserHomeDir(), ".aws", "config") +} + +// UserHomeDir returns the home directory for the user the process is +// running under. +func UserHomeDir() string { + if runtime.GOOS == "windows" { // Windows + return os.Getenv("USERPROFILE") + } + + // *nix + return os.Getenv("HOME") +} diff --git a/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_other_test.go b/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_other_test.go new file mode 100644 index 0000000..a2fd455 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_other_test.go @@ -0,0 +1,40 @@ +package shareddefaults_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/internal/shareddefaults" +) + +func TestSharedCredsFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("home_dir", ".aws", "credentials") + + name := shareddefaults.SharedCredentialsFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared creds filename, got %q", e, a) + } +} + +func TestSharedConfigFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("home_dir", ".aws", "config") + + name := shareddefaults.SharedConfigFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared config filename, got %q", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_windows_test.go b/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_windows_test.go new file mode 100644 index 0000000..afe96b1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config_windows_test.go @@ -0,0 +1,40 @@ +package shareddefaults_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/internal/shareddefaults" +) + +func TestSharedCredsFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("profile_dir", ".aws", "credentials") + + name := shareddefaults.SharedCredentialsFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared creds filename, got %q", e, a) + } +} + +func TestSharedConfigFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("profile_dir", ".aws", "config") + + name := shareddefaults.SharedConfigFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared config filename, got %q", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/README.md b/vendor/github.com/aws/aws-sdk-go/private/README.md new file mode 100644 index 0000000..5bdb4c5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/README.md @@ -0,0 +1,4 @@ +## AWS SDK for Go Private packages ## +`private` is a collection of packages used internally by the SDK, and is subject to have breaking changes. This package is not `internal` so that if you really need to use its functionality, and understand breaking changes will be made, you are able to. + +These packages will be refactored in the future so that the API generator and model parsers are exposed cleanly on their own. Making it easier for you to generate your own code based on the API models. diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go new file mode 100644 index 0000000..53831df --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go @@ -0,0 +1,75 @@ +package protocol + +import ( + "crypto/rand" + "fmt" + "reflect" +) + +// RandReader is the random reader the protocol package will use to read +// random bytes from. This is exported for testing, and should not be used. +var RandReader = rand.Reader + +const idempotencyTokenFillTag = `idempotencyToken` + +// CanSetIdempotencyToken returns true if the struct field should be +// automatically populated with a Idempotency token. +// +// Only *string and string type fields that are tagged with idempotencyToken +// which are not already set can be auto filled. +func CanSetIdempotencyToken(v reflect.Value, f reflect.StructField) bool { + switch u := v.Interface().(type) { + // To auto fill an Idempotency token the field must be a string, + // tagged for auto fill, and have a zero value. + case *string: + return u == nil && len(f.Tag.Get(idempotencyTokenFillTag)) != 0 + case string: + return len(u) == 0 && len(f.Tag.Get(idempotencyTokenFillTag)) != 0 + } + + return false +} + +// GetIdempotencyToken returns a randomly generated idempotency token. +func GetIdempotencyToken() string { + b := make([]byte, 16) + RandReader.Read(b) + + return UUIDVersion4(b) +} + +// SetIdempotencyToken will set the value provided with a Idempotency Token. +// Given that the value can be set. Will panic if value is not setable. +func SetIdempotencyToken(v reflect.Value) { + if v.Kind() == reflect.Ptr { + if v.IsNil() && v.CanSet() { + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + } + v = reflect.Indirect(v) + + if !v.CanSet() { + panic(fmt.Sprintf("unable to set idempotnecy token %v", v)) + } + + b := make([]byte, 16) + _, err := rand.Read(b) + if err != nil { + // TODO handle error + return + } + + v.Set(reflect.ValueOf(UUIDVersion4(b))) +} + +// UUIDVersion4 returns a Version 4 random UUID from the byte slice provided +func UUIDVersion4(u []byte) string { + // https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29 + // 13th character is "4" + u[6] = (u[6] | 0x40) & 0x4F + // 17th character is "8", "9", "a", or "b" + u[8] = (u[8] | 0x80) & 0xBF + + return fmt.Sprintf(`%X-%X-%X-%X-%X`, u[0:4], u[4:6], u[6:8], u[8:10], u[10:]) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency_test.go new file mode 100644 index 0000000..b6ea235 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency_test.go @@ -0,0 +1,106 @@ +package protocol_test + +import ( + "reflect" + "testing" + + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/stretchr/testify/assert" +) + +func TestCanSetIdempotencyToken(t *testing.T) { + cases := []struct { + CanSet bool + Case interface{} + }{ + { + true, + struct { + Field *string `idempotencyToken:"true"` + }{}, + }, + { + true, + struct { + Field string `idempotencyToken:"true"` + }{}, + }, + { + false, + struct { + Field *string `idempotencyToken:"true"` + }{Field: new(string)}, + }, + { + false, + struct { + Field string `idempotencyToken:"true"` + }{Field: "value"}, + }, + { + false, + struct { + Field *int `idempotencyToken:"true"` + }{}, + }, + { + false, + struct { + Field *string + }{}, + }, + } + + for i, c := range cases { + v := reflect.Indirect(reflect.ValueOf(c.Case)) + ty := v.Type() + canSet := protocol.CanSetIdempotencyToken(v.Field(0), ty.Field(0)) + assert.Equal(t, c.CanSet, canSet, "Expect case %d can set to match", i) + } +} + +func TestSetIdempotencyToken(t *testing.T) { + cases := []struct { + Case interface{} + }{ + { + &struct { + Field *string `idempotencyToken:"true"` + }{}, + }, + { + &struct { + Field string `idempotencyToken:"true"` + }{}, + }, + { + &struct { + Field *string `idempotencyToken:"true"` + }{Field: new(string)}, + }, + { + &struct { + Field string `idempotencyToken:"true"` + }{Field: ""}, + }, + } + + for i, c := range cases { + v := reflect.Indirect(reflect.ValueOf(c.Case)) + + protocol.SetIdempotencyToken(v.Field(0)) + assert.NotEmpty(t, v.Field(0).Interface(), "Expect case %d to be set", i) + } +} + +func TestUUIDVersion4(t *testing.T) { + uuid := protocol.UUIDVersion4(make([]byte, 16)) + assert.Equal(t, `00000000-0000-4000-8000-000000000000`, uuid) + + b := make([]byte, 16) + for i := 0; i < len(b); i++ { + b[i] = 1 + } + uuid = protocol.UUIDVersion4(b) + assert.Equal(t, `01010101-0101-4101-8101-010101010101`, uuid) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go new file mode 100644 index 0000000..ec765ba --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go @@ -0,0 +1,286 @@ +// Package jsonutil provides JSON serialization of AWS requests and responses. +package jsonutil + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/private/protocol" +) + +var timeType = reflect.ValueOf(time.Time{}).Type() +var byteSliceType = reflect.ValueOf([]byte{}).Type() + +// BuildJSON builds a JSON string for a given object v. +func BuildJSON(v interface{}) ([]byte, error) { + var buf bytes.Buffer + + err := buildAny(reflect.ValueOf(v), &buf, "") + return buf.Bytes(), err +} + +func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + origVal := value + value = reflect.Indirect(value) + if !value.IsValid() { + return nil + } + + vtype := value.Type() + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if value.Type() != timeType { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + // cannot be a JSONValue map + if _, ok := value.Interface().(aws.JSONValue); !ok { + t = "map" + } + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("_"); ok { + tag = field.Tag + } + return buildStruct(value, buf, tag) + case "list": + return buildList(value, buf, tag) + case "map": + return buildMap(value, buf, tag) + default: + return buildScalar(origVal, buf, tag) + } +} + +func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + if !value.IsValid() { + return nil + } + + // unwrap payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := value.Type().FieldByName(payload) + tag = field.Tag + value = elemOf(value.FieldByName(payload)) + + if !value.IsValid() { + return nil + } + } + + buf.WriteByte('{') + + t := value.Type() + first := true + for i := 0; i < t.NumField(); i++ { + member := value.Field(i) + + // This allocates the most memory. + // Additionally, we cannot skip nil fields due to + // idempotency auto filling. + field := t.Field(i) + + if field.PkgPath != "" { + continue // ignore unexported fields + } + if field.Tag.Get("json") == "-" { + continue + } + if field.Tag.Get("location") != "" { + continue // ignore non-body elements + } + if field.Tag.Get("ignore") != "" { + continue + } + + if protocol.CanSetIdempotencyToken(member, field) { + token := protocol.GetIdempotencyToken() + member = reflect.ValueOf(&token) + } + + if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice || member.Kind() == reflect.Map) && member.IsNil() { + continue // ignore unset fields + } + + if first { + first = false + } else { + buf.WriteByte(',') + } + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + writeString(name, buf) + buf.WriteString(`:`) + + err := buildAny(member, buf, field.Tag) + if err != nil { + return err + } + + } + + buf.WriteString("}") + + return nil +} + +func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("[") + + for i := 0; i < value.Len(); i++ { + buildAny(value.Index(i), buf, "") + + if i < value.Len()-1 { + buf.WriteString(",") + } + } + + buf.WriteString("]") + + return nil +} + +type sortedValues []reflect.Value + +func (sv sortedValues) Len() int { return len(sv) } +func (sv sortedValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } +func (sv sortedValues) Less(i, j int) bool { return sv[i].String() < sv[j].String() } + +func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + buf.WriteString("{") + + sv := sortedValues(value.MapKeys()) + sort.Sort(sv) + + for i, k := range sv { + if i > 0 { + buf.WriteByte(',') + } + + writeString(k.String(), buf) + buf.WriteString(`:`) + + buildAny(value.MapIndex(k), buf, "") + } + + buf.WriteString("}") + + return nil +} + +func buildScalar(v reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error { + // prevents allocation on the heap. + scratch := [64]byte{} + switch value := reflect.Indirect(v); value.Kind() { + case reflect.String: + writeString(value.String(), buf) + case reflect.Bool: + if value.Bool() { + buf.WriteString("true") + } else { + buf.WriteString("false") + } + case reflect.Int64: + buf.Write(strconv.AppendInt(scratch[:0], value.Int(), 10)) + case reflect.Float64: + f := value.Float() + if math.IsInf(f, 0) || math.IsNaN(f) { + return &json.UnsupportedValueError{Value: v, Str: strconv.FormatFloat(f, 'f', -1, 64)} + } + buf.Write(strconv.AppendFloat(scratch[:0], f, 'f', -1, 64)) + default: + switch converted := value.Interface().(type) { + case time.Time: + buf.Write(strconv.AppendInt(scratch[:0], converted.UTC().Unix(), 10)) + case []byte: + if !value.IsNil() { + buf.WriteByte('"') + if len(converted) < 1024 { + // for small buffers, using Encode directly is much faster. + dst := make([]byte, base64.StdEncoding.EncodedLen(len(converted))) + base64.StdEncoding.Encode(dst, converted) + buf.Write(dst) + } else { + // for large buffers, avoid unnecessary extra temporary + // buffer space. + enc := base64.NewEncoder(base64.StdEncoding, buf) + enc.Write(converted) + enc.Close() + } + buf.WriteByte('"') + } + case aws.JSONValue: + str, err := protocol.EncodeJSONValue(converted, protocol.QuotedEscape) + if err != nil { + return fmt.Errorf("unable to encode JSONValue, %v", err) + } + buf.WriteString(str) + default: + return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type()) + } + } + return nil +} + +var hex = "0123456789abcdef" + +func writeString(s string, buf *bytes.Buffer) { + buf.WriteByte('"') + for i := 0; i < len(s); i++ { + if s[i] == '"' { + buf.WriteString(`\"`) + } else if s[i] == '\\' { + buf.WriteString(`\\`) + } else if s[i] == '\b' { + buf.WriteString(`\b`) + } else if s[i] == '\f' { + buf.WriteString(`\f`) + } else if s[i] == '\r' { + buf.WriteString(`\r`) + } else if s[i] == '\t' { + buf.WriteString(`\t`) + } else if s[i] == '\n' { + buf.WriteString(`\n`) + } else if s[i] < 32 { + buf.WriteString("\\u00") + buf.WriteByte(hex[s[i]>>4]) + buf.WriteByte(hex[s[i]&0xF]) + } else { + buf.WriteByte(s[i]) + } + } + buf.WriteByte('"') +} + +// Returns the reflection element of a value, if it is a pointer. +func elemOf(value reflect.Value) reflect.Value { + for value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build_test.go new file mode 100644 index 0000000..e86f424 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build_test.go @@ -0,0 +1,109 @@ +package jsonutil_test + +import ( + "encoding/json" + "testing" + "time" + + "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil" + "github.com/stretchr/testify/assert" +) + +func S(s string) *string { + return &s +} + +func D(s int64) *int64 { + return &s +} + +func F(s float64) *float64 { + return &s +} + +func T(s time.Time) *time.Time { + return &s +} + +type J struct { + S *string + SS []string + D *int64 + F *float64 + T *time.Time +} + +var zero = 0.0 + +var jsonTests = []struct { + in interface{} + out string + err string +}{ + { + J{}, + `{}`, + ``, + }, + { + J{ + S: S("str"), + SS: []string{"A", "B", "C"}, + D: D(123), + F: F(4.56), + T: T(time.Unix(987, 0)), + }, + `{"S":"str","SS":["A","B","C"],"D":123,"F":4.56,"T":987}`, + ``, + }, + { + J{ + S: S(`"''"`), + }, + `{"S":"\"''\""}`, + ``, + }, + { + J{ + S: S("\x00føø\u00FF\n\\\"\r\t\b\f"), + }, + `{"S":"\u0000føøÿ\n\\\"\r\t\b\f"}`, + ``, + }, + { + J{ + F: F(4.56 / zero), + }, + "", + `json: unsupported value: +Inf`, + }, +} + +func TestBuildJSON(t *testing.T) { + for _, test := range jsonTests { + out, err := jsonutil.BuildJSON(test.in) + if test.err != "" { + assert.Error(t, err) + assert.Contains(t, err.Error(), test.err) + } else { + assert.NoError(t, err) + assert.Equal(t, string(out), test.out) + } + } +} + +func BenchmarkBuildJSON(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range jsonTests { + jsonutil.BuildJSON(test.in) + } + } +} + +func BenchmarkStdlibJSON(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range jsonTests { + json.Marshal(test.in) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go new file mode 100644 index 0000000..037e1e7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go @@ -0,0 +1,226 @@ +package jsonutil + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "reflect" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/private/protocol" +) + +// UnmarshalJSON reads a stream and unmarshals the results in object v. +func UnmarshalJSON(v interface{}, stream io.Reader) error { + var out interface{} + + b, err := ioutil.ReadAll(stream) + if err != nil { + return err + } + + if len(b) == 0 { + return nil + } + + if err := json.Unmarshal(b, &out); err != nil { + return err + } + + return unmarshalAny(reflect.ValueOf(v), out, "") +} + +func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error { + vtype := value.Type() + if vtype.Kind() == reflect.Ptr { + vtype = vtype.Elem() // check kind of actual element type + } + + t := tag.Get("type") + if t == "" { + switch vtype.Kind() { + case reflect.Struct: + // also it can't be a time object + if _, ok := value.Interface().(*time.Time); !ok { + t = "structure" + } + case reflect.Slice: + // also it can't be a byte slice + if _, ok := value.Interface().([]byte); !ok { + t = "list" + } + case reflect.Map: + // cannot be a JSONValue map + if _, ok := value.Interface().(aws.JSONValue); !ok { + t = "map" + } + } + } + + switch t { + case "structure": + if field, ok := vtype.FieldByName("_"); ok { + tag = field.Tag + } + return unmarshalStruct(value, data, tag) + case "list": + return unmarshalList(value, data, tag) + case "map": + return unmarshalMap(value, data, tag) + default: + return unmarshalScalar(value, data, tag) + } +} + +func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a structure (%#v)", data) + } + + t := value.Type() + if value.Kind() == reflect.Ptr { + if value.IsNil() { // create the structure if it's nil + s := reflect.New(value.Type().Elem()) + value.Set(s) + value = s + } + + value = value.Elem() + t = t.Elem() + } + + // unwrap any payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := t.FieldByName(payload) + return unmarshalAny(value.FieldByName(payload), data, field.Tag) + } + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if field.PkgPath != "" { + continue // ignore unexported fields + } + + // figure out what this field is called + name := field.Name + if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + member := value.FieldByIndex(field.Index) + err := unmarshalAny(member, mapData[name], field.Tag) + if err != nil { + return err + } + } + return nil +} + +func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + listData, ok := data.([]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a list (%#v)", data) + } + + if value.IsNil() { + l := len(listData) + value.Set(reflect.MakeSlice(value.Type(), l, l)) + } + + for i, c := range listData { + err := unmarshalAny(value.Index(i), c, "") + if err != nil { + return err + } + } + + return nil +} + +func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error { + if data == nil { + return nil + } + mapData, ok := data.(map[string]interface{}) + if !ok { + return fmt.Errorf("JSON value is not a map (%#v)", data) + } + + if value.IsNil() { + value.Set(reflect.MakeMap(value.Type())) + } + + for k, v := range mapData { + kvalue := reflect.ValueOf(k) + vvalue := reflect.New(value.Type().Elem()).Elem() + + unmarshalAny(vvalue, v, "") + value.SetMapIndex(kvalue, vvalue) + } + + return nil +} + +func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error { + errf := func() error { + return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type()) + } + + switch d := data.(type) { + case nil: + return nil // nothing to do here + case string: + switch value.Interface().(type) { + case *string: + value.Set(reflect.ValueOf(&d)) + case []byte: + b, err := base64.StdEncoding.DecodeString(d) + if err != nil { + return err + } + value.Set(reflect.ValueOf(b)) + case aws.JSONValue: + // No need to use escaping as the value is a non-quoted string. + v, err := protocol.DecodeJSONValue(d, protocol.NoEscape) + if err != nil { + return err + } + value.Set(reflect.ValueOf(v)) + default: + return errf() + } + case float64: + switch value.Interface().(type) { + case *int64: + di := int64(d) + value.Set(reflect.ValueOf(&di)) + case *float64: + value.Set(reflect.ValueOf(&d)) + case *time.Time: + t := time.Unix(int64(d), 0).UTC() + value.Set(reflect.ValueOf(&t)) + default: + return errf() + } + case bool: + switch value.Interface().(type) { + case *bool: + value.Set(reflect.ValueOf(&d)) + default: + return errf() + } + default: + return fmt.Errorf("unsupported JSON value (%v)", data) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_bench_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_bench_test.go new file mode 100644 index 0000000..563caa0 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_bench_test.go @@ -0,0 +1,71 @@ +// +build bench + +package jsonrpc_test + +import ( + "bytes" + "encoding/json" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" + "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" +) + +func BenchmarkJSONRPCBuild_Simple_dynamodbPutItem(b *testing.B) { + svc := awstesting.NewClient() + + params := getDynamodbPutItemParams(b) + + for i := 0; i < b.N; i++ { + r := svc.NewRequest(&request.Operation{Name: "Operation"}, params, nil) + jsonrpc.Build(r) + if r.Error != nil { + b.Fatal("Unexpected error", r.Error) + } + } +} + +func BenchmarkJSONUtilBuild_Simple_dynamodbPutItem(b *testing.B) { + svc := awstesting.NewClient() + + params := getDynamodbPutItemParams(b) + + for i := 0; i < b.N; i++ { + r := svc.NewRequest(&request.Operation{Name: "Operation"}, params, nil) + _, err := jsonutil.BuildJSON(r.Params) + if err != nil { + b.Fatal("Unexpected error", err) + } + } +} + +func BenchmarkEncodingJSONMarshal_Simple_dynamodbPutItem(b *testing.B) { + params := getDynamodbPutItemParams(b) + + for i := 0; i < b.N; i++ { + buf := &bytes.Buffer{} + encoder := json.NewEncoder(buf) + if err := encoder.Encode(params); err != nil { + b.Fatal("Unexpected error", err) + } + } +} + +func getDynamodbPutItemParams(b *testing.B) *dynamodb.PutItemInput { + av, err := dynamodbattribute.ConvertToMap(struct { + Key string + Data string + }{Key: "MyKey", Data: "MyData"}) + if err != nil { + b.Fatal("benchPutItem, expect no ConvertToMap errors", err) + } + return &dynamodb.PutItemInput{ + Item: av, + TableName: aws.String("tablename"), + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_test.go new file mode 100644 index 0000000..5982fac --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/build_test.go @@ -0,0 +1,2444 @@ +package jsonrpc_test + +import ( + "bytes" + "encoding/json" + "encoding/xml" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" + "github.com/aws/aws-sdk-go/private/util" +) + +var _ bytes.Buffer // always import bytes +var _ http.Request +var _ json.Marshaler +var _ time.Time +var _ xmlutil.XMLNode +var _ xml.Attr +var _ = ioutil.Discard +var _ = util.Trim("") +var _ = url.Values{} +var _ = io.EOF +var _ = aws.String +var _ = fmt.Println +var _ = reflect.Value{} + +func init() { + protocol.RandReader = &awstesting.ZeroReader{} +} + +// InputService1ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService1ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService1ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService1ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService1ProtocolTest client from just a session. +// svc := inputservice1protocoltest.New(mySession) +// +// // Create a InputService1ProtocolTest client with additional configuration +// svc := inputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService1ProtocolTest { + c := p.ClientConfig("inputservice1protocoltest", cfgs...) + return newInputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService1ProtocolTest { + svc := &InputService1ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice1protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService1ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService1TestCaseOperation1 = "OperationName" + +// InputService1TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService1TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService1TestCaseOperation1 for more information on using the InputService1TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService1TestCaseOperation1Request method. +// req, resp := client.InputService1TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1Request(input *InputService1TestShapeInputService1TestCaseOperation1Input) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService1TestCaseOperation1, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService1TestShapeInputService1TestCaseOperation1Input{} + } + + output = &InputService1TestShapeInputService1TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService1TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService1TestCaseOperation1 for usage and error information. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1(input *InputService1TestShapeInputService1TestCaseOperation1Input) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { + req, out := c.InputService1TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService1TestCaseOperation1WithContext is the same as InputService1TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService1TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1WithContext(ctx aws.Context, input *InputService1TestShapeInputService1TestCaseOperation1Input, opts ...request.Option) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { + req, out := c.InputService1TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService1TestShapeInputService1TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + Name *string `type:"string"` +} + +// SetName sets the Name field's value. +func (s *InputService1TestShapeInputService1TestCaseOperation1Input) SetName(v string) *InputService1TestShapeInputService1TestCaseOperation1Input { + s.Name = &v + return s +} + +type InputService1TestShapeInputService1TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService2ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService2ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService2ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService2ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService2ProtocolTest client from just a session. +// svc := inputservice2protocoltest.New(mySession) +// +// // Create a InputService2ProtocolTest client with additional configuration +// svc := inputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService2ProtocolTest { + c := p.ClientConfig("inputservice2protocoltest", cfgs...) + return newInputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService2ProtocolTest { + svc := &InputService2ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice2protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService2ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService2TestCaseOperation1 = "OperationName" + +// InputService2TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService2TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService2TestCaseOperation1 for more information on using the InputService2TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService2TestCaseOperation1Request method. +// req, resp := client.InputService2TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1Request(input *InputService2TestShapeInputService2TestCaseOperation1Input) (req *request.Request, output *InputService2TestShapeInputService2TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService2TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService2TestShapeInputService2TestCaseOperation1Input{} + } + + output = &InputService2TestShapeInputService2TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService2TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService2TestCaseOperation1 for usage and error information. +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1(input *InputService2TestShapeInputService2TestCaseOperation1Input) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { + req, out := c.InputService2TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService2TestCaseOperation1WithContext is the same as InputService2TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService2TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1WithContext(ctx aws.Context, input *InputService2TestShapeInputService2TestCaseOperation1Input, opts ...request.Option) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { + req, out := c.InputService2TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService2TestShapeInputService2TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + TimeArg *time.Time `type:"timestamp" timestampFormat:"unix"` +} + +// SetTimeArg sets the TimeArg field's value. +func (s *InputService2TestShapeInputService2TestCaseOperation1Input) SetTimeArg(v time.Time) *InputService2TestShapeInputService2TestCaseOperation1Input { + s.TimeArg = &v + return s +} + +type InputService2TestShapeInputService2TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService3ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService3ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService3ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService3ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService3ProtocolTest client from just a session. +// svc := inputservice3protocoltest.New(mySession) +// +// // Create a InputService3ProtocolTest client with additional configuration +// svc := inputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService3ProtocolTest { + c := p.ClientConfig("inputservice3protocoltest", cfgs...) + return newInputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService3ProtocolTest { + svc := &InputService3ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice3protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService3ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService3TestCaseOperation1 = "OperationName" + +// InputService3TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService3TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService3TestCaseOperation1 for more information on using the InputService3TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService3TestCaseOperation1Request method. +// req, resp := client.InputService3TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1Request(input *InputService3TestShapeInputService3TestCaseOperation2Input) (req *request.Request, output *InputService3TestShapeInputService3TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService3TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService3TestShapeInputService3TestCaseOperation2Input{} + } + + output = &InputService3TestShapeInputService3TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService3TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService3TestCaseOperation1 for usage and error information. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1(input *InputService3TestShapeInputService3TestCaseOperation2Input) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { + req, out := c.InputService3TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService3TestCaseOperation1WithContext is the same as InputService3TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService3TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1WithContext(ctx aws.Context, input *InputService3TestShapeInputService3TestCaseOperation2Input, opts ...request.Option) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { + req, out := c.InputService3TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService3TestCaseOperation2 = "OperationName" + +// InputService3TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService3TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService3TestCaseOperation2 for more information on using the InputService3TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService3TestCaseOperation2Request method. +// req, resp := client.InputService3TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2Request(input *InputService3TestShapeInputService3TestCaseOperation2Input) (req *request.Request, output *InputService3TestShapeInputService3TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService3TestCaseOperation2, + HTTPPath: "/", + } + + if input == nil { + input = &InputService3TestShapeInputService3TestCaseOperation2Input{} + } + + output = &InputService3TestShapeInputService3TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService3TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService3TestCaseOperation2 for usage and error information. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2(input *InputService3TestShapeInputService3TestCaseOperation2Input) (*InputService3TestShapeInputService3TestCaseOperation2Output, error) { + req, out := c.InputService3TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService3TestCaseOperation2WithContext is the same as InputService3TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService3TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2WithContext(ctx aws.Context, input *InputService3TestShapeInputService3TestCaseOperation2Input, opts ...request.Option) (*InputService3TestShapeInputService3TestCaseOperation2Output, error) { + req, out := c.InputService3TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService3TestShapeInputService3TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService3TestShapeInputService3TestCaseOperation2Input struct { + _ struct{} `type:"structure"` + + // BlobArg is automatically base64 encoded/decoded by the SDK. + BlobArg []byte `type:"blob"` + + BlobMap map[string][]byte `type:"map"` +} + +// SetBlobArg sets the BlobArg field's value. +func (s *InputService3TestShapeInputService3TestCaseOperation2Input) SetBlobArg(v []byte) *InputService3TestShapeInputService3TestCaseOperation2Input { + s.BlobArg = v + return s +} + +// SetBlobMap sets the BlobMap field's value. +func (s *InputService3TestShapeInputService3TestCaseOperation2Input) SetBlobMap(v map[string][]byte) *InputService3TestShapeInputService3TestCaseOperation2Input { + s.BlobMap = v + return s +} + +type InputService3TestShapeInputService3TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +// InputService4ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService4ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService4ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService4ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService4ProtocolTest client from just a session. +// svc := inputservice4protocoltest.New(mySession) +// +// // Create a InputService4ProtocolTest client with additional configuration +// svc := inputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService4ProtocolTest { + c := p.ClientConfig("inputservice4protocoltest", cfgs...) + return newInputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService4ProtocolTest { + svc := &InputService4ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice4protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService4ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService4TestCaseOperation1 = "OperationName" + +// InputService4TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService4TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService4TestCaseOperation1 for more information on using the InputService4TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService4TestCaseOperation1Request method. +// req, resp := client.InputService4TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1Request(input *InputService4TestShapeInputService4TestCaseOperation1Input) (req *request.Request, output *InputService4TestShapeInputService4TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService4TestCaseOperation1, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService4TestShapeInputService4TestCaseOperation1Input{} + } + + output = &InputService4TestShapeInputService4TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService4TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService4TestCaseOperation1 for usage and error information. +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1(input *InputService4TestShapeInputService4TestCaseOperation1Input) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { + req, out := c.InputService4TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService4TestCaseOperation1WithContext is the same as InputService4TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService4TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1WithContext(ctx aws.Context, input *InputService4TestShapeInputService4TestCaseOperation1Input, opts ...request.Option) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { + req, out := c.InputService4TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService4TestShapeInputService4TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + ListParam [][]byte `type:"list"` +} + +// SetListParam sets the ListParam field's value. +func (s *InputService4TestShapeInputService4TestCaseOperation1Input) SetListParam(v [][]byte) *InputService4TestShapeInputService4TestCaseOperation1Input { + s.ListParam = v + return s +} + +type InputService4TestShapeInputService4TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService5ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService5ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService5ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService5ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService5ProtocolTest client from just a session. +// svc := inputservice5protocoltest.New(mySession) +// +// // Create a InputService5ProtocolTest client with additional configuration +// svc := inputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService5ProtocolTest { + c := p.ClientConfig("inputservice5protocoltest", cfgs...) + return newInputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService5ProtocolTest { + svc := &InputService5ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice5protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService5ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService5TestCaseOperation1 = "OperationName" + +// InputService5TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService5TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService5TestCaseOperation1 for more information on using the InputService5TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService5TestCaseOperation1Request method. +// req, resp := client.InputService5TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1Request(input *InputService5TestShapeInputService5TestCaseOperation6Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService5TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService5TestShapeInputService5TestCaseOperation6Input{} + } + + output = &InputService5TestShapeInputService5TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService5TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService5TestCaseOperation1 for usage and error information. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1(input *InputService5TestShapeInputService5TestCaseOperation6Input) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { + req, out := c.InputService5TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService5TestCaseOperation1WithContext is the same as InputService5TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService5TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1WithContext(ctx aws.Context, input *InputService5TestShapeInputService5TestCaseOperation6Input, opts ...request.Option) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { + req, out := c.InputService5TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService5TestCaseOperation2 = "OperationName" + +// InputService5TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService5TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService5TestCaseOperation2 for more information on using the InputService5TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService5TestCaseOperation2Request method. +// req, resp := client.InputService5TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService5ProtocolTest) InputService5TestCaseOperation2Request(input *InputService5TestShapeInputService5TestCaseOperation6Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService5TestCaseOperation2, + HTTPPath: "/", + } + + if input == nil { + input = &InputService5TestShapeInputService5TestCaseOperation6Input{} + } + + output = &InputService5TestShapeInputService5TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService5TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService5TestCaseOperation2 for usage and error information. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation2(input *InputService5TestShapeInputService5TestCaseOperation6Input) (*InputService5TestShapeInputService5TestCaseOperation2Output, error) { + req, out := c.InputService5TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService5TestCaseOperation2WithContext is the same as InputService5TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService5TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation2WithContext(ctx aws.Context, input *InputService5TestShapeInputService5TestCaseOperation6Input, opts ...request.Option) (*InputService5TestShapeInputService5TestCaseOperation2Output, error) { + req, out := c.InputService5TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService5TestCaseOperation3 = "OperationName" + +// InputService5TestCaseOperation3Request generates a "aws/request.Request" representing the +// client's request for the InputService5TestCaseOperation3 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService5TestCaseOperation3 for more information on using the InputService5TestCaseOperation3 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService5TestCaseOperation3Request method. +// req, resp := client.InputService5TestCaseOperation3Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService5ProtocolTest) InputService5TestCaseOperation3Request(input *InputService5TestShapeInputService5TestCaseOperation6Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation3Output) { + op := &request.Operation{ + Name: opInputService5TestCaseOperation3, + HTTPPath: "/", + } + + if input == nil { + input = &InputService5TestShapeInputService5TestCaseOperation6Input{} + } + + output = &InputService5TestShapeInputService5TestCaseOperation3Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService5TestCaseOperation3 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService5TestCaseOperation3 for usage and error information. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation3(input *InputService5TestShapeInputService5TestCaseOperation6Input) (*InputService5TestShapeInputService5TestCaseOperation3Output, error) { + req, out := c.InputService5TestCaseOperation3Request(input) + return out, req.Send() +} + +// InputService5TestCaseOperation3WithContext is the same as InputService5TestCaseOperation3 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService5TestCaseOperation3 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation3WithContext(ctx aws.Context, input *InputService5TestShapeInputService5TestCaseOperation6Input, opts ...request.Option) (*InputService5TestShapeInputService5TestCaseOperation3Output, error) { + req, out := c.InputService5TestCaseOperation3Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService5TestCaseOperation4 = "OperationName" + +// InputService5TestCaseOperation4Request generates a "aws/request.Request" representing the +// client's request for the InputService5TestCaseOperation4 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService5TestCaseOperation4 for more information on using the InputService5TestCaseOperation4 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService5TestCaseOperation4Request method. +// req, resp := client.InputService5TestCaseOperation4Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService5ProtocolTest) InputService5TestCaseOperation4Request(input *InputService5TestShapeInputService5TestCaseOperation6Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation4Output) { + op := &request.Operation{ + Name: opInputService5TestCaseOperation4, + HTTPPath: "/", + } + + if input == nil { + input = &InputService5TestShapeInputService5TestCaseOperation6Input{} + } + + output = &InputService5TestShapeInputService5TestCaseOperation4Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService5TestCaseOperation4 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService5TestCaseOperation4 for usage and error information. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation4(input *InputService5TestShapeInputService5TestCaseOperation6Input) (*InputService5TestShapeInputService5TestCaseOperation4Output, error) { + req, out := c.InputService5TestCaseOperation4Request(input) + return out, req.Send() +} + +// InputService5TestCaseOperation4WithContext is the same as InputService5TestCaseOperation4 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService5TestCaseOperation4 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation4WithContext(ctx aws.Context, input *InputService5TestShapeInputService5TestCaseOperation6Input, opts ...request.Option) (*InputService5TestShapeInputService5TestCaseOperation4Output, error) { + req, out := c.InputService5TestCaseOperation4Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService5TestCaseOperation5 = "OperationName" + +// InputService5TestCaseOperation5Request generates a "aws/request.Request" representing the +// client's request for the InputService5TestCaseOperation5 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService5TestCaseOperation5 for more information on using the InputService5TestCaseOperation5 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService5TestCaseOperation5Request method. +// req, resp := client.InputService5TestCaseOperation5Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService5ProtocolTest) InputService5TestCaseOperation5Request(input *InputService5TestShapeInputService5TestCaseOperation6Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation5Output) { + op := &request.Operation{ + Name: opInputService5TestCaseOperation5, + HTTPPath: "/", + } + + if input == nil { + input = &InputService5TestShapeInputService5TestCaseOperation6Input{} + } + + output = &InputService5TestShapeInputService5TestCaseOperation5Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService5TestCaseOperation5 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService5TestCaseOperation5 for usage and error information. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation5(input *InputService5TestShapeInputService5TestCaseOperation6Input) (*InputService5TestShapeInputService5TestCaseOperation5Output, error) { + req, out := c.InputService5TestCaseOperation5Request(input) + return out, req.Send() +} + +// InputService5TestCaseOperation5WithContext is the same as InputService5TestCaseOperation5 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService5TestCaseOperation5 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation5WithContext(ctx aws.Context, input *InputService5TestShapeInputService5TestCaseOperation6Input, opts ...request.Option) (*InputService5TestShapeInputService5TestCaseOperation5Output, error) { + req, out := c.InputService5TestCaseOperation5Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService5TestCaseOperation6 = "OperationName" + +// InputService5TestCaseOperation6Request generates a "aws/request.Request" representing the +// client's request for the InputService5TestCaseOperation6 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService5TestCaseOperation6 for more information on using the InputService5TestCaseOperation6 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService5TestCaseOperation6Request method. +// req, resp := client.InputService5TestCaseOperation6Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService5ProtocolTest) InputService5TestCaseOperation6Request(input *InputService5TestShapeInputService5TestCaseOperation6Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation6Output) { + op := &request.Operation{ + Name: opInputService5TestCaseOperation6, + HTTPPath: "/", + } + + if input == nil { + input = &InputService5TestShapeInputService5TestCaseOperation6Input{} + } + + output = &InputService5TestShapeInputService5TestCaseOperation6Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService5TestCaseOperation6 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService5TestCaseOperation6 for usage and error information. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation6(input *InputService5TestShapeInputService5TestCaseOperation6Input) (*InputService5TestShapeInputService5TestCaseOperation6Output, error) { + req, out := c.InputService5TestCaseOperation6Request(input) + return out, req.Send() +} + +// InputService5TestCaseOperation6WithContext is the same as InputService5TestCaseOperation6 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService5TestCaseOperation6 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation6WithContext(ctx aws.Context, input *InputService5TestShapeInputService5TestCaseOperation6Input, opts ...request.Option) (*InputService5TestShapeInputService5TestCaseOperation6Output, error) { + req, out := c.InputService5TestCaseOperation6Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService5TestShapeInputService5TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService5TestShapeInputService5TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +type InputService5TestShapeInputService5TestCaseOperation3Output struct { + _ struct{} `type:"structure"` +} + +type InputService5TestShapeInputService5TestCaseOperation4Output struct { + _ struct{} `type:"structure"` +} + +type InputService5TestShapeInputService5TestCaseOperation5Output struct { + _ struct{} `type:"structure"` +} + +type InputService5TestShapeInputService5TestCaseOperation6Input struct { + _ struct{} `type:"structure"` + + RecursiveStruct *InputService5TestShapeRecursiveStructType `type:"structure"` +} + +// SetRecursiveStruct sets the RecursiveStruct field's value. +func (s *InputService5TestShapeInputService5TestCaseOperation6Input) SetRecursiveStruct(v *InputService5TestShapeRecursiveStructType) *InputService5TestShapeInputService5TestCaseOperation6Input { + s.RecursiveStruct = v + return s +} + +type InputService5TestShapeInputService5TestCaseOperation6Output struct { + _ struct{} `type:"structure"` +} + +type InputService5TestShapeRecursiveStructType struct { + _ struct{} `type:"structure"` + + NoRecurse *string `type:"string"` + + RecursiveList []*InputService5TestShapeRecursiveStructType `type:"list"` + + RecursiveMap map[string]*InputService5TestShapeRecursiveStructType `type:"map"` + + RecursiveStruct *InputService5TestShapeRecursiveStructType `type:"structure"` +} + +// SetNoRecurse sets the NoRecurse field's value. +func (s *InputService5TestShapeRecursiveStructType) SetNoRecurse(v string) *InputService5TestShapeRecursiveStructType { + s.NoRecurse = &v + return s +} + +// SetRecursiveList sets the RecursiveList field's value. +func (s *InputService5TestShapeRecursiveStructType) SetRecursiveList(v []*InputService5TestShapeRecursiveStructType) *InputService5TestShapeRecursiveStructType { + s.RecursiveList = v + return s +} + +// SetRecursiveMap sets the RecursiveMap field's value. +func (s *InputService5TestShapeRecursiveStructType) SetRecursiveMap(v map[string]*InputService5TestShapeRecursiveStructType) *InputService5TestShapeRecursiveStructType { + s.RecursiveMap = v + return s +} + +// SetRecursiveStruct sets the RecursiveStruct field's value. +func (s *InputService5TestShapeRecursiveStructType) SetRecursiveStruct(v *InputService5TestShapeRecursiveStructType) *InputService5TestShapeRecursiveStructType { + s.RecursiveStruct = v + return s +} + +// InputService6ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService6ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService6ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService6ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService6ProtocolTest client from just a session. +// svc := inputservice6protocoltest.New(mySession) +// +// // Create a InputService6ProtocolTest client with additional configuration +// svc := inputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService6ProtocolTest { + c := p.ClientConfig("inputservice6protocoltest", cfgs...) + return newInputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService6ProtocolTest { + svc := &InputService6ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice6protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + JSONVersion: "1.1", + TargetPrefix: "com.amazonaws.foo", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService6ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService6TestCaseOperation1 = "OperationName" + +// InputService6TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService6TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService6TestCaseOperation1 for more information on using the InputService6TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService6TestCaseOperation1Request method. +// req, resp := client.InputService6TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService6ProtocolTest) InputService6TestCaseOperation1Request(input *InputService6TestShapeInputService6TestCaseOperation1Input) (req *request.Request, output *InputService6TestShapeInputService6TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService6TestCaseOperation1, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService6TestShapeInputService6TestCaseOperation1Input{} + } + + output = &InputService6TestShapeInputService6TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService6TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService6TestCaseOperation1 for usage and error information. +func (c *InputService6ProtocolTest) InputService6TestCaseOperation1(input *InputService6TestShapeInputService6TestCaseOperation1Input) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { + req, out := c.InputService6TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService6TestCaseOperation1WithContext is the same as InputService6TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService6TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService6ProtocolTest) InputService6TestCaseOperation1WithContext(ctx aws.Context, input *InputService6TestShapeInputService6TestCaseOperation1Input, opts ...request.Option) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { + req, out := c.InputService6TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService6TestShapeInputService6TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + Map map[string]*string `type:"map"` +} + +// SetMap sets the Map field's value. +func (s *InputService6TestShapeInputService6TestCaseOperation1Input) SetMap(v map[string]*string) *InputService6TestShapeInputService6TestCaseOperation1Input { + s.Map = v + return s +} + +type InputService6TestShapeInputService6TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService7ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService7ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService7ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService7ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService7ProtocolTest client from just a session. +// svc := inputservice7protocoltest.New(mySession) +// +// // Create a InputService7ProtocolTest client with additional configuration +// svc := inputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService7ProtocolTest { + c := p.ClientConfig("inputservice7protocoltest", cfgs...) + return newInputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService7ProtocolTest { + svc := &InputService7ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice7protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService7ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService7TestCaseOperation1 = "OperationName" + +// InputService7TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService7TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService7TestCaseOperation1 for more information on using the InputService7TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService7TestCaseOperation1Request method. +// req, resp := client.InputService7TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService7ProtocolTest) InputService7TestCaseOperation1Request(input *InputService7TestShapeInputService7TestCaseOperation2Input) (req *request.Request, output *InputService7TestShapeInputService7TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService7TestCaseOperation1, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService7TestShapeInputService7TestCaseOperation2Input{} + } + + output = &InputService7TestShapeInputService7TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService7TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService7TestCaseOperation1 for usage and error information. +func (c *InputService7ProtocolTest) InputService7TestCaseOperation1(input *InputService7TestShapeInputService7TestCaseOperation2Input) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { + req, out := c.InputService7TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService7TestCaseOperation1WithContext is the same as InputService7TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService7TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService7ProtocolTest) InputService7TestCaseOperation1WithContext(ctx aws.Context, input *InputService7TestShapeInputService7TestCaseOperation2Input, opts ...request.Option) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { + req, out := c.InputService7TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService7TestCaseOperation2 = "OperationName" + +// InputService7TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService7TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService7TestCaseOperation2 for more information on using the InputService7TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService7TestCaseOperation2Request method. +// req, resp := client.InputService7TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService7ProtocolTest) InputService7TestCaseOperation2Request(input *InputService7TestShapeInputService7TestCaseOperation2Input) (req *request.Request, output *InputService7TestShapeInputService7TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService7TestCaseOperation2, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService7TestShapeInputService7TestCaseOperation2Input{} + } + + output = &InputService7TestShapeInputService7TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService7TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService7TestCaseOperation2 for usage and error information. +func (c *InputService7ProtocolTest) InputService7TestCaseOperation2(input *InputService7TestShapeInputService7TestCaseOperation2Input) (*InputService7TestShapeInputService7TestCaseOperation2Output, error) { + req, out := c.InputService7TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService7TestCaseOperation2WithContext is the same as InputService7TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService7TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService7ProtocolTest) InputService7TestCaseOperation2WithContext(ctx aws.Context, input *InputService7TestShapeInputService7TestCaseOperation2Input, opts ...request.Option) (*InputService7TestShapeInputService7TestCaseOperation2Output, error) { + req, out := c.InputService7TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService7TestShapeInputService7TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService7TestShapeInputService7TestCaseOperation2Input struct { + _ struct{} `type:"structure"` + + Token *string `type:"string" idempotencyToken:"true"` +} + +// SetToken sets the Token field's value. +func (s *InputService7TestShapeInputService7TestCaseOperation2Input) SetToken(v string) *InputService7TestShapeInputService7TestCaseOperation2Input { + s.Token = &v + return s +} + +type InputService7TestShapeInputService7TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +// InputService8ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService8ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService8ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService8ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService8ProtocolTest client from just a session. +// svc := inputservice8protocoltest.New(mySession) +// +// // Create a InputService8ProtocolTest client with additional configuration +// svc := inputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService8ProtocolTest { + c := p.ClientConfig("inputservice8protocoltest", cfgs...) + return newInputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService8ProtocolTest { + svc := &InputService8ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice8protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService8ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService8ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService8TestCaseOperation1 = "OperationName" + +// InputService8TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService8TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService8TestCaseOperation1 for more information on using the InputService8TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService8TestCaseOperation1Request method. +// req, resp := client.InputService8TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService8ProtocolTest) InputService8TestCaseOperation1Request(input *InputService8TestShapeInputService8TestCaseOperation2Input) (req *request.Request, output *InputService8TestShapeInputService8TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService8TestCaseOperation1, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService8TestShapeInputService8TestCaseOperation2Input{} + } + + output = &InputService8TestShapeInputService8TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService8TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService8TestCaseOperation1 for usage and error information. +func (c *InputService8ProtocolTest) InputService8TestCaseOperation1(input *InputService8TestShapeInputService8TestCaseOperation2Input) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { + req, out := c.InputService8TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService8TestCaseOperation1WithContext is the same as InputService8TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService8TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService8ProtocolTest) InputService8TestCaseOperation1WithContext(ctx aws.Context, input *InputService8TestShapeInputService8TestCaseOperation2Input, opts ...request.Option) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { + req, out := c.InputService8TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService8TestCaseOperation2 = "OperationName" + +// InputService8TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService8TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService8TestCaseOperation2 for more information on using the InputService8TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService8TestCaseOperation2Request method. +// req, resp := client.InputService8TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService8ProtocolTest) InputService8TestCaseOperation2Request(input *InputService8TestShapeInputService8TestCaseOperation2Input) (req *request.Request, output *InputService8TestShapeInputService8TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService8TestCaseOperation2, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService8TestShapeInputService8TestCaseOperation2Input{} + } + + output = &InputService8TestShapeInputService8TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService8TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService8TestCaseOperation2 for usage and error information. +func (c *InputService8ProtocolTest) InputService8TestCaseOperation2(input *InputService8TestShapeInputService8TestCaseOperation2Input) (*InputService8TestShapeInputService8TestCaseOperation2Output, error) { + req, out := c.InputService8TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService8TestCaseOperation2WithContext is the same as InputService8TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService8TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService8ProtocolTest) InputService8TestCaseOperation2WithContext(ctx aws.Context, input *InputService8TestShapeInputService8TestCaseOperation2Input, opts ...request.Option) (*InputService8TestShapeInputService8TestCaseOperation2Output, error) { + req, out := c.InputService8TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService8TestShapeInputService8TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService8TestShapeInputService8TestCaseOperation2Input struct { + _ struct{} `type:"structure"` + + FooEnum *string `type:"string" enum:"InputService8TestShapeEnumType"` + + ListEnums []*string `type:"list"` +} + +// SetFooEnum sets the FooEnum field's value. +func (s *InputService8TestShapeInputService8TestCaseOperation2Input) SetFooEnum(v string) *InputService8TestShapeInputService8TestCaseOperation2Input { + s.FooEnum = &v + return s +} + +// SetListEnums sets the ListEnums field's value. +func (s *InputService8TestShapeInputService8TestCaseOperation2Input) SetListEnums(v []*string) *InputService8TestShapeInputService8TestCaseOperation2Input { + s.ListEnums = v + return s +} + +type InputService8TestShapeInputService8TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +const ( + // EnumTypeFoo is a InputService8TestShapeEnumType enum value + EnumTypeFoo = "foo" + + // EnumTypeBar is a InputService8TestShapeEnumType enum value + EnumTypeBar = "bar" +) + +// +// Tests begin here +// + +func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) { + svc := NewInputService1ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService1TestShapeInputService1TestCaseOperation1Input{ + Name: aws.String("myname"), + } + req, _ := svc.InputService1TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"Name":"myname"}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService2ProtocolTestTimestampValuesCase1(t *testing.T) { + svc := NewInputService2ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService2TestShapeInputService2TestCaseOperation1Input{ + TimeArg: aws.Time(time.Unix(1422172800, 0)), + } + req, _ := svc.InputService2TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"TimeArg":1422172800}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService3ProtocolTestBase64EncodedBlobsCase1(t *testing.T) { + svc := NewInputService3ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService3TestShapeInputService3TestCaseOperation2Input{ + BlobArg: []byte("foo"), + } + req, _ := svc.InputService3TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"BlobArg":"Zm9v"}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService3ProtocolTestBase64EncodedBlobsCase2(t *testing.T) { + svc := NewInputService3ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService3TestShapeInputService3TestCaseOperation2Input{ + BlobMap: map[string][]byte{ + "key1": []byte("foo"), + "key2": []byte("bar"), + }, + } + req, _ := svc.InputService3TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"BlobMap":{"key1":"Zm9v","key2":"YmFy"}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService4ProtocolTestNestedBlobsCase1(t *testing.T) { + svc := NewInputService4ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService4TestShapeInputService4TestCaseOperation1Input{ + ListParam: [][]byte{ + []byte("foo"), + []byte("bar"), + }, + } + req, _ := svc.InputService4TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"ListParam":["Zm9v","YmFy"]}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService5ProtocolTestRecursiveShapesCase1(t *testing.T) { + svc := NewInputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService5TestShapeInputService5TestCaseOperation6Input{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + } + req, _ := svc.InputService5TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"RecursiveStruct":{"NoRecurse":"foo"}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService5ProtocolTestRecursiveShapesCase2(t *testing.T) { + svc := NewInputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService5TestShapeInputService5TestCaseOperation6Input{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + }, + } + req, _ := svc.InputService5TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"RecursiveStruct":{"RecursiveStruct":{"NoRecurse":"foo"}}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService5ProtocolTestRecursiveShapesCase3(t *testing.T) { + svc := NewInputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService5TestShapeInputService5TestCaseOperation6Input{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation3Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"RecursiveStruct":{"RecursiveStruct":{"RecursiveStruct":{"RecursiveStruct":{"NoRecurse":"foo"}}}}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService5ProtocolTestRecursiveShapesCase4(t *testing.T) { + svc := NewInputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService5TestShapeInputService5TestCaseOperation6Input{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveList: []*InputService5TestShapeRecursiveStructType{ + { + NoRecurse: aws.String("foo"), + }, + { + NoRecurse: aws.String("bar"), + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation4Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"RecursiveStruct":{"RecursiveList":[{"NoRecurse":"foo"},{"NoRecurse":"bar"}]}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService5ProtocolTestRecursiveShapesCase5(t *testing.T) { + svc := NewInputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService5TestShapeInputService5TestCaseOperation6Input{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveList: []*InputService5TestShapeRecursiveStructType{ + { + NoRecurse: aws.String("foo"), + }, + { + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + NoRecurse: aws.String("bar"), + }, + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation5Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"RecursiveStruct":{"RecursiveList":[{"NoRecurse":"foo"},{"RecursiveStruct":{"NoRecurse":"bar"}}]}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService5ProtocolTestRecursiveShapesCase6(t *testing.T) { + svc := NewInputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService5TestShapeInputService5TestCaseOperation6Input{ + RecursiveStruct: &InputService5TestShapeRecursiveStructType{ + RecursiveMap: map[string]*InputService5TestShapeRecursiveStructType{ + "bar": { + NoRecurse: aws.String("bar"), + }, + "foo": { + NoRecurse: aws.String("foo"), + }, + }, + }, + } + req, _ := svc.InputService5TestCaseOperation6Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"RecursiveStruct":{"RecursiveMap":{"foo":{"NoRecurse":"foo"},"bar":{"NoRecurse":"bar"}}}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService6ProtocolTestEmptyMapsCase1(t *testing.T) { + svc := NewInputService6ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService6TestShapeInputService6TestCaseOperation1Input{ + Map: map[string]*string{}, + } + req, _ := svc.InputService6TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"Map":{}}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + if e, a := "application/x-amz-json-1.1", r.Header.Get("Content-Type"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + if e, a := "com.amazonaws.foo.OperationName", r.Header.Get("X-Amz-Target"); e != a { + t.Errorf("expect %v to be %v", e, a) + } + +} + +func TestInputService7ProtocolTestIdempotencyTokenAutoFillCase1(t *testing.T) { + svc := NewInputService7ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService7TestShapeInputService7TestCaseOperation2Input{ + Token: aws.String("abc123"), + } + req, _ := svc.InputService7TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"Token":"abc123"}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService7ProtocolTestIdempotencyTokenAutoFillCase2(t *testing.T) { + svc := NewInputService7ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService7TestShapeInputService7TestCaseOperation2Input{} + req, _ := svc.InputService7TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"Token":"00000000-0000-4000-8000-000000000000"}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService8ProtocolTestEnumCase1(t *testing.T) { + svc := NewInputService8ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService8TestShapeInputService8TestCaseOperation2Input{ + FooEnum: aws.String("foo"), + ListEnums: []*string{ + aws.String("foo"), + aws.String(""), + aws.String("bar"), + }, + } + req, _ := svc.InputService8TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertJSON(t, `{"FooEnum":"foo","ListEnums":["foo","","bar"]}`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService8ProtocolTestEnumCase2(t *testing.T) { + svc := NewInputService8ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService8TestShapeInputService8TestCaseOperation2Input{} + req, _ := svc.InputService8TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + jsonrpc.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go new file mode 100644 index 0000000..56af4dc --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go @@ -0,0 +1,111 @@ +// Package jsonrpc provides JSON RPC utilities for serialization of AWS +// requests and responses. +package jsonrpc + +//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/json.json build_test.go +//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/json.json unmarshal_test.go + +import ( + "encoding/json" + "io/ioutil" + "strings" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil" + "github.com/aws/aws-sdk-go/private/protocol/rest" +) + +var emptyJSON = []byte("{}") + +// BuildHandler is a named request handler for building jsonrpc protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Build", Fn: Build} + +// UnmarshalHandler is a named request handler for unmarshaling jsonrpc protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.jsonrpc.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling jsonrpc protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalMeta", Fn: UnmarshalMeta} + +// UnmarshalErrorHandler is a named request handler for unmarshaling jsonrpc protocol request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.jsonrpc.UnmarshalError", Fn: UnmarshalError} + +// Build builds a JSON payload for a JSON RPC request. +func Build(req *request.Request) { + var buf []byte + var err error + if req.ParamsFilled() { + buf, err = jsonutil.BuildJSON(req.Params) + if err != nil { + req.Error = awserr.New("SerializationError", "failed encoding JSON RPC request", err) + return + } + } else { + buf = emptyJSON + } + + if req.ClientInfo.TargetPrefix != "" || string(buf) != "{}" { + req.SetBufferBody(buf) + } + + if req.ClientInfo.TargetPrefix != "" { + target := req.ClientInfo.TargetPrefix + "." + req.Operation.Name + req.HTTPRequest.Header.Add("X-Amz-Target", target) + } + if req.ClientInfo.JSONVersion != "" { + jsonVersion := req.ClientInfo.JSONVersion + req.HTTPRequest.Header.Add("Content-Type", "application/x-amz-json-"+jsonVersion) + } +} + +// Unmarshal unmarshals a response for a JSON RPC service. +func Unmarshal(req *request.Request) { + defer req.HTTPResponse.Body.Close() + if req.DataFilled() { + err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body) + if err != nil { + req.Error = awserr.New("SerializationError", "failed decoding JSON RPC response", err) + } + } + return +} + +// UnmarshalMeta unmarshals headers from a response for a JSON RPC service. +func UnmarshalMeta(req *request.Request) { + rest.UnmarshalMeta(req) +} + +// UnmarshalError unmarshals an error response for a JSON RPC service. +func UnmarshalError(req *request.Request) { + defer req.HTTPResponse.Body.Close() + bodyBytes, err := ioutil.ReadAll(req.HTTPResponse.Body) + if err != nil { + req.Error = awserr.New("SerializationError", "failed reading JSON RPC error response", err) + return + } + if len(bodyBytes) == 0 { + req.Error = awserr.NewRequestFailure( + awserr.New("SerializationError", req.HTTPResponse.Status, nil), + req.HTTPResponse.StatusCode, + "", + ) + return + } + var jsonErr jsonErrorResponse + if err := json.Unmarshal(bodyBytes, &jsonErr); err != nil { + req.Error = awserr.New("SerializationError", "failed decoding JSON RPC error response", err) + return + } + + codes := strings.SplitN(jsonErr.Code, "#", 2) + req.Error = awserr.NewRequestFailure( + awserr.New(codes[len(codes)-1], jsonErr.Message, nil), + req.HTTPResponse.StatusCode, + req.RequestID, + ) +} + +type jsonErrorResponse struct { + Code string `json:"__type"` + Message string `json:"message"` +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/unmarshal_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/unmarshal_test.go new file mode 100644 index 0000000..4d9c365 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/unmarshal_test.go @@ -0,0 +1,1521 @@ +package jsonrpc_test + +import ( + "bytes" + "encoding/json" + "encoding/xml" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" + "github.com/aws/aws-sdk-go/private/util" +) + +var _ bytes.Buffer // always import bytes +var _ http.Request +var _ json.Marshaler +var _ time.Time +var _ xmlutil.XMLNode +var _ xml.Attr +var _ = ioutil.Discard +var _ = util.Trim("") +var _ = url.Values{} +var _ = io.EOF +var _ = aws.String +var _ = fmt.Println +var _ = reflect.Value{} + +func init() { + protocol.RandReader = &awstesting.ZeroReader{} +} + +// OutputService1ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService1ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService1ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService1ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService1ProtocolTest client from just a session. +// svc := outputservice1protocoltest.New(mySession) +// +// // Create a OutputService1ProtocolTest client with additional configuration +// svc := outputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService1ProtocolTest { + c := p.ClientConfig("outputservice1protocoltest", cfgs...) + return newOutputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService1ProtocolTest { + svc := &OutputService1ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice1protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService1ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService1TestCaseOperation1 = "OperationName" + +// OutputService1TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService1TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService1TestCaseOperation1 for more information on using the OutputService1TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService1TestCaseOperation1Request method. +// req, resp := client.OutputService1TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (req *request.Request, output *OutputService1TestShapeOutputService1TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService1TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{} + } + + output = &OutputService1TestShapeOutputService1TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService1TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService1TestCaseOperation1 for usage and error information. +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (*OutputService1TestShapeOutputService1TestCaseOperation1Output, error) { + req, out := c.OutputService1TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService1TestCaseOperation1WithContext is the same as OutputService1TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService1TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1WithContext(ctx aws.Context, input *OutputService1TestShapeOutputService1TestCaseOperation1Input, opts ...request.Option) (*OutputService1TestShapeOutputService1TestCaseOperation1Output, error) { + req, out := c.OutputService1TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService1TestShapeOutputService1TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService1TestShapeOutputService1TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Char *string `type:"character"` + + Double *float64 `type:"double"` + + FalseBool *bool `type:"boolean"` + + Float *float64 `type:"float"` + + Long *int64 `type:"long"` + + Num *int64 `type:"integer"` + + Str *string `type:"string"` + + TrueBool *bool `type:"boolean"` +} + +// SetChar sets the Char field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetChar(v string) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Char = &v + return s +} + +// SetDouble sets the Double field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetDouble(v float64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Double = &v + return s +} + +// SetFalseBool sets the FalseBool field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetFalseBool(v bool) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.FalseBool = &v + return s +} + +// SetFloat sets the Float field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetFloat(v float64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Float = &v + return s +} + +// SetLong sets the Long field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetLong(v int64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Long = &v + return s +} + +// SetNum sets the Num field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetNum(v int64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Num = &v + return s +} + +// SetStr sets the Str field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetStr(v string) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Str = &v + return s +} + +// SetTrueBool sets the TrueBool field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetTrueBool(v bool) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.TrueBool = &v + return s +} + +// OutputService2ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService2ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService2ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService2ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService2ProtocolTest client from just a session. +// svc := outputservice2protocoltest.New(mySession) +// +// // Create a OutputService2ProtocolTest client with additional configuration +// svc := outputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService2ProtocolTest { + c := p.ClientConfig("outputservice2protocoltest", cfgs...) + return newOutputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService2ProtocolTest { + svc := &OutputService2ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice2protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService2ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService2TestCaseOperation1 = "OperationName" + +// OutputService2TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService2TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService2TestCaseOperation1 for more information on using the OutputService2TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService2TestCaseOperation1Request method. +// req, resp := client.OutputService2TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1Request(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (req *request.Request, output *OutputService2TestShapeOutputService2TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService2TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService2TestShapeOutputService2TestCaseOperation1Input{} + } + + output = &OutputService2TestShapeOutputService2TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService2TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService2TestCaseOperation1 for usage and error information. +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (*OutputService2TestShapeOutputService2TestCaseOperation1Output, error) { + req, out := c.OutputService2TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService2TestCaseOperation1WithContext is the same as OutputService2TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService2TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1WithContext(ctx aws.Context, input *OutputService2TestShapeOutputService2TestCaseOperation1Input, opts ...request.Option) (*OutputService2TestShapeOutputService2TestCaseOperation1Output, error) { + req, out := c.OutputService2TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService2TestShapeBlobContainer struct { + _ struct{} `type:"structure"` + + // Foo is automatically base64 encoded/decoded by the SDK. + Foo []byte `locationName:"foo" type:"blob"` +} + +// SetFoo sets the Foo field's value. +func (s *OutputService2TestShapeBlobContainer) SetFoo(v []byte) *OutputService2TestShapeBlobContainer { + s.Foo = v + return s +} + +type OutputService2TestShapeOutputService2TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService2TestShapeOutputService2TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + // BlobMember is automatically base64 encoded/decoded by the SDK. + BlobMember []byte `type:"blob"` + + StructMember *OutputService2TestShapeBlobContainer `type:"structure"` +} + +// SetBlobMember sets the BlobMember field's value. +func (s *OutputService2TestShapeOutputService2TestCaseOperation1Output) SetBlobMember(v []byte) *OutputService2TestShapeOutputService2TestCaseOperation1Output { + s.BlobMember = v + return s +} + +// SetStructMember sets the StructMember field's value. +func (s *OutputService2TestShapeOutputService2TestCaseOperation1Output) SetStructMember(v *OutputService2TestShapeBlobContainer) *OutputService2TestShapeOutputService2TestCaseOperation1Output { + s.StructMember = v + return s +} + +// OutputService3ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService3ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService3ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService3ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService3ProtocolTest client from just a session. +// svc := outputservice3protocoltest.New(mySession) +// +// // Create a OutputService3ProtocolTest client with additional configuration +// svc := outputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService3ProtocolTest { + c := p.ClientConfig("outputservice3protocoltest", cfgs...) + return newOutputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService3ProtocolTest { + svc := &OutputService3ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice3protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService3ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService3TestCaseOperation1 = "OperationName" + +// OutputService3TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService3TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService3TestCaseOperation1 for more information on using the OutputService3TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService3TestCaseOperation1Request method. +// req, resp := client.OutputService3TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1Request(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (req *request.Request, output *OutputService3TestShapeOutputService3TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService3TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService3TestShapeOutputService3TestCaseOperation1Input{} + } + + output = &OutputService3TestShapeOutputService3TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService3TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService3TestCaseOperation1 for usage and error information. +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (*OutputService3TestShapeOutputService3TestCaseOperation1Output, error) { + req, out := c.OutputService3TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService3TestCaseOperation1WithContext is the same as OutputService3TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService3TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1WithContext(ctx aws.Context, input *OutputService3TestShapeOutputService3TestCaseOperation1Input, opts ...request.Option) (*OutputService3TestShapeOutputService3TestCaseOperation1Output, error) { + req, out := c.OutputService3TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService3TestShapeOutputService3TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService3TestShapeOutputService3TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + StructMember *OutputService3TestShapeTimeContainer `type:"structure"` + + TimeMember *time.Time `type:"timestamp" timestampFormat:"unix"` +} + +// SetStructMember sets the StructMember field's value. +func (s *OutputService3TestShapeOutputService3TestCaseOperation1Output) SetStructMember(v *OutputService3TestShapeTimeContainer) *OutputService3TestShapeOutputService3TestCaseOperation1Output { + s.StructMember = v + return s +} + +// SetTimeMember sets the TimeMember field's value. +func (s *OutputService3TestShapeOutputService3TestCaseOperation1Output) SetTimeMember(v time.Time) *OutputService3TestShapeOutputService3TestCaseOperation1Output { + s.TimeMember = &v + return s +} + +type OutputService3TestShapeTimeContainer struct { + _ struct{} `type:"structure"` + + Foo *time.Time `locationName:"foo" type:"timestamp" timestampFormat:"unix"` +} + +// SetFoo sets the Foo field's value. +func (s *OutputService3TestShapeTimeContainer) SetFoo(v time.Time) *OutputService3TestShapeTimeContainer { + s.Foo = &v + return s +} + +// OutputService4ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService4ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService4ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService4ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService4ProtocolTest client from just a session. +// svc := outputservice4protocoltest.New(mySession) +// +// // Create a OutputService4ProtocolTest client with additional configuration +// svc := outputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService4ProtocolTest { + c := p.ClientConfig("outputservice4protocoltest", cfgs...) + return newOutputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService4ProtocolTest { + svc := &OutputService4ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice4protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService4ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService4TestCaseOperation1 = "OperationName" + +// OutputService4TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService4TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService4TestCaseOperation1 for more information on using the OutputService4TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService4TestCaseOperation1Request method. +// req, resp := client.OutputService4TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1Request(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (req *request.Request, output *OutputService4TestShapeOutputService4TestCaseOperation2Output) { + op := &request.Operation{ + Name: opOutputService4TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService4TestShapeOutputService4TestCaseOperation1Input{} + } + + output = &OutputService4TestShapeOutputService4TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService4TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService4TestCaseOperation1 for usage and error information. +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (*OutputService4TestShapeOutputService4TestCaseOperation2Output, error) { + req, out := c.OutputService4TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService4TestCaseOperation1WithContext is the same as OutputService4TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService4TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1WithContext(ctx aws.Context, input *OutputService4TestShapeOutputService4TestCaseOperation1Input, opts ...request.Option) (*OutputService4TestShapeOutputService4TestCaseOperation2Output, error) { + req, out := c.OutputService4TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opOutputService4TestCaseOperation2 = "OperationName" + +// OutputService4TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the OutputService4TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService4TestCaseOperation2 for more information on using the OutputService4TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService4TestCaseOperation2Request method. +// req, resp := client.OutputService4TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation2Request(input *OutputService4TestShapeOutputService4TestCaseOperation2Input) (req *request.Request, output *OutputService4TestShapeOutputService4TestCaseOperation2Output) { + op := &request.Operation{ + Name: opOutputService4TestCaseOperation2, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService4TestShapeOutputService4TestCaseOperation2Input{} + } + + output = &OutputService4TestShapeOutputService4TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService4TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService4TestCaseOperation2 for usage and error information. +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation2(input *OutputService4TestShapeOutputService4TestCaseOperation2Input) (*OutputService4TestShapeOutputService4TestCaseOperation2Output, error) { + req, out := c.OutputService4TestCaseOperation2Request(input) + return out, req.Send() +} + +// OutputService4TestCaseOperation2WithContext is the same as OutputService4TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService4TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation2WithContext(ctx aws.Context, input *OutputService4TestShapeOutputService4TestCaseOperation2Input, opts ...request.Option) (*OutputService4TestShapeOutputService4TestCaseOperation2Output, error) { + req, out := c.OutputService4TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService4TestShapeOutputService4TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService4TestShapeOutputService4TestCaseOperation2Input struct { + _ struct{} `type:"structure"` +} + +type OutputService4TestShapeOutputService4TestCaseOperation2Output struct { + _ struct{} `type:"structure"` + + ListMember []*string `type:"list"` + + ListMemberMap []map[string]*string `type:"list"` + + ListMemberStruct []*OutputService4TestShapeStructType `type:"list"` +} + +// SetListMember sets the ListMember field's value. +func (s *OutputService4TestShapeOutputService4TestCaseOperation2Output) SetListMember(v []*string) *OutputService4TestShapeOutputService4TestCaseOperation2Output { + s.ListMember = v + return s +} + +// SetListMemberMap sets the ListMemberMap field's value. +func (s *OutputService4TestShapeOutputService4TestCaseOperation2Output) SetListMemberMap(v []map[string]*string) *OutputService4TestShapeOutputService4TestCaseOperation2Output { + s.ListMemberMap = v + return s +} + +// SetListMemberStruct sets the ListMemberStruct field's value. +func (s *OutputService4TestShapeOutputService4TestCaseOperation2Output) SetListMemberStruct(v []*OutputService4TestShapeStructType) *OutputService4TestShapeOutputService4TestCaseOperation2Output { + s.ListMemberStruct = v + return s +} + +type OutputService4TestShapeStructType struct { + _ struct{} `type:"structure"` +} + +// OutputService5ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService5ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService5ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService5ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService5ProtocolTest client from just a session. +// svc := outputservice5protocoltest.New(mySession) +// +// // Create a OutputService5ProtocolTest client with additional configuration +// svc := outputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService5ProtocolTest { + c := p.ClientConfig("outputservice5protocoltest", cfgs...) + return newOutputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService5ProtocolTest { + svc := &OutputService5ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice5protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService5ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService5TestCaseOperation1 = "OperationName" + +// OutputService5TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService5TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService5TestCaseOperation1 for more information on using the OutputService5TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService5TestCaseOperation1Request method. +// req, resp := client.OutputService5TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1Request(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (req *request.Request, output *OutputService5TestShapeOutputService5TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService5TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService5TestShapeOutputService5TestCaseOperation1Input{} + } + + output = &OutputService5TestShapeOutputService5TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService5TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService5TestCaseOperation1 for usage and error information. +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (*OutputService5TestShapeOutputService5TestCaseOperation1Output, error) { + req, out := c.OutputService5TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService5TestCaseOperation1WithContext is the same as OutputService5TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService5TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1WithContext(ctx aws.Context, input *OutputService5TestShapeOutputService5TestCaseOperation1Input, opts ...request.Option) (*OutputService5TestShapeOutputService5TestCaseOperation1Output, error) { + req, out := c.OutputService5TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService5TestShapeOutputService5TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService5TestShapeOutputService5TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + MapMember map[string][]*int64 `type:"map"` +} + +// SetMapMember sets the MapMember field's value. +func (s *OutputService5TestShapeOutputService5TestCaseOperation1Output) SetMapMember(v map[string][]*int64) *OutputService5TestShapeOutputService5TestCaseOperation1Output { + s.MapMember = v + return s +} + +// OutputService6ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService6ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService6ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService6ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService6ProtocolTest client from just a session. +// svc := outputservice6protocoltest.New(mySession) +// +// // Create a OutputService6ProtocolTest client with additional configuration +// svc := outputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService6ProtocolTest { + c := p.ClientConfig("outputservice6protocoltest", cfgs...) + return newOutputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService6ProtocolTest { + svc := &OutputService6ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice6protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService6ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService6TestCaseOperation1 = "OperationName" + +// OutputService6TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService6TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService6TestCaseOperation1 for more information on using the OutputService6TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService6TestCaseOperation1Request method. +// req, resp := client.OutputService6TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1Request(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (req *request.Request, output *OutputService6TestShapeOutputService6TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService6TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService6TestShapeOutputService6TestCaseOperation1Input{} + } + + output = &OutputService6TestShapeOutputService6TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService6TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService6TestCaseOperation1 for usage and error information. +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (*OutputService6TestShapeOutputService6TestCaseOperation1Output, error) { + req, out := c.OutputService6TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService6TestCaseOperation1WithContext is the same as OutputService6TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService6TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1WithContext(ctx aws.Context, input *OutputService6TestShapeOutputService6TestCaseOperation1Input, opts ...request.Option) (*OutputService6TestShapeOutputService6TestCaseOperation1Output, error) { + req, out := c.OutputService6TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService6TestShapeOutputService6TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService6TestShapeOutputService6TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + StrType *string `type:"string"` +} + +// SetStrType sets the StrType field's value. +func (s *OutputService6TestShapeOutputService6TestCaseOperation1Output) SetStrType(v string) *OutputService6TestShapeOutputService6TestCaseOperation1Output { + s.StrType = &v + return s +} + +// OutputService7ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService7ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService7ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService7ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService7ProtocolTest client from just a session. +// svc := outputservice7protocoltest.New(mySession) +// +// // Create a OutputService7ProtocolTest client with additional configuration +// svc := outputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService7ProtocolTest { + c := p.ClientConfig("outputservice7protocoltest", cfgs...) + return newOutputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService7ProtocolTest { + svc := &OutputService7ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice7protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService7ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService7TestCaseOperation1 = "OperationName" + +// OutputService7TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService7TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService7TestCaseOperation1 for more information on using the OutputService7TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService7TestCaseOperation1Request method. +// req, resp := client.OutputService7TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1Request(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (req *request.Request, output *OutputService7TestShapeOutputService7TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService7TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService7TestShapeOutputService7TestCaseOperation1Input{} + } + + output = &OutputService7TestShapeOutputService7TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService7TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService7TestCaseOperation1 for usage and error information. +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (*OutputService7TestShapeOutputService7TestCaseOperation1Output, error) { + req, out := c.OutputService7TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService7TestCaseOperation1WithContext is the same as OutputService7TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService7TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1WithContext(ctx aws.Context, input *OutputService7TestShapeOutputService7TestCaseOperation1Input, opts ...request.Option) (*OutputService7TestShapeOutputService7TestCaseOperation1Output, error) { + req, out := c.OutputService7TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService7TestShapeOutputService7TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService7TestShapeOutputService7TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + FooEnum *string `type:"string" enum:"OutputService7TestShapeJSONEnumType"` + + ListEnums []*string `type:"list"` +} + +// SetFooEnum sets the FooEnum field's value. +func (s *OutputService7TestShapeOutputService7TestCaseOperation1Output) SetFooEnum(v string) *OutputService7TestShapeOutputService7TestCaseOperation1Output { + s.FooEnum = &v + return s +} + +// SetListEnums sets the ListEnums field's value. +func (s *OutputService7TestShapeOutputService7TestCaseOperation1Output) SetListEnums(v []*string) *OutputService7TestShapeOutputService7TestCaseOperation1Output { + s.ListEnums = v + return s +} + +const ( + // JSONEnumTypeFoo is a OutputService7TestShapeJSONEnumType enum value + JSONEnumTypeFoo = "foo" + + // JSONEnumTypeBar is a OutputService7TestShapeJSONEnumType enum value + JSONEnumTypeBar = "bar" +) + +// +// Tests begin here +// + +func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) { + svc := NewOutputService1ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"Str\": \"myname\", \"Num\": 123, \"FalseBool\": false, \"TrueBool\": true, \"Float\": 1.2, \"Double\": 1.3, \"Long\": 200, \"Char\": \"a\"}")) + req, out := svc.OutputService1TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "a", *out.Char; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := 1.3, *out.Double; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := false, *out.FalseBool; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := 1.2, *out.Float; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := int64(200), *out.Long; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := int64(123), *out.Num; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "myname", *out.Str; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := true, *out.TrueBool; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService2ProtocolTestBlobMembersCase1(t *testing.T) { + svc := NewOutputService2ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"BlobMember\": \"aGkh\", \"StructMember\": {\"foo\": \"dGhlcmUh\"}}")) + req, out := svc.OutputService2TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "hi!", string(out.BlobMember); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "there!", string(out.StructMember.Foo); e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService3ProtocolTestTimestampMembersCase1(t *testing.T) { + svc := NewOutputService3ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"TimeMember\": 1398796238, \"StructMember\": {\"foo\": 1398796238}}")) + req, out := svc.OutputService3TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := time.Unix(1.398796238e+09, 0).UTC().String(), out.StructMember.Foo.String(); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := time.Unix(1.398796238e+09, 0).UTC().String(), out.TimeMember.String(); e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService4ProtocolTestListsCase1(t *testing.T) { + svc := NewOutputService4ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"ListMember\": [\"a\", \"b\"]}")) + req, out := svc.OutputService4TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "a", *out.ListMember[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "b", *out.ListMember[1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService4ProtocolTestListsCase2(t *testing.T) { + svc := NewOutputService4ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"ListMember\": [\"a\", null], \"ListMemberMap\": [{}, null, null, {}], \"ListMemberStruct\": [{}, null, null, {}]}")) + req, out := svc.OutputService4TestCaseOperation2Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "a", *out.ListMember[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e := out.ListMember[1]; e != nil { + t.Errorf("expect nil, got %v", e) + } + if e := out.ListMemberMap[1]; e != nil { + t.Errorf("expect nil, got %v", e) + } + if e := out.ListMemberMap[2]; e != nil { + t.Errorf("expect nil, got %v", e) + } + if e := out.ListMemberStruct[1]; e != nil { + t.Errorf("expect nil, got %v", e) + } + if e := out.ListMemberStruct[2]; e != nil { + t.Errorf("expect nil, got %v", e) + } + +} + +func TestOutputService5ProtocolTestMapsCase1(t *testing.T) { + svc := NewOutputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"MapMember\": {\"a\": [1, 2], \"b\": [3, 4]}}")) + req, out := svc.OutputService5TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := int64(1), *out.MapMember["a"][0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := int64(2), *out.MapMember["a"][1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := int64(3), *out.MapMember["b"][0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := int64(4), *out.MapMember["b"][1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService6ProtocolTestIgnoresExtraDataCase1(t *testing.T) { + svc := NewOutputService6ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"foo\": \"bar\"}")) + req, out := svc.OutputService6TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + +} + +func TestOutputService7ProtocolTestEnumOutputCase1(t *testing.T) { + svc := NewOutputService7ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("{\"FooEnum\": \"foo\", \"ListEnums\": [\"foo\", \"bar\"]}")) + req, out := svc.OutputService7TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + jsonrpc.UnmarshalMeta(req) + jsonrpc.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "foo", *out.FooEnum; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "foo", *out.ListEnums[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "bar", *out.ListEnums[1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue.go new file mode 100644 index 0000000..776d110 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue.go @@ -0,0 +1,76 @@ +package protocol + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "strconv" + + "github.com/aws/aws-sdk-go/aws" +) + +// EscapeMode is the mode that should be use for escaping a value +type EscapeMode uint + +// The modes for escaping a value before it is marshaled, and unmarshaled. +const ( + NoEscape EscapeMode = iota + Base64Escape + QuotedEscape +) + +// EncodeJSONValue marshals the value into a JSON string, and optionally base64 +// encodes the string before returning it. +// +// Will panic if the escape mode is unknown. +func EncodeJSONValue(v aws.JSONValue, escape EscapeMode) (string, error) { + b, err := json.Marshal(v) + if err != nil { + return "", err + } + + switch escape { + case NoEscape: + return string(b), nil + case Base64Escape: + return base64.StdEncoding.EncodeToString(b), nil + case QuotedEscape: + return strconv.Quote(string(b)), nil + } + + panic(fmt.Sprintf("EncodeJSONValue called with unknown EscapeMode, %v", escape)) +} + +// DecodeJSONValue will attempt to decode the string input as a JSONValue. +// Optionally decoding base64 the value first before JSON unmarshaling. +// +// Will panic if the escape mode is unknown. +func DecodeJSONValue(v string, escape EscapeMode) (aws.JSONValue, error) { + var b []byte + var err error + + switch escape { + case NoEscape: + b = []byte(v) + case Base64Escape: + b, err = base64.StdEncoding.DecodeString(v) + case QuotedEscape: + var u string + u, err = strconv.Unquote(v) + b = []byte(u) + default: + panic(fmt.Sprintf("DecodeJSONValue called with unknown EscapeMode, %v", escape)) + } + + if err != nil { + return nil, err + } + + m := aws.JSONValue{} + err = json.Unmarshal(b, &m) + if err != nil { + return nil, err + } + + return m, nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue_test.go new file mode 100644 index 0000000..66a3c8c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue_test.go @@ -0,0 +1,93 @@ +package protocol + +import ( + "fmt" + "reflect" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" +) + +var testJSONValueCases = []struct { + Value aws.JSONValue + Mode EscapeMode + String string +}{ + { + Value: aws.JSONValue{ + "abc": 123., + }, + Mode: NoEscape, + String: `{"abc":123}`, + }, + { + Value: aws.JSONValue{ + "abc": 123., + }, + Mode: Base64Escape, + String: `eyJhYmMiOjEyM30=`, + }, + { + Value: aws.JSONValue{ + "abc": 123., + }, + Mode: QuotedEscape, + String: `"{\"abc\":123}"`, + }, +} + +func TestEncodeJSONValue(t *testing.T) { + for i, c := range testJSONValueCases { + str, err := EncodeJSONValue(c.Value, c.Mode) + if err != nil { + t.Fatalf("%d, expect no error, got %v", i, err) + } + if e, a := c.String, str; e != a { + t.Errorf("%d, expect %v encoded value, got %v", i, e, a) + } + } +} + +func TestDecodeJSONValue(t *testing.T) { + for i, c := range testJSONValueCases { + val, err := DecodeJSONValue(c.String, c.Mode) + if err != nil { + t.Fatalf("%d, expect no error, got %v", i, err) + } + if e, a := c.Value, val; !reflect.DeepEqual(e, a) { + t.Errorf("%d, expect %v encoded value, got %v", i, e, a) + } + } +} + +func TestEncodeJSONValue_PanicUnkownMode(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("expect panic, got none") + } else { + reason := fmt.Sprintf("%v", r) + if e, a := "unknown EscapeMode", reason; !strings.Contains(a, e) { + t.Errorf("expect %q to be in %v", e, a) + } + } + }() + + val := aws.JSONValue{} + + EncodeJSONValue(val, 123456) +} +func TestDecodeJSONValue_PanicUnkownMode(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("expect panic, got none") + } else { + reason := fmt.Sprintf("%v", r) + if e, a := "unknown EscapeMode", reason; !strings.Contains(a, e) { + t.Errorf("expect %q to be in %v", e, a) + } + } + }() + + DecodeJSONValue(`{"abc":123}`, 123456) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/protocol_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/protocol_test.go new file mode 100644 index 0000000..eb2e155 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/protocol_test.go @@ -0,0 +1,203 @@ +package protocol_test + +import ( + "net/http" + "net/url" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/aws/aws-sdk-go/private/protocol/ec2query" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" + "github.com/aws/aws-sdk-go/private/protocol/query" + "github.com/aws/aws-sdk-go/private/protocol/rest" + "github.com/aws/aws-sdk-go/private/protocol/restjson" + "github.com/aws/aws-sdk-go/private/protocol/restxml" +) + +func xmlData(set bool, b []byte, size, delta int) { + const openingTags = "" + const closingTags = "" + if !set { + copy(b, []byte(openingTags)) + } + if size == 0 { + copy(b[delta-len(closingTags):], []byte(closingTags)) + } +} + +func jsonData(set bool, b []byte, size, delta int) { + if !set { + copy(b, []byte("{\"A\": \"")) + } + if size == 0 { + copy(b[delta-len("\"}"):], []byte("\"}")) + } +} + +func buildNewRequest(data interface{}) *request.Request { + v := url.Values{} + v.Set("test", "TEST") + v.Add("test1", "TEST1") + + req := &request.Request{ + HTTPRequest: &http.Request{ + Header: make(http.Header), + Body: &awstesting.ReadCloser{Size: 2048}, + URL: &url.URL{ + RawQuery: v.Encode(), + }, + }, + Params: &struct { + LocationName string `locationName:"test"` + }{ + "Test", + }, + ClientInfo: metadata.ClientInfo{ + ServiceName: "test", + TargetPrefix: "test", + JSONVersion: "test", + APIVersion: "test", + Endpoint: "test", + SigningName: "test", + SigningRegion: "test", + }, + Operation: &request.Operation{ + Name: "test", + }, + } + req.HTTPResponse = &http.Response{ + Body: &awstesting.ReadCloser{Size: 2048}, + Header: http.Header{ + "X-Amzn-Requestid": []string{"1"}, + }, + StatusCode: http.StatusOK, + } + + if data == nil { + data = &struct { + _ struct{} `type:"structure"` + LocationName *string `locationName:"testName"` + Location *string `location:"statusCode"` + A *string `type:"string"` + }{} + } + + req.Data = data + + return req +} + +type expected struct { + dataType int + closed bool + size int + errExists bool +} + +const ( + jsonType = iota + xmlType +) + +func checkForLeak(data interface{}, build, fn func(*request.Request), t *testing.T, result expected) { + req := buildNewRequest(data) + reader := req.HTTPResponse.Body.(*awstesting.ReadCloser) + switch result.dataType { + case jsonType: + reader.FillData = jsonData + case xmlType: + reader.FillData = xmlData + } + build(req) + fn(req) + + if result.errExists { + assert.NotNil(t, req.Error) + } else { + assert.Nil(t, req.Error) + } + + assert.Equal(t, reader.Closed, result.closed) + assert.Equal(t, reader.Size, result.size) +} + +func TestJSONRpc(t *testing.T) { + checkForLeak(nil, jsonrpc.Build, jsonrpc.Unmarshal, t, expected{jsonType, true, 0, false}) + checkForLeak(nil, jsonrpc.Build, jsonrpc.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) + checkForLeak(nil, jsonrpc.Build, jsonrpc.UnmarshalError, t, expected{jsonType, true, 0, true}) +} + +func TestQuery(t *testing.T) { + checkForLeak(nil, query.Build, query.Unmarshal, t, expected{jsonType, true, 0, false}) + checkForLeak(nil, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) + checkForLeak(nil, query.Build, query.UnmarshalError, t, expected{jsonType, true, 0, true}) +} + +func TestRest(t *testing.T) { + // case 1: Payload io.ReadSeeker + checkForLeak(nil, rest.Build, rest.Unmarshal, t, expected{jsonType, false, 2048, false}) + checkForLeak(nil, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) + + // case 2: Payload *string + // should close the body + dataStr := struct { + _ struct{} `type:"structure" payload:"Payload"` + LocationName *string `locationName:"testName"` + Location *string `location:"statusCode"` + A *string `type:"string"` + Payload *string `locationName:"payload" type:"blob" required:"true"` + }{} + checkForLeak(&dataStr, rest.Build, rest.Unmarshal, t, expected{jsonType, true, 0, false}) + checkForLeak(&dataStr, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) + + // case 3: Payload []byte + // should close the body + dataBytes := struct { + _ struct{} `type:"structure" payload:"Payload"` + LocationName *string `locationName:"testName"` + Location *string `location:"statusCode"` + A *string `type:"string"` + Payload []byte `locationName:"payload" type:"blob" required:"true"` + }{} + checkForLeak(&dataBytes, rest.Build, rest.Unmarshal, t, expected{jsonType, true, 0, false}) + checkForLeak(&dataBytes, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) + + // case 4: Payload unsupported type + // should close the body + dataUnsupported := struct { + _ struct{} `type:"structure" payload:"Payload"` + LocationName *string `locationName:"testName"` + Location *string `location:"statusCode"` + A *string `type:"string"` + Payload string `locationName:"payload" type:"blob" required:"true"` + }{} + checkForLeak(&dataUnsupported, rest.Build, rest.Unmarshal, t, expected{jsonType, true, 0, true}) + checkForLeak(&dataUnsupported, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) +} + +func TestRestJSON(t *testing.T) { + checkForLeak(nil, restjson.Build, restjson.Unmarshal, t, expected{jsonType, true, 0, false}) + checkForLeak(nil, restjson.Build, restjson.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) + checkForLeak(nil, restjson.Build, restjson.UnmarshalError, t, expected{jsonType, true, 0, true}) +} + +func TestRestXML(t *testing.T) { + checkForLeak(nil, restxml.Build, restxml.Unmarshal, t, expected{xmlType, true, 0, false}) + checkForLeak(nil, restxml.Build, restxml.UnmarshalMeta, t, expected{xmlType, false, 2048, false}) + checkForLeak(nil, restxml.Build, restxml.UnmarshalError, t, expected{xmlType, true, 0, true}) +} + +func TestXML(t *testing.T) { + checkForLeak(nil, ec2query.Build, ec2query.Unmarshal, t, expected{jsonType, true, 0, false}) + checkForLeak(nil, ec2query.Build, ec2query.UnmarshalMeta, t, expected{jsonType, false, 2048, false}) + checkForLeak(nil, ec2query.Build, ec2query.UnmarshalError, t, expected{jsonType, true, 0, true}) +} + +func TestProtocol(t *testing.T) { + checkForLeak(nil, restxml.Build, protocol.UnmarshalDiscardBody, t, expected{xmlType, true, 0, false}) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go new file mode 100644 index 0000000..18169f0 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go @@ -0,0 +1,36 @@ +// Package query provides serialization of AWS query requests, and responses. +package query + +//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/input/query.json build_test.go + +import ( + "net/url" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/query/queryutil" +) + +// BuildHandler is a named request handler for building query protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.query.Build", Fn: Build} + +// Build builds a request for an AWS Query service. +func Build(r *request.Request) { + body := url.Values{ + "Action": {r.Operation.Name}, + "Version": {r.ClientInfo.APIVersion}, + } + if err := queryutil.Parse(body, r.Params, false); err != nil { + r.Error = awserr.New("SerializationError", "failed encoding Query request", err) + return + } + + if r.ExpireTime == 0 { + r.HTTPRequest.Method = "POST" + r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") + r.SetBufferBody([]byte(body.Encode())) + } else { // This is a pre-signed request + r.HTTPRequest.Method = "GET" + r.HTTPRequest.URL.RawQuery = body.Encode() + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go new file mode 100644 index 0000000..abcc271 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go @@ -0,0 +1,4056 @@ +package query_test + +import ( + "bytes" + "encoding/json" + "encoding/xml" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/aws/aws-sdk-go/private/protocol/query" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" + "github.com/aws/aws-sdk-go/private/util" +) + +var _ bytes.Buffer // always import bytes +var _ http.Request +var _ json.Marshaler +var _ time.Time +var _ xmlutil.XMLNode +var _ xml.Attr +var _ = ioutil.Discard +var _ = util.Trim("") +var _ = url.Values{} +var _ = io.EOF +var _ = aws.String +var _ = fmt.Println +var _ = reflect.Value{} + +func init() { + protocol.RandReader = &awstesting.ZeroReader{} +} + +// InputService1ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService1ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService1ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService1ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService1ProtocolTest client from just a session. +// svc := inputservice1protocoltest.New(mySession) +// +// // Create a InputService1ProtocolTest client with additional configuration +// svc := inputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService1ProtocolTest { + c := p.ClientConfig("inputservice1protocoltest", cfgs...) + return newInputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService1ProtocolTest { + svc := &InputService1ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice1protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService1ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService1TestCaseOperation1 = "OperationName" + +// InputService1TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService1TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService1TestCaseOperation1 for more information on using the InputService1TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService1TestCaseOperation1Request method. +// req, resp := client.InputService1TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1Request(input *InputService1TestShapeInputService1TestCaseOperation3Input) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService1TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService1TestShapeInputService1TestCaseOperation3Input{} + } + + output = &InputService1TestShapeInputService1TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService1TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService1TestCaseOperation1 for usage and error information. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1(input *InputService1TestShapeInputService1TestCaseOperation3Input) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { + req, out := c.InputService1TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService1TestCaseOperation1WithContext is the same as InputService1TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService1TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation1WithContext(ctx aws.Context, input *InputService1TestShapeInputService1TestCaseOperation3Input, opts ...request.Option) (*InputService1TestShapeInputService1TestCaseOperation1Output, error) { + req, out := c.InputService1TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService1TestCaseOperation2 = "OperationName" + +// InputService1TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService1TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService1TestCaseOperation2 for more information on using the InputService1TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService1TestCaseOperation2Request method. +// req, resp := client.InputService1TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService1ProtocolTest) InputService1TestCaseOperation2Request(input *InputService1TestShapeInputService1TestCaseOperation3Input) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService1TestCaseOperation2, + HTTPPath: "/", + } + + if input == nil { + input = &InputService1TestShapeInputService1TestCaseOperation3Input{} + } + + output = &InputService1TestShapeInputService1TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService1TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService1TestCaseOperation2 for usage and error information. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation2(input *InputService1TestShapeInputService1TestCaseOperation3Input) (*InputService1TestShapeInputService1TestCaseOperation2Output, error) { + req, out := c.InputService1TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService1TestCaseOperation2WithContext is the same as InputService1TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService1TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation2WithContext(ctx aws.Context, input *InputService1TestShapeInputService1TestCaseOperation3Input, opts ...request.Option) (*InputService1TestShapeInputService1TestCaseOperation2Output, error) { + req, out := c.InputService1TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService1TestCaseOperation3 = "OperationName" + +// InputService1TestCaseOperation3Request generates a "aws/request.Request" representing the +// client's request for the InputService1TestCaseOperation3 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService1TestCaseOperation3 for more information on using the InputService1TestCaseOperation3 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService1TestCaseOperation3Request method. +// req, resp := client.InputService1TestCaseOperation3Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService1ProtocolTest) InputService1TestCaseOperation3Request(input *InputService1TestShapeInputService1TestCaseOperation3Input) (req *request.Request, output *InputService1TestShapeInputService1TestCaseOperation3Output) { + op := &request.Operation{ + Name: opInputService1TestCaseOperation3, + HTTPPath: "/", + } + + if input == nil { + input = &InputService1TestShapeInputService1TestCaseOperation3Input{} + } + + output = &InputService1TestShapeInputService1TestCaseOperation3Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService1TestCaseOperation3 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService1TestCaseOperation3 for usage and error information. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation3(input *InputService1TestShapeInputService1TestCaseOperation3Input) (*InputService1TestShapeInputService1TestCaseOperation3Output, error) { + req, out := c.InputService1TestCaseOperation3Request(input) + return out, req.Send() +} + +// InputService1TestCaseOperation3WithContext is the same as InputService1TestCaseOperation3 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService1TestCaseOperation3 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService1ProtocolTest) InputService1TestCaseOperation3WithContext(ctx aws.Context, input *InputService1TestShapeInputService1TestCaseOperation3Input, opts ...request.Option) (*InputService1TestShapeInputService1TestCaseOperation3Output, error) { + req, out := c.InputService1TestCaseOperation3Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService1TestShapeInputService1TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService1TestShapeInputService1TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +type InputService1TestShapeInputService1TestCaseOperation3Input struct { + _ struct{} `type:"structure"` + + Bar *string `type:"string"` + + Baz *bool `type:"boolean"` + + Foo *string `type:"string"` +} + +// SetBar sets the Bar field's value. +func (s *InputService1TestShapeInputService1TestCaseOperation3Input) SetBar(v string) *InputService1TestShapeInputService1TestCaseOperation3Input { + s.Bar = &v + return s +} + +// SetBaz sets the Baz field's value. +func (s *InputService1TestShapeInputService1TestCaseOperation3Input) SetBaz(v bool) *InputService1TestShapeInputService1TestCaseOperation3Input { + s.Baz = &v + return s +} + +// SetFoo sets the Foo field's value. +func (s *InputService1TestShapeInputService1TestCaseOperation3Input) SetFoo(v string) *InputService1TestShapeInputService1TestCaseOperation3Input { + s.Foo = &v + return s +} + +type InputService1TestShapeInputService1TestCaseOperation3Output struct { + _ struct{} `type:"structure"` +} + +// InputService2ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService2ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService2ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService2ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService2ProtocolTest client from just a session. +// svc := inputservice2protocoltest.New(mySession) +// +// // Create a InputService2ProtocolTest client with additional configuration +// svc := inputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService2ProtocolTest { + c := p.ClientConfig("inputservice2protocoltest", cfgs...) + return newInputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService2ProtocolTest { + svc := &InputService2ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice2protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService2ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService2TestCaseOperation1 = "OperationName" + +// InputService2TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService2TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService2TestCaseOperation1 for more information on using the InputService2TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService2TestCaseOperation1Request method. +// req, resp := client.InputService2TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1Request(input *InputService2TestShapeInputService2TestCaseOperation1Input) (req *request.Request, output *InputService2TestShapeInputService2TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService2TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService2TestShapeInputService2TestCaseOperation1Input{} + } + + output = &InputService2TestShapeInputService2TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService2TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService2TestCaseOperation1 for usage and error information. +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1(input *InputService2TestShapeInputService2TestCaseOperation1Input) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { + req, out := c.InputService2TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService2TestCaseOperation1WithContext is the same as InputService2TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService2TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService2ProtocolTest) InputService2TestCaseOperation1WithContext(ctx aws.Context, input *InputService2TestShapeInputService2TestCaseOperation1Input, opts ...request.Option) (*InputService2TestShapeInputService2TestCaseOperation1Output, error) { + req, out := c.InputService2TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService2TestShapeInputService2TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + StructArg *InputService2TestShapeStructType `type:"structure"` +} + +// SetStructArg sets the StructArg field's value. +func (s *InputService2TestShapeInputService2TestCaseOperation1Input) SetStructArg(v *InputService2TestShapeStructType) *InputService2TestShapeInputService2TestCaseOperation1Input { + s.StructArg = v + return s +} + +type InputService2TestShapeInputService2TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService2TestShapeStructType struct { + _ struct{} `type:"structure"` + + ScalarArg *string `type:"string"` +} + +// SetScalarArg sets the ScalarArg field's value. +func (s *InputService2TestShapeStructType) SetScalarArg(v string) *InputService2TestShapeStructType { + s.ScalarArg = &v + return s +} + +// InputService3ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService3ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService3ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService3ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService3ProtocolTest client from just a session. +// svc := inputservice3protocoltest.New(mySession) +// +// // Create a InputService3ProtocolTest client with additional configuration +// svc := inputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService3ProtocolTest { + c := p.ClientConfig("inputservice3protocoltest", cfgs...) + return newInputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService3ProtocolTest { + svc := &InputService3ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice3protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService3ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService3TestCaseOperation1 = "OperationName" + +// InputService3TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService3TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService3TestCaseOperation1 for more information on using the InputService3TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService3TestCaseOperation1Request method. +// req, resp := client.InputService3TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1Request(input *InputService3TestShapeInputService3TestCaseOperation2Input) (req *request.Request, output *InputService3TestShapeInputService3TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService3TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService3TestShapeInputService3TestCaseOperation2Input{} + } + + output = &InputService3TestShapeInputService3TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService3TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService3TestCaseOperation1 for usage and error information. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1(input *InputService3TestShapeInputService3TestCaseOperation2Input) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { + req, out := c.InputService3TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService3TestCaseOperation1WithContext is the same as InputService3TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService3TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation1WithContext(ctx aws.Context, input *InputService3TestShapeInputService3TestCaseOperation2Input, opts ...request.Option) (*InputService3TestShapeInputService3TestCaseOperation1Output, error) { + req, out := c.InputService3TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService3TestCaseOperation2 = "OperationName" + +// InputService3TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService3TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService3TestCaseOperation2 for more information on using the InputService3TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService3TestCaseOperation2Request method. +// req, resp := client.InputService3TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2Request(input *InputService3TestShapeInputService3TestCaseOperation2Input) (req *request.Request, output *InputService3TestShapeInputService3TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService3TestCaseOperation2, + HTTPPath: "/", + } + + if input == nil { + input = &InputService3TestShapeInputService3TestCaseOperation2Input{} + } + + output = &InputService3TestShapeInputService3TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService3TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService3TestCaseOperation2 for usage and error information. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2(input *InputService3TestShapeInputService3TestCaseOperation2Input) (*InputService3TestShapeInputService3TestCaseOperation2Output, error) { + req, out := c.InputService3TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService3TestCaseOperation2WithContext is the same as InputService3TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService3TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService3ProtocolTest) InputService3TestCaseOperation2WithContext(ctx aws.Context, input *InputService3TestShapeInputService3TestCaseOperation2Input, opts ...request.Option) (*InputService3TestShapeInputService3TestCaseOperation2Output, error) { + req, out := c.InputService3TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService3TestShapeInputService3TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService3TestShapeInputService3TestCaseOperation2Input struct { + _ struct{} `type:"structure"` + + ListArg []*string `type:"list"` +} + +// SetListArg sets the ListArg field's value. +func (s *InputService3TestShapeInputService3TestCaseOperation2Input) SetListArg(v []*string) *InputService3TestShapeInputService3TestCaseOperation2Input { + s.ListArg = v + return s +} + +type InputService3TestShapeInputService3TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +// InputService4ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService4ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService4ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService4ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService4ProtocolTest client from just a session. +// svc := inputservice4protocoltest.New(mySession) +// +// // Create a InputService4ProtocolTest client with additional configuration +// svc := inputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService4ProtocolTest { + c := p.ClientConfig("inputservice4protocoltest", cfgs...) + return newInputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService4ProtocolTest { + svc := &InputService4ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice4protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService4ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService4TestCaseOperation1 = "OperationName" + +// InputService4TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService4TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService4TestCaseOperation1 for more information on using the InputService4TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService4TestCaseOperation1Request method. +// req, resp := client.InputService4TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1Request(input *InputService4TestShapeInputService4TestCaseOperation2Input) (req *request.Request, output *InputService4TestShapeInputService4TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService4TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService4TestShapeInputService4TestCaseOperation2Input{} + } + + output = &InputService4TestShapeInputService4TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService4TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService4TestCaseOperation1 for usage and error information. +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1(input *InputService4TestShapeInputService4TestCaseOperation2Input) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { + req, out := c.InputService4TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService4TestCaseOperation1WithContext is the same as InputService4TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService4TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService4ProtocolTest) InputService4TestCaseOperation1WithContext(ctx aws.Context, input *InputService4TestShapeInputService4TestCaseOperation2Input, opts ...request.Option) (*InputService4TestShapeInputService4TestCaseOperation1Output, error) { + req, out := c.InputService4TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService4TestCaseOperation2 = "OperationName" + +// InputService4TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService4TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService4TestCaseOperation2 for more information on using the InputService4TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService4TestCaseOperation2Request method. +// req, resp := client.InputService4TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService4ProtocolTest) InputService4TestCaseOperation2Request(input *InputService4TestShapeInputService4TestCaseOperation2Input) (req *request.Request, output *InputService4TestShapeInputService4TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService4TestCaseOperation2, + HTTPPath: "/", + } + + if input == nil { + input = &InputService4TestShapeInputService4TestCaseOperation2Input{} + } + + output = &InputService4TestShapeInputService4TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService4TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService4TestCaseOperation2 for usage and error information. +func (c *InputService4ProtocolTest) InputService4TestCaseOperation2(input *InputService4TestShapeInputService4TestCaseOperation2Input) (*InputService4TestShapeInputService4TestCaseOperation2Output, error) { + req, out := c.InputService4TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService4TestCaseOperation2WithContext is the same as InputService4TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService4TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService4ProtocolTest) InputService4TestCaseOperation2WithContext(ctx aws.Context, input *InputService4TestShapeInputService4TestCaseOperation2Input, opts ...request.Option) (*InputService4TestShapeInputService4TestCaseOperation2Output, error) { + req, out := c.InputService4TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService4TestShapeInputService4TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService4TestShapeInputService4TestCaseOperation2Input struct { + _ struct{} `type:"structure"` + + ListArg []*string `type:"list" flattened:"true"` + + NamedListArg []*string `locationNameList:"Foo" type:"list" flattened:"true"` + + ScalarArg *string `type:"string"` +} + +// SetListArg sets the ListArg field's value. +func (s *InputService4TestShapeInputService4TestCaseOperation2Input) SetListArg(v []*string) *InputService4TestShapeInputService4TestCaseOperation2Input { + s.ListArg = v + return s +} + +// SetNamedListArg sets the NamedListArg field's value. +func (s *InputService4TestShapeInputService4TestCaseOperation2Input) SetNamedListArg(v []*string) *InputService4TestShapeInputService4TestCaseOperation2Input { + s.NamedListArg = v + return s +} + +// SetScalarArg sets the ScalarArg field's value. +func (s *InputService4TestShapeInputService4TestCaseOperation2Input) SetScalarArg(v string) *InputService4TestShapeInputService4TestCaseOperation2Input { + s.ScalarArg = &v + return s +} + +type InputService4TestShapeInputService4TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +// InputService5ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService5ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService5ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService5ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService5ProtocolTest client from just a session. +// svc := inputservice5protocoltest.New(mySession) +// +// // Create a InputService5ProtocolTest client with additional configuration +// svc := inputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService5ProtocolTest { + c := p.ClientConfig("inputservice5protocoltest", cfgs...) + return newInputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService5ProtocolTest { + svc := &InputService5ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice5protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService5ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService5TestCaseOperation1 = "OperationName" + +// InputService5TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService5TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService5TestCaseOperation1 for more information on using the InputService5TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService5TestCaseOperation1Request method. +// req, resp := client.InputService5TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1Request(input *InputService5TestShapeInputService5TestCaseOperation1Input) (req *request.Request, output *InputService5TestShapeInputService5TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService5TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService5TestShapeInputService5TestCaseOperation1Input{} + } + + output = &InputService5TestShapeInputService5TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService5TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService5TestCaseOperation1 for usage and error information. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1(input *InputService5TestShapeInputService5TestCaseOperation1Input) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { + req, out := c.InputService5TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService5TestCaseOperation1WithContext is the same as InputService5TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService5TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService5ProtocolTest) InputService5TestCaseOperation1WithContext(ctx aws.Context, input *InputService5TestShapeInputService5TestCaseOperation1Input, opts ...request.Option) (*InputService5TestShapeInputService5TestCaseOperation1Output, error) { + req, out := c.InputService5TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService5TestShapeInputService5TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + MapArg map[string]*string `type:"map" flattened:"true"` +} + +// SetMapArg sets the MapArg field's value. +func (s *InputService5TestShapeInputService5TestCaseOperation1Input) SetMapArg(v map[string]*string) *InputService5TestShapeInputService5TestCaseOperation1Input { + s.MapArg = v + return s +} + +type InputService5TestShapeInputService5TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService6ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService6ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService6ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService6ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService6ProtocolTest client from just a session. +// svc := inputservice6protocoltest.New(mySession) +// +// // Create a InputService6ProtocolTest client with additional configuration +// svc := inputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService6ProtocolTest { + c := p.ClientConfig("inputservice6protocoltest", cfgs...) + return newInputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService6ProtocolTest { + svc := &InputService6ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice6protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService6ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService6TestCaseOperation1 = "OperationName" + +// InputService6TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService6TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService6TestCaseOperation1 for more information on using the InputService6TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService6TestCaseOperation1Request method. +// req, resp := client.InputService6TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService6ProtocolTest) InputService6TestCaseOperation1Request(input *InputService6TestShapeInputService6TestCaseOperation1Input) (req *request.Request, output *InputService6TestShapeInputService6TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService6TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService6TestShapeInputService6TestCaseOperation1Input{} + } + + output = &InputService6TestShapeInputService6TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService6TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService6TestCaseOperation1 for usage and error information. +func (c *InputService6ProtocolTest) InputService6TestCaseOperation1(input *InputService6TestShapeInputService6TestCaseOperation1Input) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { + req, out := c.InputService6TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService6TestCaseOperation1WithContext is the same as InputService6TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService6TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService6ProtocolTest) InputService6TestCaseOperation1WithContext(ctx aws.Context, input *InputService6TestShapeInputService6TestCaseOperation1Input, opts ...request.Option) (*InputService6TestShapeInputService6TestCaseOperation1Output, error) { + req, out := c.InputService6TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService6TestShapeInputService6TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + ListArg []*string `locationNameList:"item" type:"list"` +} + +// SetListArg sets the ListArg field's value. +func (s *InputService6TestShapeInputService6TestCaseOperation1Input) SetListArg(v []*string) *InputService6TestShapeInputService6TestCaseOperation1Input { + s.ListArg = v + return s +} + +type InputService6TestShapeInputService6TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService7ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService7ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService7ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService7ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService7ProtocolTest client from just a session. +// svc := inputservice7protocoltest.New(mySession) +// +// // Create a InputService7ProtocolTest client with additional configuration +// svc := inputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService7ProtocolTest { + c := p.ClientConfig("inputservice7protocoltest", cfgs...) + return newInputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService7ProtocolTest { + svc := &InputService7ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice7protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService7ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService7TestCaseOperation1 = "OperationName" + +// InputService7TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService7TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService7TestCaseOperation1 for more information on using the InputService7TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService7TestCaseOperation1Request method. +// req, resp := client.InputService7TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService7ProtocolTest) InputService7TestCaseOperation1Request(input *InputService7TestShapeInputService7TestCaseOperation1Input) (req *request.Request, output *InputService7TestShapeInputService7TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService7TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService7TestShapeInputService7TestCaseOperation1Input{} + } + + output = &InputService7TestShapeInputService7TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService7TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService7TestCaseOperation1 for usage and error information. +func (c *InputService7ProtocolTest) InputService7TestCaseOperation1(input *InputService7TestShapeInputService7TestCaseOperation1Input) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { + req, out := c.InputService7TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService7TestCaseOperation1WithContext is the same as InputService7TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService7TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService7ProtocolTest) InputService7TestCaseOperation1WithContext(ctx aws.Context, input *InputService7TestShapeInputService7TestCaseOperation1Input, opts ...request.Option) (*InputService7TestShapeInputService7TestCaseOperation1Output, error) { + req, out := c.InputService7TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService7TestShapeInputService7TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + ListArg []*string `locationNameList:"ListArgLocation" type:"list" flattened:"true"` + + ScalarArg *string `type:"string"` +} + +// SetListArg sets the ListArg field's value. +func (s *InputService7TestShapeInputService7TestCaseOperation1Input) SetListArg(v []*string) *InputService7TestShapeInputService7TestCaseOperation1Input { + s.ListArg = v + return s +} + +// SetScalarArg sets the ScalarArg field's value. +func (s *InputService7TestShapeInputService7TestCaseOperation1Input) SetScalarArg(v string) *InputService7TestShapeInputService7TestCaseOperation1Input { + s.ScalarArg = &v + return s +} + +type InputService7TestShapeInputService7TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService8ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService8ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService8ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService8ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService8ProtocolTest client from just a session. +// svc := inputservice8protocoltest.New(mySession) +// +// // Create a InputService8ProtocolTest client with additional configuration +// svc := inputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService8ProtocolTest { + c := p.ClientConfig("inputservice8protocoltest", cfgs...) + return newInputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService8ProtocolTest { + svc := &InputService8ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice8protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService8ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService8ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService8TestCaseOperation1 = "OperationName" + +// InputService8TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService8TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService8TestCaseOperation1 for more information on using the InputService8TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService8TestCaseOperation1Request method. +// req, resp := client.InputService8TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService8ProtocolTest) InputService8TestCaseOperation1Request(input *InputService8TestShapeInputService8TestCaseOperation1Input) (req *request.Request, output *InputService8TestShapeInputService8TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService8TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService8TestShapeInputService8TestCaseOperation1Input{} + } + + output = &InputService8TestShapeInputService8TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService8TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService8TestCaseOperation1 for usage and error information. +func (c *InputService8ProtocolTest) InputService8TestCaseOperation1(input *InputService8TestShapeInputService8TestCaseOperation1Input) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { + req, out := c.InputService8TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService8TestCaseOperation1WithContext is the same as InputService8TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService8TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService8ProtocolTest) InputService8TestCaseOperation1WithContext(ctx aws.Context, input *InputService8TestShapeInputService8TestCaseOperation1Input, opts ...request.Option) (*InputService8TestShapeInputService8TestCaseOperation1Output, error) { + req, out := c.InputService8TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService8TestShapeInputService8TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + MapArg map[string]*string `type:"map"` +} + +// SetMapArg sets the MapArg field's value. +func (s *InputService8TestShapeInputService8TestCaseOperation1Input) SetMapArg(v map[string]*string) *InputService8TestShapeInputService8TestCaseOperation1Input { + s.MapArg = v + return s +} + +type InputService8TestShapeInputService8TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService9ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService9ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService9ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService9ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService9ProtocolTest client from just a session. +// svc := inputservice9protocoltest.New(mySession) +// +// // Create a InputService9ProtocolTest client with additional configuration +// svc := inputservice9protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService9ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService9ProtocolTest { + c := p.ClientConfig("inputservice9protocoltest", cfgs...) + return newInputService9ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService9ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService9ProtocolTest { + svc := &InputService9ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice9protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService9ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService9ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService9TestCaseOperation1 = "OperationName" + +// InputService9TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService9TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService9TestCaseOperation1 for more information on using the InputService9TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService9TestCaseOperation1Request method. +// req, resp := client.InputService9TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService9ProtocolTest) InputService9TestCaseOperation1Request(input *InputService9TestShapeInputService9TestCaseOperation1Input) (req *request.Request, output *InputService9TestShapeInputService9TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService9TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService9TestShapeInputService9TestCaseOperation1Input{} + } + + output = &InputService9TestShapeInputService9TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService9TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService9TestCaseOperation1 for usage and error information. +func (c *InputService9ProtocolTest) InputService9TestCaseOperation1(input *InputService9TestShapeInputService9TestCaseOperation1Input) (*InputService9TestShapeInputService9TestCaseOperation1Output, error) { + req, out := c.InputService9TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService9TestCaseOperation1WithContext is the same as InputService9TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService9TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService9ProtocolTest) InputService9TestCaseOperation1WithContext(ctx aws.Context, input *InputService9TestShapeInputService9TestCaseOperation1Input, opts ...request.Option) (*InputService9TestShapeInputService9TestCaseOperation1Output, error) { + req, out := c.InputService9TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService9TestShapeInputService9TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + MapArg map[string]*string `locationNameKey:"TheKey" locationNameValue:"TheValue" type:"map"` +} + +// SetMapArg sets the MapArg field's value. +func (s *InputService9TestShapeInputService9TestCaseOperation1Input) SetMapArg(v map[string]*string) *InputService9TestShapeInputService9TestCaseOperation1Input { + s.MapArg = v + return s +} + +type InputService9TestShapeInputService9TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService10ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService10ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService10ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService10ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService10ProtocolTest client from just a session. +// svc := inputservice10protocoltest.New(mySession) +// +// // Create a InputService10ProtocolTest client with additional configuration +// svc := inputservice10protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService10ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService10ProtocolTest { + c := p.ClientConfig("inputservice10protocoltest", cfgs...) + return newInputService10ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService10ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService10ProtocolTest { + svc := &InputService10ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice10protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService10ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService10ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService10TestCaseOperation1 = "OperationName" + +// InputService10TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService10TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService10TestCaseOperation1 for more information on using the InputService10TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService10TestCaseOperation1Request method. +// req, resp := client.InputService10TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService10ProtocolTest) InputService10TestCaseOperation1Request(input *InputService10TestShapeInputService10TestCaseOperation1Input) (req *request.Request, output *InputService10TestShapeInputService10TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService10TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService10TestShapeInputService10TestCaseOperation1Input{} + } + + output = &InputService10TestShapeInputService10TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService10TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService10TestCaseOperation1 for usage and error information. +func (c *InputService10ProtocolTest) InputService10TestCaseOperation1(input *InputService10TestShapeInputService10TestCaseOperation1Input) (*InputService10TestShapeInputService10TestCaseOperation1Output, error) { + req, out := c.InputService10TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService10TestCaseOperation1WithContext is the same as InputService10TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService10TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService10ProtocolTest) InputService10TestCaseOperation1WithContext(ctx aws.Context, input *InputService10TestShapeInputService10TestCaseOperation1Input, opts ...request.Option) (*InputService10TestShapeInputService10TestCaseOperation1Output, error) { + req, out := c.InputService10TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService10TestShapeInputService10TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + // BlobArg is automatically base64 encoded/decoded by the SDK. + BlobArg []byte `type:"blob"` +} + +// SetBlobArg sets the BlobArg field's value. +func (s *InputService10TestShapeInputService10TestCaseOperation1Input) SetBlobArg(v []byte) *InputService10TestShapeInputService10TestCaseOperation1Input { + s.BlobArg = v + return s +} + +type InputService10TestShapeInputService10TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService11ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService11ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService11ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService11ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService11ProtocolTest client from just a session. +// svc := inputservice11protocoltest.New(mySession) +// +// // Create a InputService11ProtocolTest client with additional configuration +// svc := inputservice11protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService11ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService11ProtocolTest { + c := p.ClientConfig("inputservice11protocoltest", cfgs...) + return newInputService11ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService11ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService11ProtocolTest { + svc := &InputService11ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice11protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService11ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService11ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService11TestCaseOperation1 = "OperationName" + +// InputService11TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService11TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService11TestCaseOperation1 for more information on using the InputService11TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService11TestCaseOperation1Request method. +// req, resp := client.InputService11TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService11ProtocolTest) InputService11TestCaseOperation1Request(input *InputService11TestShapeInputService11TestCaseOperation1Input) (req *request.Request, output *InputService11TestShapeInputService11TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService11TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService11TestShapeInputService11TestCaseOperation1Input{} + } + + output = &InputService11TestShapeInputService11TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService11TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService11TestCaseOperation1 for usage and error information. +func (c *InputService11ProtocolTest) InputService11TestCaseOperation1(input *InputService11TestShapeInputService11TestCaseOperation1Input) (*InputService11TestShapeInputService11TestCaseOperation1Output, error) { + req, out := c.InputService11TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService11TestCaseOperation1WithContext is the same as InputService11TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService11TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService11ProtocolTest) InputService11TestCaseOperation1WithContext(ctx aws.Context, input *InputService11TestShapeInputService11TestCaseOperation1Input, opts ...request.Option) (*InputService11TestShapeInputService11TestCaseOperation1Output, error) { + req, out := c.InputService11TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService11TestShapeInputService11TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + BlobArgs [][]byte `type:"list" flattened:"true"` +} + +// SetBlobArgs sets the BlobArgs field's value. +func (s *InputService11TestShapeInputService11TestCaseOperation1Input) SetBlobArgs(v [][]byte) *InputService11TestShapeInputService11TestCaseOperation1Input { + s.BlobArgs = v + return s +} + +type InputService11TestShapeInputService11TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService12ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService12ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService12ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService12ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService12ProtocolTest client from just a session. +// svc := inputservice12protocoltest.New(mySession) +// +// // Create a InputService12ProtocolTest client with additional configuration +// svc := inputservice12protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService12ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService12ProtocolTest { + c := p.ClientConfig("inputservice12protocoltest", cfgs...) + return newInputService12ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService12ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService12ProtocolTest { + svc := &InputService12ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice12protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService12ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService12ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService12TestCaseOperation1 = "OperationName" + +// InputService12TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService12TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService12TestCaseOperation1 for more information on using the InputService12TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService12TestCaseOperation1Request method. +// req, resp := client.InputService12TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService12ProtocolTest) InputService12TestCaseOperation1Request(input *InputService12TestShapeInputService12TestCaseOperation1Input) (req *request.Request, output *InputService12TestShapeInputService12TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService12TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService12TestShapeInputService12TestCaseOperation1Input{} + } + + output = &InputService12TestShapeInputService12TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService12TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService12TestCaseOperation1 for usage and error information. +func (c *InputService12ProtocolTest) InputService12TestCaseOperation1(input *InputService12TestShapeInputService12TestCaseOperation1Input) (*InputService12TestShapeInputService12TestCaseOperation1Output, error) { + req, out := c.InputService12TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService12TestCaseOperation1WithContext is the same as InputService12TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService12TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService12ProtocolTest) InputService12TestCaseOperation1WithContext(ctx aws.Context, input *InputService12TestShapeInputService12TestCaseOperation1Input, opts ...request.Option) (*InputService12TestShapeInputService12TestCaseOperation1Output, error) { + req, out := c.InputService12TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService12TestShapeInputService12TestCaseOperation1Input struct { + _ struct{} `type:"structure"` + + TimeArg *time.Time `type:"timestamp" timestampFormat:"iso8601"` +} + +// SetTimeArg sets the TimeArg field's value. +func (s *InputService12TestShapeInputService12TestCaseOperation1Input) SetTimeArg(v time.Time) *InputService12TestShapeInputService12TestCaseOperation1Input { + s.TimeArg = &v + return s +} + +type InputService12TestShapeInputService12TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +// InputService13ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService13ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService13ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService13ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService13ProtocolTest client from just a session. +// svc := inputservice13protocoltest.New(mySession) +// +// // Create a InputService13ProtocolTest client with additional configuration +// svc := inputservice13protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService13ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService13ProtocolTest { + c := p.ClientConfig("inputservice13protocoltest", cfgs...) + return newInputService13ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService13ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService13ProtocolTest { + svc := &InputService13ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice13protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService13ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService13ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService13TestCaseOperation1 = "OperationName" + +// InputService13TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService13TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService13TestCaseOperation1 for more information on using the InputService13TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService13TestCaseOperation1Request method. +// req, resp := client.InputService13TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService13ProtocolTest) InputService13TestCaseOperation1Request(input *InputService13TestShapeInputService13TestCaseOperation6Input) (req *request.Request, output *InputService13TestShapeInputService13TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService13TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &InputService13TestShapeInputService13TestCaseOperation6Input{} + } + + output = &InputService13TestShapeInputService13TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService13TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService13TestCaseOperation1 for usage and error information. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation1(input *InputService13TestShapeInputService13TestCaseOperation6Input) (*InputService13TestShapeInputService13TestCaseOperation1Output, error) { + req, out := c.InputService13TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService13TestCaseOperation1WithContext is the same as InputService13TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService13TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation1WithContext(ctx aws.Context, input *InputService13TestShapeInputService13TestCaseOperation6Input, opts ...request.Option) (*InputService13TestShapeInputService13TestCaseOperation1Output, error) { + req, out := c.InputService13TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService13TestCaseOperation2 = "OperationName" + +// InputService13TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService13TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService13TestCaseOperation2 for more information on using the InputService13TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService13TestCaseOperation2Request method. +// req, resp := client.InputService13TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService13ProtocolTest) InputService13TestCaseOperation2Request(input *InputService13TestShapeInputService13TestCaseOperation6Input) (req *request.Request, output *InputService13TestShapeInputService13TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService13TestCaseOperation2, + HTTPPath: "/", + } + + if input == nil { + input = &InputService13TestShapeInputService13TestCaseOperation6Input{} + } + + output = &InputService13TestShapeInputService13TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService13TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService13TestCaseOperation2 for usage and error information. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation2(input *InputService13TestShapeInputService13TestCaseOperation6Input) (*InputService13TestShapeInputService13TestCaseOperation2Output, error) { + req, out := c.InputService13TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService13TestCaseOperation2WithContext is the same as InputService13TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService13TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation2WithContext(ctx aws.Context, input *InputService13TestShapeInputService13TestCaseOperation6Input, opts ...request.Option) (*InputService13TestShapeInputService13TestCaseOperation2Output, error) { + req, out := c.InputService13TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService13TestCaseOperation3 = "OperationName" + +// InputService13TestCaseOperation3Request generates a "aws/request.Request" representing the +// client's request for the InputService13TestCaseOperation3 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService13TestCaseOperation3 for more information on using the InputService13TestCaseOperation3 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService13TestCaseOperation3Request method. +// req, resp := client.InputService13TestCaseOperation3Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService13ProtocolTest) InputService13TestCaseOperation3Request(input *InputService13TestShapeInputService13TestCaseOperation6Input) (req *request.Request, output *InputService13TestShapeInputService13TestCaseOperation3Output) { + op := &request.Operation{ + Name: opInputService13TestCaseOperation3, + HTTPPath: "/", + } + + if input == nil { + input = &InputService13TestShapeInputService13TestCaseOperation6Input{} + } + + output = &InputService13TestShapeInputService13TestCaseOperation3Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService13TestCaseOperation3 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService13TestCaseOperation3 for usage and error information. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation3(input *InputService13TestShapeInputService13TestCaseOperation6Input) (*InputService13TestShapeInputService13TestCaseOperation3Output, error) { + req, out := c.InputService13TestCaseOperation3Request(input) + return out, req.Send() +} + +// InputService13TestCaseOperation3WithContext is the same as InputService13TestCaseOperation3 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService13TestCaseOperation3 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation3WithContext(ctx aws.Context, input *InputService13TestShapeInputService13TestCaseOperation6Input, opts ...request.Option) (*InputService13TestShapeInputService13TestCaseOperation3Output, error) { + req, out := c.InputService13TestCaseOperation3Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService13TestCaseOperation4 = "OperationName" + +// InputService13TestCaseOperation4Request generates a "aws/request.Request" representing the +// client's request for the InputService13TestCaseOperation4 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService13TestCaseOperation4 for more information on using the InputService13TestCaseOperation4 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService13TestCaseOperation4Request method. +// req, resp := client.InputService13TestCaseOperation4Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService13ProtocolTest) InputService13TestCaseOperation4Request(input *InputService13TestShapeInputService13TestCaseOperation6Input) (req *request.Request, output *InputService13TestShapeInputService13TestCaseOperation4Output) { + op := &request.Operation{ + Name: opInputService13TestCaseOperation4, + HTTPPath: "/", + } + + if input == nil { + input = &InputService13TestShapeInputService13TestCaseOperation6Input{} + } + + output = &InputService13TestShapeInputService13TestCaseOperation4Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService13TestCaseOperation4 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService13TestCaseOperation4 for usage and error information. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation4(input *InputService13TestShapeInputService13TestCaseOperation6Input) (*InputService13TestShapeInputService13TestCaseOperation4Output, error) { + req, out := c.InputService13TestCaseOperation4Request(input) + return out, req.Send() +} + +// InputService13TestCaseOperation4WithContext is the same as InputService13TestCaseOperation4 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService13TestCaseOperation4 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation4WithContext(ctx aws.Context, input *InputService13TestShapeInputService13TestCaseOperation6Input, opts ...request.Option) (*InputService13TestShapeInputService13TestCaseOperation4Output, error) { + req, out := c.InputService13TestCaseOperation4Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService13TestCaseOperation5 = "OperationName" + +// InputService13TestCaseOperation5Request generates a "aws/request.Request" representing the +// client's request for the InputService13TestCaseOperation5 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService13TestCaseOperation5 for more information on using the InputService13TestCaseOperation5 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService13TestCaseOperation5Request method. +// req, resp := client.InputService13TestCaseOperation5Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService13ProtocolTest) InputService13TestCaseOperation5Request(input *InputService13TestShapeInputService13TestCaseOperation6Input) (req *request.Request, output *InputService13TestShapeInputService13TestCaseOperation5Output) { + op := &request.Operation{ + Name: opInputService13TestCaseOperation5, + HTTPPath: "/", + } + + if input == nil { + input = &InputService13TestShapeInputService13TestCaseOperation6Input{} + } + + output = &InputService13TestShapeInputService13TestCaseOperation5Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService13TestCaseOperation5 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService13TestCaseOperation5 for usage and error information. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation5(input *InputService13TestShapeInputService13TestCaseOperation6Input) (*InputService13TestShapeInputService13TestCaseOperation5Output, error) { + req, out := c.InputService13TestCaseOperation5Request(input) + return out, req.Send() +} + +// InputService13TestCaseOperation5WithContext is the same as InputService13TestCaseOperation5 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService13TestCaseOperation5 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation5WithContext(ctx aws.Context, input *InputService13TestShapeInputService13TestCaseOperation6Input, opts ...request.Option) (*InputService13TestShapeInputService13TestCaseOperation5Output, error) { + req, out := c.InputService13TestCaseOperation5Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService13TestCaseOperation6 = "OperationName" + +// InputService13TestCaseOperation6Request generates a "aws/request.Request" representing the +// client's request for the InputService13TestCaseOperation6 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService13TestCaseOperation6 for more information on using the InputService13TestCaseOperation6 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService13TestCaseOperation6Request method. +// req, resp := client.InputService13TestCaseOperation6Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService13ProtocolTest) InputService13TestCaseOperation6Request(input *InputService13TestShapeInputService13TestCaseOperation6Input) (req *request.Request, output *InputService13TestShapeInputService13TestCaseOperation6Output) { + op := &request.Operation{ + Name: opInputService13TestCaseOperation6, + HTTPPath: "/", + } + + if input == nil { + input = &InputService13TestShapeInputService13TestCaseOperation6Input{} + } + + output = &InputService13TestShapeInputService13TestCaseOperation6Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService13TestCaseOperation6 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService13TestCaseOperation6 for usage and error information. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation6(input *InputService13TestShapeInputService13TestCaseOperation6Input) (*InputService13TestShapeInputService13TestCaseOperation6Output, error) { + req, out := c.InputService13TestCaseOperation6Request(input) + return out, req.Send() +} + +// InputService13TestCaseOperation6WithContext is the same as InputService13TestCaseOperation6 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService13TestCaseOperation6 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService13ProtocolTest) InputService13TestCaseOperation6WithContext(ctx aws.Context, input *InputService13TestShapeInputService13TestCaseOperation6Input, opts ...request.Option) (*InputService13TestShapeInputService13TestCaseOperation6Output, error) { + req, out := c.InputService13TestCaseOperation6Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService13TestShapeInputService13TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService13TestShapeInputService13TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +type InputService13TestShapeInputService13TestCaseOperation3Output struct { + _ struct{} `type:"structure"` +} + +type InputService13TestShapeInputService13TestCaseOperation4Output struct { + _ struct{} `type:"structure"` +} + +type InputService13TestShapeInputService13TestCaseOperation5Output struct { + _ struct{} `type:"structure"` +} + +type InputService13TestShapeInputService13TestCaseOperation6Input struct { + _ struct{} `type:"structure"` + + RecursiveStruct *InputService13TestShapeRecursiveStructType `type:"structure"` +} + +// SetRecursiveStruct sets the RecursiveStruct field's value. +func (s *InputService13TestShapeInputService13TestCaseOperation6Input) SetRecursiveStruct(v *InputService13TestShapeRecursiveStructType) *InputService13TestShapeInputService13TestCaseOperation6Input { + s.RecursiveStruct = v + return s +} + +type InputService13TestShapeInputService13TestCaseOperation6Output struct { + _ struct{} `type:"structure"` +} + +type InputService13TestShapeRecursiveStructType struct { + _ struct{} `type:"structure"` + + NoRecurse *string `type:"string"` + + RecursiveList []*InputService13TestShapeRecursiveStructType `type:"list"` + + RecursiveMap map[string]*InputService13TestShapeRecursiveStructType `type:"map"` + + RecursiveStruct *InputService13TestShapeRecursiveStructType `type:"structure"` +} + +// SetNoRecurse sets the NoRecurse field's value. +func (s *InputService13TestShapeRecursiveStructType) SetNoRecurse(v string) *InputService13TestShapeRecursiveStructType { + s.NoRecurse = &v + return s +} + +// SetRecursiveList sets the RecursiveList field's value. +func (s *InputService13TestShapeRecursiveStructType) SetRecursiveList(v []*InputService13TestShapeRecursiveStructType) *InputService13TestShapeRecursiveStructType { + s.RecursiveList = v + return s +} + +// SetRecursiveMap sets the RecursiveMap field's value. +func (s *InputService13TestShapeRecursiveStructType) SetRecursiveMap(v map[string]*InputService13TestShapeRecursiveStructType) *InputService13TestShapeRecursiveStructType { + s.RecursiveMap = v + return s +} + +// SetRecursiveStruct sets the RecursiveStruct field's value. +func (s *InputService13TestShapeRecursiveStructType) SetRecursiveStruct(v *InputService13TestShapeRecursiveStructType) *InputService13TestShapeRecursiveStructType { + s.RecursiveStruct = v + return s +} + +// InputService14ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService14ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService14ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService14ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService14ProtocolTest client from just a session. +// svc := inputservice14protocoltest.New(mySession) +// +// // Create a InputService14ProtocolTest client with additional configuration +// svc := inputservice14protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService14ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService14ProtocolTest { + c := p.ClientConfig("inputservice14protocoltest", cfgs...) + return newInputService14ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService14ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService14ProtocolTest { + svc := &InputService14ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice14protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService14ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService14ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService14TestCaseOperation1 = "OperationName" + +// InputService14TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService14TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService14TestCaseOperation1 for more information on using the InputService14TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService14TestCaseOperation1Request method. +// req, resp := client.InputService14TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService14ProtocolTest) InputService14TestCaseOperation1Request(input *InputService14TestShapeInputService14TestCaseOperation2Input) (req *request.Request, output *InputService14TestShapeInputService14TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService14TestCaseOperation1, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService14TestShapeInputService14TestCaseOperation2Input{} + } + + output = &InputService14TestShapeInputService14TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService14TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService14TestCaseOperation1 for usage and error information. +func (c *InputService14ProtocolTest) InputService14TestCaseOperation1(input *InputService14TestShapeInputService14TestCaseOperation2Input) (*InputService14TestShapeInputService14TestCaseOperation1Output, error) { + req, out := c.InputService14TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService14TestCaseOperation1WithContext is the same as InputService14TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService14TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService14ProtocolTest) InputService14TestCaseOperation1WithContext(ctx aws.Context, input *InputService14TestShapeInputService14TestCaseOperation2Input, opts ...request.Option) (*InputService14TestShapeInputService14TestCaseOperation1Output, error) { + req, out := c.InputService14TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService14TestCaseOperation2 = "OperationName" + +// InputService14TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService14TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService14TestCaseOperation2 for more information on using the InputService14TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService14TestCaseOperation2Request method. +// req, resp := client.InputService14TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService14ProtocolTest) InputService14TestCaseOperation2Request(input *InputService14TestShapeInputService14TestCaseOperation2Input) (req *request.Request, output *InputService14TestShapeInputService14TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService14TestCaseOperation2, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService14TestShapeInputService14TestCaseOperation2Input{} + } + + output = &InputService14TestShapeInputService14TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService14TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService14TestCaseOperation2 for usage and error information. +func (c *InputService14ProtocolTest) InputService14TestCaseOperation2(input *InputService14TestShapeInputService14TestCaseOperation2Input) (*InputService14TestShapeInputService14TestCaseOperation2Output, error) { + req, out := c.InputService14TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService14TestCaseOperation2WithContext is the same as InputService14TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService14TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService14ProtocolTest) InputService14TestCaseOperation2WithContext(ctx aws.Context, input *InputService14TestShapeInputService14TestCaseOperation2Input, opts ...request.Option) (*InputService14TestShapeInputService14TestCaseOperation2Output, error) { + req, out := c.InputService14TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService14TestShapeInputService14TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService14TestShapeInputService14TestCaseOperation2Input struct { + _ struct{} `type:"structure"` + + Token *string `type:"string" idempotencyToken:"true"` +} + +// SetToken sets the Token field's value. +func (s *InputService14TestShapeInputService14TestCaseOperation2Input) SetToken(v string) *InputService14TestShapeInputService14TestCaseOperation2Input { + s.Token = &v + return s +} + +type InputService14TestShapeInputService14TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +// InputService15ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// InputService15ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type InputService15ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the InputService15ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a InputService15ProtocolTest client from just a session. +// svc := inputservice15protocoltest.New(mySession) +// +// // Create a InputService15ProtocolTest client with additional configuration +// svc := inputservice15protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewInputService15ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService15ProtocolTest { + c := p.ClientConfig("inputservice15protocoltest", cfgs...) + return newInputService15ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newInputService15ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *InputService15ProtocolTest { + svc := &InputService15ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "inputservice15protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2014-01-01", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a InputService15ProtocolTest operation and runs any +// custom request initialization. +func (c *InputService15ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opInputService15TestCaseOperation1 = "OperationName" + +// InputService15TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the InputService15TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService15TestCaseOperation1 for more information on using the InputService15TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService15TestCaseOperation1Request method. +// req, resp := client.InputService15TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService15ProtocolTest) InputService15TestCaseOperation1Request(input *InputService15TestShapeInputService15TestCaseOperation3Input) (req *request.Request, output *InputService15TestShapeInputService15TestCaseOperation1Output) { + op := &request.Operation{ + Name: opInputService15TestCaseOperation1, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService15TestShapeInputService15TestCaseOperation3Input{} + } + + output = &InputService15TestShapeInputService15TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService15TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService15TestCaseOperation1 for usage and error information. +func (c *InputService15ProtocolTest) InputService15TestCaseOperation1(input *InputService15TestShapeInputService15TestCaseOperation3Input) (*InputService15TestShapeInputService15TestCaseOperation1Output, error) { + req, out := c.InputService15TestCaseOperation1Request(input) + return out, req.Send() +} + +// InputService15TestCaseOperation1WithContext is the same as InputService15TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService15TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService15ProtocolTest) InputService15TestCaseOperation1WithContext(ctx aws.Context, input *InputService15TestShapeInputService15TestCaseOperation3Input, opts ...request.Option) (*InputService15TestShapeInputService15TestCaseOperation1Output, error) { + req, out := c.InputService15TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService15TestCaseOperation2 = "OperationName" + +// InputService15TestCaseOperation2Request generates a "aws/request.Request" representing the +// client's request for the InputService15TestCaseOperation2 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService15TestCaseOperation2 for more information on using the InputService15TestCaseOperation2 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService15TestCaseOperation2Request method. +// req, resp := client.InputService15TestCaseOperation2Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService15ProtocolTest) InputService15TestCaseOperation2Request(input *InputService15TestShapeInputService15TestCaseOperation3Input) (req *request.Request, output *InputService15TestShapeInputService15TestCaseOperation2Output) { + op := &request.Operation{ + Name: opInputService15TestCaseOperation2, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService15TestShapeInputService15TestCaseOperation3Input{} + } + + output = &InputService15TestShapeInputService15TestCaseOperation2Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService15TestCaseOperation2 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService15TestCaseOperation2 for usage and error information. +func (c *InputService15ProtocolTest) InputService15TestCaseOperation2(input *InputService15TestShapeInputService15TestCaseOperation3Input) (*InputService15TestShapeInputService15TestCaseOperation2Output, error) { + req, out := c.InputService15TestCaseOperation2Request(input) + return out, req.Send() +} + +// InputService15TestCaseOperation2WithContext is the same as InputService15TestCaseOperation2 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService15TestCaseOperation2 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService15ProtocolTest) InputService15TestCaseOperation2WithContext(ctx aws.Context, input *InputService15TestShapeInputService15TestCaseOperation3Input, opts ...request.Option) (*InputService15TestShapeInputService15TestCaseOperation2Output, error) { + req, out := c.InputService15TestCaseOperation2Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opInputService15TestCaseOperation3 = "OperationName" + +// InputService15TestCaseOperation3Request generates a "aws/request.Request" representing the +// client's request for the InputService15TestCaseOperation3 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See InputService15TestCaseOperation3 for more information on using the InputService15TestCaseOperation3 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the InputService15TestCaseOperation3Request method. +// req, resp := client.InputService15TestCaseOperation3Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *InputService15ProtocolTest) InputService15TestCaseOperation3Request(input *InputService15TestShapeInputService15TestCaseOperation3Input) (req *request.Request, output *InputService15TestShapeInputService15TestCaseOperation3Output) { + op := &request.Operation{ + Name: opInputService15TestCaseOperation3, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &InputService15TestShapeInputService15TestCaseOperation3Input{} + } + + output = &InputService15TestShapeInputService15TestCaseOperation3Output{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(query.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// InputService15TestCaseOperation3 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation InputService15TestCaseOperation3 for usage and error information. +func (c *InputService15ProtocolTest) InputService15TestCaseOperation3(input *InputService15TestShapeInputService15TestCaseOperation3Input) (*InputService15TestShapeInputService15TestCaseOperation3Output, error) { + req, out := c.InputService15TestCaseOperation3Request(input) + return out, req.Send() +} + +// InputService15TestCaseOperation3WithContext is the same as InputService15TestCaseOperation3 with the addition of +// the ability to pass a context and additional request options. +// +// See InputService15TestCaseOperation3 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *InputService15ProtocolTest) InputService15TestCaseOperation3WithContext(ctx aws.Context, input *InputService15TestShapeInputService15TestCaseOperation3Input, opts ...request.Option) (*InputService15TestShapeInputService15TestCaseOperation3Output, error) { + req, out := c.InputService15TestCaseOperation3Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type InputService15TestShapeInputService15TestCaseOperation1Output struct { + _ struct{} `type:"structure"` +} + +type InputService15TestShapeInputService15TestCaseOperation2Output struct { + _ struct{} `type:"structure"` +} + +type InputService15TestShapeInputService15TestCaseOperation3Input struct { + _ struct{} `type:"structure"` + + FooEnum *string `type:"string" enum:"InputService15TestShapeEnumType"` + + ListEnums []*string `type:"list"` +} + +// SetFooEnum sets the FooEnum field's value. +func (s *InputService15TestShapeInputService15TestCaseOperation3Input) SetFooEnum(v string) *InputService15TestShapeInputService15TestCaseOperation3Input { + s.FooEnum = &v + return s +} + +// SetListEnums sets the ListEnums field's value. +func (s *InputService15TestShapeInputService15TestCaseOperation3Input) SetListEnums(v []*string) *InputService15TestShapeInputService15TestCaseOperation3Input { + s.ListEnums = v + return s +} + +type InputService15TestShapeInputService15TestCaseOperation3Output struct { + _ struct{} `type:"structure"` +} + +const ( + // EnumTypeFoo is a InputService15TestShapeEnumType enum value + EnumTypeFoo = "foo" + + // EnumTypeBar is a InputService15TestShapeEnumType enum value + EnumTypeBar = "bar" +) + +// +// Tests begin here +// + +func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) { + svc := NewInputService1ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService1TestShapeInputService1TestCaseOperation3Input{ + Bar: aws.String("val2"), + Foo: aws.String("val1"), + } + req, _ := svc.InputService1TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&Bar=val2&Foo=val1&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService1ProtocolTestScalarMembersCase2(t *testing.T) { + svc := NewInputService1ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService1TestShapeInputService1TestCaseOperation3Input{ + Baz: aws.Bool(true), + } + req, _ := svc.InputService1TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&Baz=true&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService1ProtocolTestScalarMembersCase3(t *testing.T) { + svc := NewInputService1ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService1TestShapeInputService1TestCaseOperation3Input{ + Baz: aws.Bool(false), + } + req, _ := svc.InputService1TestCaseOperation3Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&Baz=false&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService2ProtocolTestNestedStructureMembersCase1(t *testing.T) { + svc := NewInputService2ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService2TestShapeInputService2TestCaseOperation1Input{ + StructArg: &InputService2TestShapeStructType{ + ScalarArg: aws.String("foo"), + }, + } + req, _ := svc.InputService2TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&StructArg.ScalarArg=foo&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService3ProtocolTestListTypesCase1(t *testing.T) { + svc := NewInputService3ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService3TestShapeInputService3TestCaseOperation2Input{ + ListArg: []*string{ + aws.String("foo"), + aws.String("bar"), + aws.String("baz"), + }, + } + req, _ := svc.InputService3TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&ListArg.member.1=foo&ListArg.member.2=bar&ListArg.member.3=baz&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService3ProtocolTestListTypesCase2(t *testing.T) { + svc := NewInputService3ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService3TestShapeInputService3TestCaseOperation2Input{ + ListArg: []*string{}, + } + req, _ := svc.InputService3TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&ListArg=&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService4ProtocolTestFlattenedListCase1(t *testing.T) { + svc := NewInputService4ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService4TestShapeInputService4TestCaseOperation2Input{ + ListArg: []*string{ + aws.String("a"), + aws.String("b"), + aws.String("c"), + }, + ScalarArg: aws.String("foo"), + } + req, _ := svc.InputService4TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&ListArg.1=a&ListArg.2=b&ListArg.3=c&ScalarArg=foo&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService4ProtocolTestFlattenedListCase2(t *testing.T) { + svc := NewInputService4ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService4TestShapeInputService4TestCaseOperation2Input{ + NamedListArg: []*string{ + aws.String("a"), + }, + } + req, _ := svc.InputService4TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&Foo.1=a&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService5ProtocolTestSerializeFlattenedMapTypeCase1(t *testing.T) { + svc := NewInputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService5TestShapeInputService5TestCaseOperation1Input{ + MapArg: map[string]*string{ + "key1": aws.String("val1"), + "key2": aws.String("val2"), + }, + } + req, _ := svc.InputService5TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&MapArg.1.key=key1&MapArg.1.value=val1&MapArg.2.key=key2&MapArg.2.value=val2&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService6ProtocolTestNonFlattenedListWithLocationNameCase1(t *testing.T) { + svc := NewInputService6ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService6TestShapeInputService6TestCaseOperation1Input{ + ListArg: []*string{ + aws.String("a"), + aws.String("b"), + aws.String("c"), + }, + } + req, _ := svc.InputService6TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&ListArg.item.1=a&ListArg.item.2=b&ListArg.item.3=c&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService7ProtocolTestFlattenedListWithLocationNameCase1(t *testing.T) { + svc := NewInputService7ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService7TestShapeInputService7TestCaseOperation1Input{ + ListArg: []*string{ + aws.String("a"), + aws.String("b"), + aws.String("c"), + }, + ScalarArg: aws.String("foo"), + } + req, _ := svc.InputService7TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&ListArgLocation.1=a&ListArgLocation.2=b&ListArgLocation.3=c&ScalarArg=foo&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService8ProtocolTestSerializeMapTypeCase1(t *testing.T) { + svc := NewInputService8ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService8TestShapeInputService8TestCaseOperation1Input{ + MapArg: map[string]*string{ + "key1": aws.String("val1"), + "key2": aws.String("val2"), + }, + } + req, _ := svc.InputService8TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&MapArg.entry.1.key=key1&MapArg.entry.1.value=val1&MapArg.entry.2.key=key2&MapArg.entry.2.value=val2&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService9ProtocolTestSerializeMapTypeWithLocationNameCase1(t *testing.T) { + svc := NewInputService9ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService9TestShapeInputService9TestCaseOperation1Input{ + MapArg: map[string]*string{ + "key1": aws.String("val1"), + "key2": aws.String("val2"), + }, + } + req, _ := svc.InputService9TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&MapArg.entry.1.TheKey=key1&MapArg.entry.1.TheValue=val1&MapArg.entry.2.TheKey=key2&MapArg.entry.2.TheValue=val2&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService10ProtocolTestBase64EncodedBlobsCase1(t *testing.T) { + svc := NewInputService10ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService10TestShapeInputService10TestCaseOperation1Input{ + BlobArg: []byte("foo"), + } + req, _ := svc.InputService10TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&BlobArg=Zm9v&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService11ProtocolTestBase64EncodedBlobsNestedCase1(t *testing.T) { + svc := NewInputService11ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService11TestShapeInputService11TestCaseOperation1Input{ + BlobArgs: [][]byte{ + []byte("foo"), + }, + } + req, _ := svc.InputService11TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&BlobArgs.1=Zm9v&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService12ProtocolTestTimestampValuesCase1(t *testing.T) { + svc := NewInputService12ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService12TestShapeInputService12TestCaseOperation1Input{ + TimeArg: aws.Time(time.Unix(1422172800, 0)), + } + req, _ := svc.InputService12TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&TimeArg=2015-01-25T08%3A00%3A00Z&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService13ProtocolTestRecursiveShapesCase1(t *testing.T) { + svc := NewInputService13ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService13TestShapeInputService13TestCaseOperation6Input{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + } + req, _ := svc.InputService13TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.NoRecurse=foo&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService13ProtocolTestRecursiveShapesCase2(t *testing.T) { + svc := NewInputService13ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService13TestShapeInputService13TestCaseOperation6Input{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + }, + } + req, _ := svc.InputService13TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveStruct.NoRecurse=foo&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService13ProtocolTestRecursiveShapesCase3(t *testing.T) { + svc := NewInputService13ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService13TestShapeInputService13TestCaseOperation6Input{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + NoRecurse: aws.String("foo"), + }, + }, + }, + }, + } + req, _ := svc.InputService13TestCaseOperation3Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveStruct.RecursiveStruct.RecursiveStruct.NoRecurse=foo&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService13ProtocolTestRecursiveShapesCase4(t *testing.T) { + svc := NewInputService13ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService13TestShapeInputService13TestCaseOperation6Input{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + RecursiveList: []*InputService13TestShapeRecursiveStructType{ + { + NoRecurse: aws.String("foo"), + }, + { + NoRecurse: aws.String("bar"), + }, + }, + }, + } + req, _ := svc.InputService13TestCaseOperation4Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveList.member.1.NoRecurse=foo&RecursiveStruct.RecursiveList.member.2.NoRecurse=bar&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService13ProtocolTestRecursiveShapesCase5(t *testing.T) { + svc := NewInputService13ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService13TestShapeInputService13TestCaseOperation6Input{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + RecursiveList: []*InputService13TestShapeRecursiveStructType{ + { + NoRecurse: aws.String("foo"), + }, + { + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + NoRecurse: aws.String("bar"), + }, + }, + }, + }, + } + req, _ := svc.InputService13TestCaseOperation5Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveList.member.1.NoRecurse=foo&RecursiveStruct.RecursiveList.member.2.RecursiveStruct.NoRecurse=bar&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService13ProtocolTestRecursiveShapesCase6(t *testing.T) { + svc := NewInputService13ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService13TestShapeInputService13TestCaseOperation6Input{ + RecursiveStruct: &InputService13TestShapeRecursiveStructType{ + RecursiveMap: map[string]*InputService13TestShapeRecursiveStructType{ + "bar": { + NoRecurse: aws.String("bar"), + }, + "foo": { + NoRecurse: aws.String("foo"), + }, + }, + }, + } + req, _ := svc.InputService13TestCaseOperation6Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&RecursiveStruct.RecursiveMap.entry.1.key=foo&RecursiveStruct.RecursiveMap.entry.1.value.NoRecurse=foo&RecursiveStruct.RecursiveMap.entry.2.key=bar&RecursiveStruct.RecursiveMap.entry.2.value.NoRecurse=bar&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService14ProtocolTestIdempotencyTokenAutoFillCase1(t *testing.T) { + svc := NewInputService14ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService14TestShapeInputService14TestCaseOperation2Input{ + Token: aws.String("abc123"), + } + req, _ := svc.InputService14TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&Token=abc123&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService14ProtocolTestIdempotencyTokenAutoFillCase2(t *testing.T) { + svc := NewInputService14ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService14TestShapeInputService14TestCaseOperation2Input{} + req, _ := svc.InputService14TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&Token=00000000-0000-4000-8000-000000000000&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService15ProtocolTestEnumCase1(t *testing.T) { + svc := NewInputService15ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService15TestShapeInputService15TestCaseOperation3Input{ + FooEnum: aws.String("foo"), + ListEnums: []*string{ + aws.String("foo"), + aws.String(""), + aws.String("bar"), + }, + } + req, _ := svc.InputService15TestCaseOperation1Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&FooEnum=foo&ListEnums.member.1=foo&ListEnums.member.2=&ListEnums.member.3=bar&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService15ProtocolTestEnumCase2(t *testing.T) { + svc := NewInputService15ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService15TestShapeInputService15TestCaseOperation3Input{ + FooEnum: aws.String("foo"), + } + req, _ := svc.InputService15TestCaseOperation2Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&FooEnum=foo&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} + +func TestInputService15ProtocolTestEnumCase3(t *testing.T) { + svc := NewInputService15ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + input := &InputService15TestShapeInputService15TestCaseOperation3Input{} + req, _ := svc.InputService15TestCaseOperation3Request(input) + r := req.HTTPRequest + + // build request + query.Build(req) + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } + + // assert body + if r.Body == nil { + t.Errorf("expect body not to be nil") + } + body, _ := ioutil.ReadAll(r.Body) + awstesting.AssertQuery(t, `Action=OperationName&Version=2014-01-01`, util.Trim(string(body))) + + // assert URL + awstesting.AssertURL(t, "https://test/", r.URL.String()) + + // assert headers + +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go new file mode 100644 index 0000000..5ce9cba --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go @@ -0,0 +1,241 @@ +package queryutil + +import ( + "encoding/base64" + "fmt" + "net/url" + "reflect" + "sort" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/private/protocol" +) + +// Parse parses an object i and fills a url.Values object. The isEC2 flag +// indicates if this is the EC2 Query sub-protocol. +func Parse(body url.Values, i interface{}, isEC2 bool) error { + q := queryParser{isEC2: isEC2} + return q.parseValue(body, reflect.ValueOf(i), "", "") +} + +func elemOf(value reflect.Value) reflect.Value { + for value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value +} + +type queryParser struct { + isEC2 bool +} + +func (q *queryParser) parseValue(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { + value = elemOf(value) + + // no need to handle zero values + if !value.IsValid() { + return nil + } + + t := tag.Get("type") + if t == "" { + switch value.Kind() { + case reflect.Struct: + t = "structure" + case reflect.Slice: + t = "list" + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + return q.parseStruct(v, value, prefix) + case "list": + return q.parseList(v, value, prefix, tag) + case "map": + return q.parseMap(v, value, prefix, tag) + default: + return q.parseScalar(v, value, prefix, tag) + } +} + +func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix string) error { + if !value.IsValid() { + return nil + } + + t := value.Type() + for i := 0; i < value.NumField(); i++ { + elemValue := elemOf(value.Field(i)) + field := t.Field(i) + + if field.PkgPath != "" { + continue // ignore unexported fields + } + if field.Tag.Get("ignore") != "" { + continue + } + + if protocol.CanSetIdempotencyToken(value.Field(i), field) { + token := protocol.GetIdempotencyToken() + elemValue = reflect.ValueOf(token) + } + + var name string + if q.isEC2 { + name = field.Tag.Get("queryName") + } + if name == "" { + if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" { + name = field.Tag.Get("locationNameList") + } else if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + if name != "" && q.isEC2 { + name = strings.ToUpper(name[0:1]) + name[1:] + } + } + if name == "" { + name = field.Name + } + + if prefix != "" { + name = prefix + "." + name + } + + if err := q.parseValue(v, elemValue, name, field.Tag); err != nil { + return err + } + } + return nil +} + +func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { + // If it's empty, generate an empty value + if !value.IsNil() && value.Len() == 0 { + v.Set(prefix, "") + return nil + } + + if _, ok := value.Interface().([]byte); ok { + return q.parseScalar(v, value, prefix, tag) + } + + // check for unflattened list member + if !q.isEC2 && tag.Get("flattened") == "" { + if listName := tag.Get("locationNameList"); listName == "" { + prefix += ".member" + } else { + prefix += "." + listName + } + } + + for i := 0; i < value.Len(); i++ { + slicePrefix := prefix + if slicePrefix == "" { + slicePrefix = strconv.Itoa(i + 1) + } else { + slicePrefix = slicePrefix + "." + strconv.Itoa(i+1) + } + if err := q.parseValue(v, value.Index(i), slicePrefix, ""); err != nil { + return err + } + } + return nil +} + +func (q *queryParser) parseMap(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { + // If it's empty, generate an empty value + if !value.IsNil() && value.Len() == 0 { + v.Set(prefix, "") + return nil + } + + // check for unflattened list member + if !q.isEC2 && tag.Get("flattened") == "" { + prefix += ".entry" + } + + // sort keys for improved serialization consistency. + // this is not strictly necessary for protocol support. + mapKeyValues := value.MapKeys() + mapKeys := map[string]reflect.Value{} + mapKeyNames := make([]string, len(mapKeyValues)) + for i, mapKey := range mapKeyValues { + name := mapKey.String() + mapKeys[name] = mapKey + mapKeyNames[i] = name + } + sort.Strings(mapKeyNames) + + for i, mapKeyName := range mapKeyNames { + mapKey := mapKeys[mapKeyName] + mapValue := value.MapIndex(mapKey) + + kname := tag.Get("locationNameKey") + if kname == "" { + kname = "key" + } + vname := tag.Get("locationNameValue") + if vname == "" { + vname = "value" + } + + // serialize key + var keyName string + if prefix == "" { + keyName = strconv.Itoa(i+1) + "." + kname + } else { + keyName = prefix + "." + strconv.Itoa(i+1) + "." + kname + } + + if err := q.parseValue(v, mapKey, keyName, ""); err != nil { + return err + } + + // serialize value + var valueName string + if prefix == "" { + valueName = strconv.Itoa(i+1) + "." + vname + } else { + valueName = prefix + "." + strconv.Itoa(i+1) + "." + vname + } + + if err := q.parseValue(v, mapValue, valueName, ""); err != nil { + return err + } + } + + return nil +} + +func (q *queryParser) parseScalar(v url.Values, r reflect.Value, name string, tag reflect.StructTag) error { + switch value := r.Interface().(type) { + case string: + v.Set(name, value) + case []byte: + if !r.IsNil() { + v.Set(name, base64.StdEncoding.EncodeToString(value)) + } + case bool: + v.Set(name, strconv.FormatBool(value)) + case int64: + v.Set(name, strconv.FormatInt(value, 10)) + case int: + v.Set(name, strconv.Itoa(value)) + case float64: + v.Set(name, strconv.FormatFloat(value, 'f', -1, 64)) + case float32: + v.Set(name, strconv.FormatFloat(float64(value), 'f', -1, 32)) + case time.Time: + const ISO8601UTC = "2006-01-02T15:04:05Z" + v.Set(name, value.UTC().Format(ISO8601UTC)) + default: + return fmt.Errorf("unsupported value for param %s: %v (%s)", name, r.Interface(), r.Type().Name()) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go new file mode 100644 index 0000000..e0f4d5a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go @@ -0,0 +1,35 @@ +package query + +//go:generate go run -tags codegen ../../../models/protocol_tests/generate.go ../../../models/protocol_tests/output/query.json unmarshal_test.go + +import ( + "encoding/xml" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" +) + +// UnmarshalHandler is a named request handler for unmarshaling query protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.query.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling query protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalMeta", Fn: UnmarshalMeta} + +// Unmarshal unmarshals a response for an AWS Query service. +func Unmarshal(r *request.Request) { + defer r.HTTPResponse.Body.Close() + if r.DataFilled() { + decoder := xml.NewDecoder(r.HTTPResponse.Body) + err := xmlutil.UnmarshalXML(r.Data, decoder, r.Operation.Name+"Result") + if err != nil { + r.Error = awserr.New("SerializationError", "failed decoding Query response", err) + return + } + } +} + +// UnmarshalMeta unmarshals header response values for an AWS Query service. +func UnmarshalMeta(r *request.Request) { + r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid") +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go new file mode 100644 index 0000000..f214296 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go @@ -0,0 +1,66 @@ +package query + +import ( + "encoding/xml" + "io/ioutil" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" +) + +type xmlErrorResponse struct { + XMLName xml.Name `xml:"ErrorResponse"` + Code string `xml:"Error>Code"` + Message string `xml:"Error>Message"` + RequestID string `xml:"RequestId"` +} + +type xmlServiceUnavailableResponse struct { + XMLName xml.Name `xml:"ServiceUnavailableException"` +} + +// UnmarshalErrorHandler is a name request handler to unmarshal request errors +var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalError", Fn: UnmarshalError} + +// UnmarshalError unmarshals an error response for an AWS Query service. +func UnmarshalError(r *request.Request) { + defer r.HTTPResponse.Body.Close() + + bodyBytes, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to read from query HTTP response body", err) + return + } + + // First check for specific error + resp := xmlErrorResponse{} + decodeErr := xml.Unmarshal(bodyBytes, &resp) + if decodeErr == nil { + reqID := resp.RequestID + if reqID == "" { + reqID = r.RequestID + } + r.Error = awserr.NewRequestFailure( + awserr.New(resp.Code, resp.Message, nil), + r.HTTPResponse.StatusCode, + reqID, + ) + return + } + + // Check for unhandled error + servUnavailResp := xmlServiceUnavailableResponse{} + unavailErr := xml.Unmarshal(bodyBytes, &servUnavailResp) + if unavailErr == nil { + r.Error = awserr.NewRequestFailure( + awserr.New("ServiceUnavailableException", "service is unavailable", nil), + r.HTTPResponse.StatusCode, + r.RequestID, + ) + return + } + + // Failed to retrieve any error message from the response body + r.Error = awserr.New("SerializationError", + "failed to decode query XML error response", decodeErr) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go new file mode 100644 index 0000000..e6c5c97 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go @@ -0,0 +1,2991 @@ +package query_test + +import ( + "bytes" + "encoding/json" + "encoding/xml" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/aws/aws-sdk-go/private/protocol/query" + "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil" + "github.com/aws/aws-sdk-go/private/util" +) + +var _ bytes.Buffer // always import bytes +var _ http.Request +var _ json.Marshaler +var _ time.Time +var _ xmlutil.XMLNode +var _ xml.Attr +var _ = ioutil.Discard +var _ = util.Trim("") +var _ = url.Values{} +var _ = io.EOF +var _ = aws.String +var _ = fmt.Println +var _ = reflect.Value{} + +func init() { + protocol.RandReader = &awstesting.ZeroReader{} +} + +// OutputService1ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService1ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService1ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService1ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService1ProtocolTest client from just a session. +// svc := outputservice1protocoltest.New(mySession) +// +// // Create a OutputService1ProtocolTest client with additional configuration +// svc := outputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService1ProtocolTest { + c := p.ClientConfig("outputservice1protocoltest", cfgs...) + return newOutputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService1ProtocolTest { + svc := &OutputService1ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice1protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService1ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService1ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService1TestCaseOperation1 = "OperationName" + +// OutputService1TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService1TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService1TestCaseOperation1 for more information on using the OutputService1TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService1TestCaseOperation1Request method. +// req, resp := client.OutputService1TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (req *request.Request, output *OutputService1TestShapeOutputService1TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService1TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{} + } + + output = &OutputService1TestShapeOutputService1TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService1TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService1TestCaseOperation1 for usage and error information. +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1(input *OutputService1TestShapeOutputService1TestCaseOperation1Input) (*OutputService1TestShapeOutputService1TestCaseOperation1Output, error) { + req, out := c.OutputService1TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService1TestCaseOperation1WithContext is the same as OutputService1TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService1TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1WithContext(ctx aws.Context, input *OutputService1TestShapeOutputService1TestCaseOperation1Input, opts ...request.Option) (*OutputService1TestShapeOutputService1TestCaseOperation1Output, error) { + req, out := c.OutputService1TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService1TestShapeOutputService1TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService1TestShapeOutputService1TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Char *string `type:"character"` + + Double *float64 `type:"double"` + + FalseBool *bool `type:"boolean"` + + Float *float64 `type:"float"` + + Long *int64 `type:"long"` + + Num *int64 `locationName:"FooNum" type:"integer"` + + Str *string `type:"string"` + + Timestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"` + + TrueBool *bool `type:"boolean"` +} + +// SetChar sets the Char field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetChar(v string) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Char = &v + return s +} + +// SetDouble sets the Double field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetDouble(v float64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Double = &v + return s +} + +// SetFalseBool sets the FalseBool field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetFalseBool(v bool) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.FalseBool = &v + return s +} + +// SetFloat sets the Float field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetFloat(v float64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Float = &v + return s +} + +// SetLong sets the Long field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetLong(v int64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Long = &v + return s +} + +// SetNum sets the Num field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetNum(v int64) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Num = &v + return s +} + +// SetStr sets the Str field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetStr(v string) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Str = &v + return s +} + +// SetTimestamp sets the Timestamp field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetTimestamp(v time.Time) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.Timestamp = &v + return s +} + +// SetTrueBool sets the TrueBool field's value. +func (s *OutputService1TestShapeOutputService1TestCaseOperation1Output) SetTrueBool(v bool) *OutputService1TestShapeOutputService1TestCaseOperation1Output { + s.TrueBool = &v + return s +} + +// OutputService2ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService2ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService2ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService2ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService2ProtocolTest client from just a session. +// svc := outputservice2protocoltest.New(mySession) +// +// // Create a OutputService2ProtocolTest client with additional configuration +// svc := outputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService2ProtocolTest { + c := p.ClientConfig("outputservice2protocoltest", cfgs...) + return newOutputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService2ProtocolTest { + svc := &OutputService2ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice2protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService2ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService2ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService2TestCaseOperation1 = "OperationName" + +// OutputService2TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService2TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService2TestCaseOperation1 for more information on using the OutputService2TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService2TestCaseOperation1Request method. +// req, resp := client.OutputService2TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1Request(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (req *request.Request, output *OutputService2TestShapeOutputService2TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService2TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService2TestShapeOutputService2TestCaseOperation1Input{} + } + + output = &OutputService2TestShapeOutputService2TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService2TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService2TestCaseOperation1 for usage and error information. +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1(input *OutputService2TestShapeOutputService2TestCaseOperation1Input) (*OutputService2TestShapeOutputService2TestCaseOperation1Output, error) { + req, out := c.OutputService2TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService2TestCaseOperation1WithContext is the same as OutputService2TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService2TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService2ProtocolTest) OutputService2TestCaseOperation1WithContext(ctx aws.Context, input *OutputService2TestShapeOutputService2TestCaseOperation1Input, opts ...request.Option) (*OutputService2TestShapeOutputService2TestCaseOperation1Output, error) { + req, out := c.OutputService2TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService2TestShapeOutputService2TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService2TestShapeOutputService2TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Num *int64 `type:"integer"` + + Str *string `type:"string"` +} + +// SetNum sets the Num field's value. +func (s *OutputService2TestShapeOutputService2TestCaseOperation1Output) SetNum(v int64) *OutputService2TestShapeOutputService2TestCaseOperation1Output { + s.Num = &v + return s +} + +// SetStr sets the Str field's value. +func (s *OutputService2TestShapeOutputService2TestCaseOperation1Output) SetStr(v string) *OutputService2TestShapeOutputService2TestCaseOperation1Output { + s.Str = &v + return s +} + +// OutputService3ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService3ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService3ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService3ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService3ProtocolTest client from just a session. +// svc := outputservice3protocoltest.New(mySession) +// +// // Create a OutputService3ProtocolTest client with additional configuration +// svc := outputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService3ProtocolTest { + c := p.ClientConfig("outputservice3protocoltest", cfgs...) + return newOutputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService3ProtocolTest { + svc := &OutputService3ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice3protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService3ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService3ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService3TestCaseOperation1 = "OperationName" + +// OutputService3TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService3TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService3TestCaseOperation1 for more information on using the OutputService3TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService3TestCaseOperation1Request method. +// req, resp := client.OutputService3TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1Request(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (req *request.Request, output *OutputService3TestShapeOutputService3TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService3TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService3TestShapeOutputService3TestCaseOperation1Input{} + } + + output = &OutputService3TestShapeOutputService3TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService3TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService3TestCaseOperation1 for usage and error information. +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1(input *OutputService3TestShapeOutputService3TestCaseOperation1Input) (*OutputService3TestShapeOutputService3TestCaseOperation1Output, error) { + req, out := c.OutputService3TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService3TestCaseOperation1WithContext is the same as OutputService3TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService3TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService3ProtocolTest) OutputService3TestCaseOperation1WithContext(ctx aws.Context, input *OutputService3TestShapeOutputService3TestCaseOperation1Input, opts ...request.Option) (*OutputService3TestShapeOutputService3TestCaseOperation1Output, error) { + req, out := c.OutputService3TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService3TestShapeOutputService3TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService3TestShapeOutputService3TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + // Blob is automatically base64 encoded/decoded by the SDK. + Blob []byte `type:"blob"` +} + +// SetBlob sets the Blob field's value. +func (s *OutputService3TestShapeOutputService3TestCaseOperation1Output) SetBlob(v []byte) *OutputService3TestShapeOutputService3TestCaseOperation1Output { + s.Blob = v + return s +} + +// OutputService4ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService4ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService4ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService4ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService4ProtocolTest client from just a session. +// svc := outputservice4protocoltest.New(mySession) +// +// // Create a OutputService4ProtocolTest client with additional configuration +// svc := outputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService4ProtocolTest { + c := p.ClientConfig("outputservice4protocoltest", cfgs...) + return newOutputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService4ProtocolTest { + svc := &OutputService4ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice4protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService4ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService4ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService4TestCaseOperation1 = "OperationName" + +// OutputService4TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService4TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService4TestCaseOperation1 for more information on using the OutputService4TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService4TestCaseOperation1Request method. +// req, resp := client.OutputService4TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1Request(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (req *request.Request, output *OutputService4TestShapeOutputService4TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService4TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService4TestShapeOutputService4TestCaseOperation1Input{} + } + + output = &OutputService4TestShapeOutputService4TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService4TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService4TestCaseOperation1 for usage and error information. +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1(input *OutputService4TestShapeOutputService4TestCaseOperation1Input) (*OutputService4TestShapeOutputService4TestCaseOperation1Output, error) { + req, out := c.OutputService4TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService4TestCaseOperation1WithContext is the same as OutputService4TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService4TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService4ProtocolTest) OutputService4TestCaseOperation1WithContext(ctx aws.Context, input *OutputService4TestShapeOutputService4TestCaseOperation1Input, opts ...request.Option) (*OutputService4TestShapeOutputService4TestCaseOperation1Output, error) { + req, out := c.OutputService4TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService4TestShapeOutputService4TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService4TestShapeOutputService4TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + ListMember []*string `type:"list"` +} + +// SetListMember sets the ListMember field's value. +func (s *OutputService4TestShapeOutputService4TestCaseOperation1Output) SetListMember(v []*string) *OutputService4TestShapeOutputService4TestCaseOperation1Output { + s.ListMember = v + return s +} + +// OutputService5ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService5ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService5ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService5ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService5ProtocolTest client from just a session. +// svc := outputservice5protocoltest.New(mySession) +// +// // Create a OutputService5ProtocolTest client with additional configuration +// svc := outputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService5ProtocolTest { + c := p.ClientConfig("outputservice5protocoltest", cfgs...) + return newOutputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService5ProtocolTest { + svc := &OutputService5ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice5protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService5ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService5ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService5TestCaseOperation1 = "OperationName" + +// OutputService5TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService5TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService5TestCaseOperation1 for more information on using the OutputService5TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService5TestCaseOperation1Request method. +// req, resp := client.OutputService5TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1Request(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (req *request.Request, output *OutputService5TestShapeOutputService5TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService5TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService5TestShapeOutputService5TestCaseOperation1Input{} + } + + output = &OutputService5TestShapeOutputService5TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService5TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService5TestCaseOperation1 for usage and error information. +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1(input *OutputService5TestShapeOutputService5TestCaseOperation1Input) (*OutputService5TestShapeOutputService5TestCaseOperation1Output, error) { + req, out := c.OutputService5TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService5TestCaseOperation1WithContext is the same as OutputService5TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService5TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService5ProtocolTest) OutputService5TestCaseOperation1WithContext(ctx aws.Context, input *OutputService5TestShapeOutputService5TestCaseOperation1Input, opts ...request.Option) (*OutputService5TestShapeOutputService5TestCaseOperation1Output, error) { + req, out := c.OutputService5TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService5TestShapeOutputService5TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService5TestShapeOutputService5TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + ListMember []*string `locationNameList:"item" type:"list"` +} + +// SetListMember sets the ListMember field's value. +func (s *OutputService5TestShapeOutputService5TestCaseOperation1Output) SetListMember(v []*string) *OutputService5TestShapeOutputService5TestCaseOperation1Output { + s.ListMember = v + return s +} + +// OutputService6ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService6ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService6ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService6ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService6ProtocolTest client from just a session. +// svc := outputservice6protocoltest.New(mySession) +// +// // Create a OutputService6ProtocolTest client with additional configuration +// svc := outputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService6ProtocolTest { + c := p.ClientConfig("outputservice6protocoltest", cfgs...) + return newOutputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService6ProtocolTest { + svc := &OutputService6ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice6protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService6ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService6ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService6TestCaseOperation1 = "OperationName" + +// OutputService6TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService6TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService6TestCaseOperation1 for more information on using the OutputService6TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService6TestCaseOperation1Request method. +// req, resp := client.OutputService6TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1Request(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (req *request.Request, output *OutputService6TestShapeOutputService6TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService6TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService6TestShapeOutputService6TestCaseOperation1Input{} + } + + output = &OutputService6TestShapeOutputService6TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService6TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService6TestCaseOperation1 for usage and error information. +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1(input *OutputService6TestShapeOutputService6TestCaseOperation1Input) (*OutputService6TestShapeOutputService6TestCaseOperation1Output, error) { + req, out := c.OutputService6TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService6TestCaseOperation1WithContext is the same as OutputService6TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService6TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService6ProtocolTest) OutputService6TestCaseOperation1WithContext(ctx aws.Context, input *OutputService6TestShapeOutputService6TestCaseOperation1Input, opts ...request.Option) (*OutputService6TestShapeOutputService6TestCaseOperation1Output, error) { + req, out := c.OutputService6TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService6TestShapeOutputService6TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService6TestShapeOutputService6TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + ListMember []*string `type:"list" flattened:"true"` +} + +// SetListMember sets the ListMember field's value. +func (s *OutputService6TestShapeOutputService6TestCaseOperation1Output) SetListMember(v []*string) *OutputService6TestShapeOutputService6TestCaseOperation1Output { + s.ListMember = v + return s +} + +// OutputService7ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService7ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService7ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService7ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService7ProtocolTest client from just a session. +// svc := outputservice7protocoltest.New(mySession) +// +// // Create a OutputService7ProtocolTest client with additional configuration +// svc := outputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService7ProtocolTest { + c := p.ClientConfig("outputservice7protocoltest", cfgs...) + return newOutputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService7ProtocolTest { + svc := &OutputService7ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice7protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService7ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService7ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService7TestCaseOperation1 = "OperationName" + +// OutputService7TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService7TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService7TestCaseOperation1 for more information on using the OutputService7TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService7TestCaseOperation1Request method. +// req, resp := client.OutputService7TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1Request(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (req *request.Request, output *OutputService7TestShapeOutputService7TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService7TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService7TestShapeOutputService7TestCaseOperation1Input{} + } + + output = &OutputService7TestShapeOutputService7TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService7TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService7TestCaseOperation1 for usage and error information. +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1(input *OutputService7TestShapeOutputService7TestCaseOperation1Input) (*OutputService7TestShapeOutputService7TestCaseOperation1Output, error) { + req, out := c.OutputService7TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService7TestCaseOperation1WithContext is the same as OutputService7TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService7TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService7ProtocolTest) OutputService7TestCaseOperation1WithContext(ctx aws.Context, input *OutputService7TestShapeOutputService7TestCaseOperation1Input, opts ...request.Option) (*OutputService7TestShapeOutputService7TestCaseOperation1Output, error) { + req, out := c.OutputService7TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService7TestShapeOutputService7TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService7TestShapeOutputService7TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + ListMember []*string `type:"list" flattened:"true"` +} + +// SetListMember sets the ListMember field's value. +func (s *OutputService7TestShapeOutputService7TestCaseOperation1Output) SetListMember(v []*string) *OutputService7TestShapeOutputService7TestCaseOperation1Output { + s.ListMember = v + return s +} + +// OutputService8ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService8ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService8ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService8ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService8ProtocolTest client from just a session. +// svc := outputservice8protocoltest.New(mySession) +// +// // Create a OutputService8ProtocolTest client with additional configuration +// svc := outputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService8ProtocolTest { + c := p.ClientConfig("outputservice8protocoltest", cfgs...) + return newOutputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService8ProtocolTest { + svc := &OutputService8ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice8protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService8ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService8ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService8TestCaseOperation1 = "OperationName" + +// OutputService8TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService8TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService8TestCaseOperation1 for more information on using the OutputService8TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService8TestCaseOperation1Request method. +// req, resp := client.OutputService8TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1Request(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (req *request.Request, output *OutputService8TestShapeOutputService8TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService8TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService8TestShapeOutputService8TestCaseOperation1Input{} + } + + output = &OutputService8TestShapeOutputService8TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService8TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService8TestCaseOperation1 for usage and error information. +func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1(input *OutputService8TestShapeOutputService8TestCaseOperation1Input) (*OutputService8TestShapeOutputService8TestCaseOperation1Output, error) { + req, out := c.OutputService8TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService8TestCaseOperation1WithContext is the same as OutputService8TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService8TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService8ProtocolTest) OutputService8TestCaseOperation1WithContext(ctx aws.Context, input *OutputService8TestShapeOutputService8TestCaseOperation1Input, opts ...request.Option) (*OutputService8TestShapeOutputService8TestCaseOperation1Output, error) { + req, out := c.OutputService8TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService8TestShapeOutputService8TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService8TestShapeOutputService8TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + List []*OutputService8TestShapeStructureShape `type:"list"` +} + +// SetList sets the List field's value. +func (s *OutputService8TestShapeOutputService8TestCaseOperation1Output) SetList(v []*OutputService8TestShapeStructureShape) *OutputService8TestShapeOutputService8TestCaseOperation1Output { + s.List = v + return s +} + +type OutputService8TestShapeStructureShape struct { + _ struct{} `type:"structure"` + + Bar *string `type:"string"` + + Baz *string `type:"string"` + + Foo *string `type:"string"` +} + +// SetBar sets the Bar field's value. +func (s *OutputService8TestShapeStructureShape) SetBar(v string) *OutputService8TestShapeStructureShape { + s.Bar = &v + return s +} + +// SetBaz sets the Baz field's value. +func (s *OutputService8TestShapeStructureShape) SetBaz(v string) *OutputService8TestShapeStructureShape { + s.Baz = &v + return s +} + +// SetFoo sets the Foo field's value. +func (s *OutputService8TestShapeStructureShape) SetFoo(v string) *OutputService8TestShapeStructureShape { + s.Foo = &v + return s +} + +// OutputService9ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService9ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService9ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService9ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService9ProtocolTest client from just a session. +// svc := outputservice9protocoltest.New(mySession) +// +// // Create a OutputService9ProtocolTest client with additional configuration +// svc := outputservice9protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService9ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService9ProtocolTest { + c := p.ClientConfig("outputservice9protocoltest", cfgs...) + return newOutputService9ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService9ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService9ProtocolTest { + svc := &OutputService9ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice9protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService9ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService9ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService9TestCaseOperation1 = "OperationName" + +// OutputService9TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService9TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService9TestCaseOperation1 for more information on using the OutputService9TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService9TestCaseOperation1Request method. +// req, resp := client.OutputService9TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1Request(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (req *request.Request, output *OutputService9TestShapeOutputService9TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService9TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService9TestShapeOutputService9TestCaseOperation1Input{} + } + + output = &OutputService9TestShapeOutputService9TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService9TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService9TestCaseOperation1 for usage and error information. +func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (*OutputService9TestShapeOutputService9TestCaseOperation1Output, error) { + req, out := c.OutputService9TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService9TestCaseOperation1WithContext is the same as OutputService9TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService9TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1WithContext(ctx aws.Context, input *OutputService9TestShapeOutputService9TestCaseOperation1Input, opts ...request.Option) (*OutputService9TestShapeOutputService9TestCaseOperation1Output, error) { + req, out := c.OutputService9TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService9TestShapeOutputService9TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService9TestShapeOutputService9TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + List []*OutputService9TestShapeStructureShape `type:"list" flattened:"true"` +} + +// SetList sets the List field's value. +func (s *OutputService9TestShapeOutputService9TestCaseOperation1Output) SetList(v []*OutputService9TestShapeStructureShape) *OutputService9TestShapeOutputService9TestCaseOperation1Output { + s.List = v + return s +} + +type OutputService9TestShapeStructureShape struct { + _ struct{} `type:"structure"` + + Bar *string `type:"string"` + + Baz *string `type:"string"` + + Foo *string `type:"string"` +} + +// SetBar sets the Bar field's value. +func (s *OutputService9TestShapeStructureShape) SetBar(v string) *OutputService9TestShapeStructureShape { + s.Bar = &v + return s +} + +// SetBaz sets the Baz field's value. +func (s *OutputService9TestShapeStructureShape) SetBaz(v string) *OutputService9TestShapeStructureShape { + s.Baz = &v + return s +} + +// SetFoo sets the Foo field's value. +func (s *OutputService9TestShapeStructureShape) SetFoo(v string) *OutputService9TestShapeStructureShape { + s.Foo = &v + return s +} + +// OutputService10ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService10ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService10ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService10ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService10ProtocolTest client from just a session. +// svc := outputservice10protocoltest.New(mySession) +// +// // Create a OutputService10ProtocolTest client with additional configuration +// svc := outputservice10protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService10ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService10ProtocolTest { + c := p.ClientConfig("outputservice10protocoltest", cfgs...) + return newOutputService10ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService10ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService10ProtocolTest { + svc := &OutputService10ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice10protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService10ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService10ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService10TestCaseOperation1 = "OperationName" + +// OutputService10TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService10TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService10TestCaseOperation1 for more information on using the OutputService10TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService10TestCaseOperation1Request method. +// req, resp := client.OutputService10TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService10ProtocolTest) OutputService10TestCaseOperation1Request(input *OutputService10TestShapeOutputService10TestCaseOperation1Input) (req *request.Request, output *OutputService10TestShapeOutputService10TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService10TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService10TestShapeOutputService10TestCaseOperation1Input{} + } + + output = &OutputService10TestShapeOutputService10TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService10TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService10TestCaseOperation1 for usage and error information. +func (c *OutputService10ProtocolTest) OutputService10TestCaseOperation1(input *OutputService10TestShapeOutputService10TestCaseOperation1Input) (*OutputService10TestShapeOutputService10TestCaseOperation1Output, error) { + req, out := c.OutputService10TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService10TestCaseOperation1WithContext is the same as OutputService10TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService10TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService10ProtocolTest) OutputService10TestCaseOperation1WithContext(ctx aws.Context, input *OutputService10TestShapeOutputService10TestCaseOperation1Input, opts ...request.Option) (*OutputService10TestShapeOutputService10TestCaseOperation1Output, error) { + req, out := c.OutputService10TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService10TestShapeOutputService10TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService10TestShapeOutputService10TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + List []*string `locationNameList:"NamedList" type:"list" flattened:"true"` +} + +// SetList sets the List field's value. +func (s *OutputService10TestShapeOutputService10TestCaseOperation1Output) SetList(v []*string) *OutputService10TestShapeOutputService10TestCaseOperation1Output { + s.List = v + return s +} + +// OutputService11ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService11ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService11ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService11ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService11ProtocolTest client from just a session. +// svc := outputservice11protocoltest.New(mySession) +// +// // Create a OutputService11ProtocolTest client with additional configuration +// svc := outputservice11protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService11ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService11ProtocolTest { + c := p.ClientConfig("outputservice11protocoltest", cfgs...) + return newOutputService11ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService11ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService11ProtocolTest { + svc := &OutputService11ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice11protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService11ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService11ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService11TestCaseOperation1 = "OperationName" + +// OutputService11TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService11TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService11TestCaseOperation1 for more information on using the OutputService11TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService11TestCaseOperation1Request method. +// req, resp := client.OutputService11TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService11ProtocolTest) OutputService11TestCaseOperation1Request(input *OutputService11TestShapeOutputService11TestCaseOperation1Input) (req *request.Request, output *OutputService11TestShapeOutputService11TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService11TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService11TestShapeOutputService11TestCaseOperation1Input{} + } + + output = &OutputService11TestShapeOutputService11TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService11TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService11TestCaseOperation1 for usage and error information. +func (c *OutputService11ProtocolTest) OutputService11TestCaseOperation1(input *OutputService11TestShapeOutputService11TestCaseOperation1Input) (*OutputService11TestShapeOutputService11TestCaseOperation1Output, error) { + req, out := c.OutputService11TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService11TestCaseOperation1WithContext is the same as OutputService11TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService11TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService11ProtocolTest) OutputService11TestCaseOperation1WithContext(ctx aws.Context, input *OutputService11TestShapeOutputService11TestCaseOperation1Input, opts ...request.Option) (*OutputService11TestShapeOutputService11TestCaseOperation1Output, error) { + req, out := c.OutputService11TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService11TestShapeOutputService11TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService11TestShapeOutputService11TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Map map[string]*OutputService11TestShapeStructType `type:"map"` +} + +// SetMap sets the Map field's value. +func (s *OutputService11TestShapeOutputService11TestCaseOperation1Output) SetMap(v map[string]*OutputService11TestShapeStructType) *OutputService11TestShapeOutputService11TestCaseOperation1Output { + s.Map = v + return s +} + +type OutputService11TestShapeStructType struct { + _ struct{} `type:"structure"` + + Foo *string `locationName:"foo" type:"string"` +} + +// SetFoo sets the Foo field's value. +func (s *OutputService11TestShapeStructType) SetFoo(v string) *OutputService11TestShapeStructType { + s.Foo = &v + return s +} + +// OutputService12ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService12ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService12ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService12ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService12ProtocolTest client from just a session. +// svc := outputservice12protocoltest.New(mySession) +// +// // Create a OutputService12ProtocolTest client with additional configuration +// svc := outputservice12protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService12ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService12ProtocolTest { + c := p.ClientConfig("outputservice12protocoltest", cfgs...) + return newOutputService12ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService12ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService12ProtocolTest { + svc := &OutputService12ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice12protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService12ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService12ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService12TestCaseOperation1 = "OperationName" + +// OutputService12TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService12TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService12TestCaseOperation1 for more information on using the OutputService12TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService12TestCaseOperation1Request method. +// req, resp := client.OutputService12TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService12ProtocolTest) OutputService12TestCaseOperation1Request(input *OutputService12TestShapeOutputService12TestCaseOperation1Input) (req *request.Request, output *OutputService12TestShapeOutputService12TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService12TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService12TestShapeOutputService12TestCaseOperation1Input{} + } + + output = &OutputService12TestShapeOutputService12TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService12TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService12TestCaseOperation1 for usage and error information. +func (c *OutputService12ProtocolTest) OutputService12TestCaseOperation1(input *OutputService12TestShapeOutputService12TestCaseOperation1Input) (*OutputService12TestShapeOutputService12TestCaseOperation1Output, error) { + req, out := c.OutputService12TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService12TestCaseOperation1WithContext is the same as OutputService12TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService12TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService12ProtocolTest) OutputService12TestCaseOperation1WithContext(ctx aws.Context, input *OutputService12TestShapeOutputService12TestCaseOperation1Input, opts ...request.Option) (*OutputService12TestShapeOutputService12TestCaseOperation1Output, error) { + req, out := c.OutputService12TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService12TestShapeOutputService12TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService12TestShapeOutputService12TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Map map[string]*string `type:"map" flattened:"true"` +} + +// SetMap sets the Map field's value. +func (s *OutputService12TestShapeOutputService12TestCaseOperation1Output) SetMap(v map[string]*string) *OutputService12TestShapeOutputService12TestCaseOperation1Output { + s.Map = v + return s +} + +// OutputService13ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService13ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService13ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService13ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService13ProtocolTest client from just a session. +// svc := outputservice13protocoltest.New(mySession) +// +// // Create a OutputService13ProtocolTest client with additional configuration +// svc := outputservice13protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService13ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService13ProtocolTest { + c := p.ClientConfig("outputservice13protocoltest", cfgs...) + return newOutputService13ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService13ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService13ProtocolTest { + svc := &OutputService13ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice13protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService13ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService13ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService13TestCaseOperation1 = "OperationName" + +// OutputService13TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService13TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService13TestCaseOperation1 for more information on using the OutputService13TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService13TestCaseOperation1Request method. +// req, resp := client.OutputService13TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService13ProtocolTest) OutputService13TestCaseOperation1Request(input *OutputService13TestShapeOutputService13TestCaseOperation1Input) (req *request.Request, output *OutputService13TestShapeOutputService13TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService13TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService13TestShapeOutputService13TestCaseOperation1Input{} + } + + output = &OutputService13TestShapeOutputService13TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService13TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService13TestCaseOperation1 for usage and error information. +func (c *OutputService13ProtocolTest) OutputService13TestCaseOperation1(input *OutputService13TestShapeOutputService13TestCaseOperation1Input) (*OutputService13TestShapeOutputService13TestCaseOperation1Output, error) { + req, out := c.OutputService13TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService13TestCaseOperation1WithContext is the same as OutputService13TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService13TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService13ProtocolTest) OutputService13TestCaseOperation1WithContext(ctx aws.Context, input *OutputService13TestShapeOutputService13TestCaseOperation1Input, opts ...request.Option) (*OutputService13TestShapeOutputService13TestCaseOperation1Output, error) { + req, out := c.OutputService13TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService13TestShapeOutputService13TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService13TestShapeOutputService13TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Map map[string]*string `locationName:"Attribute" locationNameKey:"Name" locationNameValue:"Value" type:"map" flattened:"true"` +} + +// SetMap sets the Map field's value. +func (s *OutputService13TestShapeOutputService13TestCaseOperation1Output) SetMap(v map[string]*string) *OutputService13TestShapeOutputService13TestCaseOperation1Output { + s.Map = v + return s +} + +// OutputService14ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService14ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService14ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService14ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService14ProtocolTest client from just a session. +// svc := outputservice14protocoltest.New(mySession) +// +// // Create a OutputService14ProtocolTest client with additional configuration +// svc := outputservice14protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService14ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService14ProtocolTest { + c := p.ClientConfig("outputservice14protocoltest", cfgs...) + return newOutputService14ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService14ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService14ProtocolTest { + svc := &OutputService14ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice14protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService14ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService14ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService14TestCaseOperation1 = "OperationName" + +// OutputService14TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService14TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService14TestCaseOperation1 for more information on using the OutputService14TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService14TestCaseOperation1Request method. +// req, resp := client.OutputService14TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService14ProtocolTest) OutputService14TestCaseOperation1Request(input *OutputService14TestShapeOutputService14TestCaseOperation1Input) (req *request.Request, output *OutputService14TestShapeOutputService14TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService14TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService14TestShapeOutputService14TestCaseOperation1Input{} + } + + output = &OutputService14TestShapeOutputService14TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService14TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService14TestCaseOperation1 for usage and error information. +func (c *OutputService14ProtocolTest) OutputService14TestCaseOperation1(input *OutputService14TestShapeOutputService14TestCaseOperation1Input) (*OutputService14TestShapeOutputService14TestCaseOperation1Output, error) { + req, out := c.OutputService14TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService14TestCaseOperation1WithContext is the same as OutputService14TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService14TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService14ProtocolTest) OutputService14TestCaseOperation1WithContext(ctx aws.Context, input *OutputService14TestShapeOutputService14TestCaseOperation1Input, opts ...request.Option) (*OutputService14TestShapeOutputService14TestCaseOperation1Output, error) { + req, out := c.OutputService14TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService14TestShapeOutputService14TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService14TestShapeOutputService14TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Map map[string]*string `locationNameKey:"foo" locationNameValue:"bar" type:"map" flattened:"true"` +} + +// SetMap sets the Map field's value. +func (s *OutputService14TestShapeOutputService14TestCaseOperation1Output) SetMap(v map[string]*string) *OutputService14TestShapeOutputService14TestCaseOperation1Output { + s.Map = v + return s +} + +// OutputService15ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService15ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService15ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService15ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService15ProtocolTest client from just a session. +// svc := outputservice15protocoltest.New(mySession) +// +// // Create a OutputService15ProtocolTest client with additional configuration +// svc := outputservice15protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService15ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService15ProtocolTest { + c := p.ClientConfig("outputservice15protocoltest", cfgs...) + return newOutputService15ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService15ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService15ProtocolTest { + svc := &OutputService15ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice15protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService15ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService15ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService15TestCaseOperation1 = "OperationName" + +// OutputService15TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService15TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService15TestCaseOperation1 for more information on using the OutputService15TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService15TestCaseOperation1Request method. +// req, resp := client.OutputService15TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService15ProtocolTest) OutputService15TestCaseOperation1Request(input *OutputService15TestShapeOutputService15TestCaseOperation1Input) (req *request.Request, output *OutputService15TestShapeOutputService15TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService15TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService15TestShapeOutputService15TestCaseOperation1Input{} + } + + output = &OutputService15TestShapeOutputService15TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService15TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService15TestCaseOperation1 for usage and error information. +func (c *OutputService15ProtocolTest) OutputService15TestCaseOperation1(input *OutputService15TestShapeOutputService15TestCaseOperation1Input) (*OutputService15TestShapeOutputService15TestCaseOperation1Output, error) { + req, out := c.OutputService15TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService15TestCaseOperation1WithContext is the same as OutputService15TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService15TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService15ProtocolTest) OutputService15TestCaseOperation1WithContext(ctx aws.Context, input *OutputService15TestShapeOutputService15TestCaseOperation1Input, opts ...request.Option) (*OutputService15TestShapeOutputService15TestCaseOperation1Output, error) { + req, out := c.OutputService15TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService15TestShapeOutputService15TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService15TestShapeOutputService15TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + Foo *string `type:"string"` +} + +// SetFoo sets the Foo field's value. +func (s *OutputService15TestShapeOutputService15TestCaseOperation1Output) SetFoo(v string) *OutputService15TestShapeOutputService15TestCaseOperation1Output { + s.Foo = &v + return s +} + +// OutputService16ProtocolTest provides the API operation methods for making requests to +// . See this package's package overview docs +// for details on the service. +// +// OutputService16ProtocolTest methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type OutputService16ProtocolTest struct { + *client.Client +} + +// New creates a new instance of the OutputService16ProtocolTest client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a OutputService16ProtocolTest client from just a session. +// svc := outputservice16protocoltest.New(mySession) +// +// // Create a OutputService16ProtocolTest client with additional configuration +// svc := outputservice16protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func NewOutputService16ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService16ProtocolTest { + c := p.ClientConfig("outputservice16protocoltest", cfgs...) + return newOutputService16ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newOutputService16ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *OutputService16ProtocolTest { + svc := &OutputService16ProtocolTest{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: "outputservice16protocoltest", + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + return svc +} + +// newRequest creates a new request for a OutputService16ProtocolTest operation and runs any +// custom request initialization. +func (c *OutputService16ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} + +const opOutputService16TestCaseOperation1 = "OperationName" + +// OutputService16TestCaseOperation1Request generates a "aws/request.Request" representing the +// client's request for the OutputService16TestCaseOperation1 operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See OutputService16TestCaseOperation1 for more information on using the OutputService16TestCaseOperation1 +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the OutputService16TestCaseOperation1Request method. +// req, resp := client.OutputService16TestCaseOperation1Request(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +func (c *OutputService16ProtocolTest) OutputService16TestCaseOperation1Request(input *OutputService16TestShapeOutputService16TestCaseOperation1Input) (req *request.Request, output *OutputService16TestShapeOutputService16TestCaseOperation1Output) { + op := &request.Operation{ + Name: opOutputService16TestCaseOperation1, + HTTPPath: "/", + } + + if input == nil { + input = &OutputService16TestShapeOutputService16TestCaseOperation1Input{} + } + + output = &OutputService16TestShapeOutputService16TestCaseOperation1Output{} + req = c.newRequest(op, input, output) + return +} + +// OutputService16TestCaseOperation1 API operation for . +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for 's +// API operation OutputService16TestCaseOperation1 for usage and error information. +func (c *OutputService16ProtocolTest) OutputService16TestCaseOperation1(input *OutputService16TestShapeOutputService16TestCaseOperation1Input) (*OutputService16TestShapeOutputService16TestCaseOperation1Output, error) { + req, out := c.OutputService16TestCaseOperation1Request(input) + return out, req.Send() +} + +// OutputService16TestCaseOperation1WithContext is the same as OutputService16TestCaseOperation1 with the addition of +// the ability to pass a context and additional request options. +// +// See OutputService16TestCaseOperation1 for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *OutputService16ProtocolTest) OutputService16TestCaseOperation1WithContext(ctx aws.Context, input *OutputService16TestShapeOutputService16TestCaseOperation1Input, opts ...request.Option) (*OutputService16TestShapeOutputService16TestCaseOperation1Output, error) { + req, out := c.OutputService16TestCaseOperation1Request(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type OutputService16TestShapeOutputService16TestCaseOperation1Input struct { + _ struct{} `type:"structure"` +} + +type OutputService16TestShapeOutputService16TestCaseOperation1Output struct { + _ struct{} `type:"structure"` + + FooEnum *string `type:"string" enum:"OutputService16TestShapeEC2EnumType"` + + ListEnums []*string `type:"list"` +} + +// SetFooEnum sets the FooEnum field's value. +func (s *OutputService16TestShapeOutputService16TestCaseOperation1Output) SetFooEnum(v string) *OutputService16TestShapeOutputService16TestCaseOperation1Output { + s.FooEnum = &v + return s +} + +// SetListEnums sets the ListEnums field's value. +func (s *OutputService16TestShapeOutputService16TestCaseOperation1Output) SetListEnums(v []*string) *OutputService16TestShapeOutputService16TestCaseOperation1Output { + s.ListEnums = v + return s +} + +const ( + // EC2EnumTypeFoo is a OutputService16TestShapeEC2EnumType enum value + EC2EnumTypeFoo = "foo" + + // EC2EnumTypeBar is a OutputService16TestShapeEC2EnumType enum value + EC2EnumTypeBar = "bar" +) + +// +// Tests begin here +// + +func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) { + svc := NewOutputService1ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("myname123falsetrue1.21.3200a2015-01-25T08:00:00Zrequest-id")) + req, out := svc.OutputService1TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "a", *out.Char; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := 1.3, *out.Double; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := false, *out.FalseBool; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := 1.2, *out.Float; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := int64(200), *out.Long; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := int64(123), *out.Num; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "myname", *out.Str; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := time.Unix(1.4221728e+09, 0).UTC().String(), out.Timestamp.String(); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := true, *out.TrueBool; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService2ProtocolTestNotAllMembersInResponseCase1(t *testing.T) { + svc := NewOutputService2ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("mynamerequest-id")) + req, out := svc.OutputService2TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "myname", *out.Str; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService3ProtocolTestBlobCase1(t *testing.T) { + svc := NewOutputService3ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("dmFsdWU=requestid")) + req, out := svc.OutputService3TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "value", string(out.Blob); e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService4ProtocolTestListsCase1(t *testing.T) { + svc := NewOutputService4ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("abc123requestid")) + req, out := svc.OutputService4TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "abc", *out.ListMember[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "123", *out.ListMember[1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService5ProtocolTestListWithCustomMemberNameCase1(t *testing.T) { + svc := NewOutputService5ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("abc123requestid")) + req, out := svc.OutputService5TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "abc", *out.ListMember[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "123", *out.ListMember[1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService6ProtocolTestFlattenedListCase1(t *testing.T) { + svc := NewOutputService6ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("abc123requestid")) + req, out := svc.OutputService6TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "abc", *out.ListMember[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "123", *out.ListMember[1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService7ProtocolTestFlattenedSingleElementListCase1(t *testing.T) { + svc := NewOutputService7ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("abcrequestid")) + req, out := svc.OutputService7TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "abc", *out.ListMember[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService8ProtocolTestListOfStructuresCase1(t *testing.T) { + svc := NewOutputService8ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("firstfoofirstbarfirstbazsecondfoosecondbarsecondbazrequestid")) + req, out := svc.OutputService8TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "firstbar", *out.List[0].Bar; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "firstbaz", *out.List[0].Baz; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "firstfoo", *out.List[0].Foo; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "secondbar", *out.List[1].Bar; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "secondbaz", *out.List[1].Baz; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "secondfoo", *out.List[1].Foo; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService9ProtocolTestFlattenedListOfStructuresCase1(t *testing.T) { + svc := NewOutputService9ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("firstfoofirstbarfirstbazsecondfoosecondbarsecondbazrequestid")) + req, out := svc.OutputService9TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "firstbar", *out.List[0].Bar; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "firstbaz", *out.List[0].Baz; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "firstfoo", *out.List[0].Foo; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "secondbar", *out.List[1].Bar; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "secondbaz", *out.List[1].Baz; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "secondfoo", *out.List[1].Foo; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService10ProtocolTestFlattenedListWithLocationNameCase1(t *testing.T) { + svc := NewOutputService10ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("abrequestid")) + req, out := svc.OutputService10TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "a", *out.List[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "b", *out.List[1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService11ProtocolTestNormalMapCase1(t *testing.T) { + svc := NewOutputService11ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) + req, out := svc.OutputService11TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "bam", *out.Map["baz"].Foo; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "bar", *out.Map["qux"].Foo; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService12ProtocolTestFlattenedMapCase1(t *testing.T) { + svc := NewOutputService12ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) + req, out := svc.OutputService12TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "bam", *out.Map["baz"]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "bar", *out.Map["qux"]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService13ProtocolTestFlattenedMapInShapeDefinitionCase1(t *testing.T) { + svc := NewOutputService13ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("quxbarrequestid")) + req, out := svc.OutputService13TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "bar", *out.Map["qux"]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService14ProtocolTestNamedMapCase1(t *testing.T) { + svc := NewOutputService14ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("quxbarbazbamrequestid")) + req, out := svc.OutputService14TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "bam", *out.Map["baz"]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "bar", *out.Map["qux"]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService15ProtocolTestEmptyStringCase1(t *testing.T) { + svc := NewOutputService15ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("requestid")) + req, out := svc.OutputService15TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "", *out.Foo; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} + +func TestOutputService16ProtocolTestEnumOutputCase1(t *testing.T) { + svc := NewOutputService16ProtocolTest(unit.Session, &aws.Config{Endpoint: aws.String("https://test")}) + + buf := bytes.NewReader([]byte("foofoobar")) + req, out := svc.OutputService16TestCaseOperation1Request(nil) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}} + + // set headers + + // unmarshal response + query.UnmarshalMeta(req) + query.Unmarshal(req) + if req.Error != nil { + t.Errorf("expect not error, got %v", req.Error) + } + + // assert response + if out == nil { + t.Errorf("expect not to be nil") + } + if e, a := "foo", *out.FooEnum; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "foo", *out.ListEnums[0]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "bar", *out.ListEnums[1]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go new file mode 100644 index 0000000..c405288 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go @@ -0,0 +1,291 @@ +// Package rest provides RESTful serialization of AWS requests and responses. +package rest + +import ( + "bytes" + "encoding/base64" + "fmt" + "io" + "net/http" + "net/url" + "path" + "reflect" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol" +) + +// RFC822 returns an RFC822 formatted timestamp for AWS protocols +const RFC822 = "Mon, 2 Jan 2006 15:04:05 GMT" + +// Whether the byte value can be sent without escaping in AWS URLs +var noEscape [256]bool + +var errValueNotSet = fmt.Errorf("value not set") + +func init() { + for i := 0; i < len(noEscape); i++ { + // AWS expects every character except these to be escaped + noEscape[i] = (i >= 'A' && i <= 'Z') || + (i >= 'a' && i <= 'z') || + (i >= '0' && i <= '9') || + i == '-' || + i == '.' || + i == '_' || + i == '~' + } +} + +// BuildHandler is a named request handler for building rest protocol requests +var BuildHandler = request.NamedHandler{Name: "awssdk.rest.Build", Fn: Build} + +// Build builds the REST component of a service request. +func Build(r *request.Request) { + if r.ParamsFilled() { + v := reflect.ValueOf(r.Params).Elem() + buildLocationElements(r, v, false) + buildBody(r, v) + } +} + +// BuildAsGET builds the REST component of a service request with the ability to hoist +// data from the body. +func BuildAsGET(r *request.Request) { + if r.ParamsFilled() { + v := reflect.ValueOf(r.Params).Elem() + buildLocationElements(r, v, true) + buildBody(r, v) + } +} + +func buildLocationElements(r *request.Request, v reflect.Value, buildGETQuery bool) { + query := r.HTTPRequest.URL.Query() + + // Setup the raw path to match the base path pattern. This is needed + // so that when the path is mutated a custom escaped version can be + // stored in RawPath that will be used by the Go client. + r.HTTPRequest.URL.RawPath = r.HTTPRequest.URL.Path + + for i := 0; i < v.NumField(); i++ { + m := v.Field(i) + if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) { + continue + } + + if m.IsValid() { + field := v.Type().Field(i) + name := field.Tag.Get("locationName") + if name == "" { + name = field.Name + } + if kind := m.Kind(); kind == reflect.Ptr { + m = m.Elem() + } else if kind == reflect.Interface { + if !m.Elem().IsValid() { + continue + } + } + if !m.IsValid() { + continue + } + if field.Tag.Get("ignore") != "" { + continue + } + + var err error + switch field.Tag.Get("location") { + case "headers": // header maps + err = buildHeaderMap(&r.HTTPRequest.Header, m, field.Tag) + case "header": + err = buildHeader(&r.HTTPRequest.Header, m, name, field.Tag) + case "uri": + err = buildURI(r.HTTPRequest.URL, m, name, field.Tag) + case "querystring": + err = buildQueryString(query, m, name, field.Tag) + default: + if buildGETQuery { + err = buildQueryString(query, m, name, field.Tag) + } + } + r.Error = err + } + if r.Error != nil { + return + } + } + + r.HTTPRequest.URL.RawQuery = query.Encode() + if !aws.BoolValue(r.Config.DisableRestProtocolURICleaning) { + cleanPath(r.HTTPRequest.URL) + } +} + +func buildBody(r *request.Request, v reflect.Value) { + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + pfield, _ := v.Type().FieldByName(payloadName) + if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { + payload := reflect.Indirect(v.FieldByName(payloadName)) + if payload.IsValid() && payload.Interface() != nil { + switch reader := payload.Interface().(type) { + case io.ReadSeeker: + r.SetReaderBody(reader) + case []byte: + r.SetBufferBody(reader) + case string: + r.SetStringBody(reader) + default: + r.Error = awserr.New("SerializationError", + "failed to encode REST request", + fmt.Errorf("unknown payload type %s", payload.Type())) + } + } + } + } + } +} + +func buildHeader(header *http.Header, v reflect.Value, name string, tag reflect.StructTag) error { + str, err := convertType(v, tag) + if err == errValueNotSet { + return nil + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + } + + header.Add(name, str) + + return nil +} + +func buildHeaderMap(header *http.Header, v reflect.Value, tag reflect.StructTag) error { + prefix := tag.Get("locationName") + for _, key := range v.MapKeys() { + str, err := convertType(v.MapIndex(key), tag) + if err == errValueNotSet { + continue + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + + } + + header.Add(prefix+key.String(), str) + } + return nil +} + +func buildURI(u *url.URL, v reflect.Value, name string, tag reflect.StructTag) error { + value, err := convertType(v, tag) + if err == errValueNotSet { + return nil + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + } + + u.Path = strings.Replace(u.Path, "{"+name+"}", value, -1) + u.Path = strings.Replace(u.Path, "{"+name+"+}", value, -1) + + u.RawPath = strings.Replace(u.RawPath, "{"+name+"}", EscapePath(value, true), -1) + u.RawPath = strings.Replace(u.RawPath, "{"+name+"+}", EscapePath(value, false), -1) + + return nil +} + +func buildQueryString(query url.Values, v reflect.Value, name string, tag reflect.StructTag) error { + switch value := v.Interface().(type) { + case []*string: + for _, item := range value { + query.Add(name, *item) + } + case map[string]*string: + for key, item := range value { + query.Add(key, *item) + } + case map[string][]*string: + for key, items := range value { + for _, item := range items { + query.Add(key, *item) + } + } + default: + str, err := convertType(v, tag) + if err == errValueNotSet { + return nil + } else if err != nil { + return awserr.New("SerializationError", "failed to encode REST request", err) + } + query.Set(name, str) + } + + return nil +} + +func cleanPath(u *url.URL) { + hasSlash := strings.HasSuffix(u.Path, "/") + + // clean up path, removing duplicate `/` + u.Path = path.Clean(u.Path) + u.RawPath = path.Clean(u.RawPath) + + if hasSlash && !strings.HasSuffix(u.Path, "/") { + u.Path += "/" + u.RawPath += "/" + } +} + +// EscapePath escapes part of a URL path in Amazon style +func EscapePath(path string, encodeSep bool) string { + var buf bytes.Buffer + for i := 0; i < len(path); i++ { + c := path[i] + if noEscape[c] || (c == '/' && !encodeSep) { + buf.WriteByte(c) + } else { + fmt.Fprintf(&buf, "%%%02X", c) + } + } + return buf.String() +} + +func convertType(v reflect.Value, tag reflect.StructTag) (str string, err error) { + v = reflect.Indirect(v) + if !v.IsValid() { + return "", errValueNotSet + } + + switch value := v.Interface().(type) { + case string: + str = value + case []byte: + str = base64.StdEncoding.EncodeToString(value) + case bool: + str = strconv.FormatBool(value) + case int64: + str = strconv.FormatInt(value, 10) + case float64: + str = strconv.FormatFloat(value, 'f', -1, 64) + case time.Time: + str = value.UTC().Format(RFC822) + case aws.JSONValue: + if len(value) == 0 { + return "", errValueNotSet + } + escaping := protocol.NoEscape + if tag.Get("location") == "header" { + escaping = protocol.Base64Escape + } + str, err = protocol.EncodeJSONValue(value, escaping) + if err != nil { + return "", fmt.Errorf("unable to encode JSONValue, %v", err) + } + default: + err := fmt.Errorf("unsupported value for param %v (%s)", v.Interface(), v.Type()) + return "", err + } + return str, nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build_test.go new file mode 100644 index 0000000..9f18081 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build_test.go @@ -0,0 +1,63 @@ +package rest + +import ( + "net/http" + "net/url" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" +) + +func TestCleanPath(t *testing.T) { + uri := &url.URL{ + Path: "//foo//bar", + Scheme: "https", + Host: "host", + } + cleanPath(uri) + + expected := "https://host/foo/bar" + if a, e := uri.String(), expected; a != e { + t.Errorf("expect %q URI, got %q", e, a) + } +} + +func TestMarshalPath(t *testing.T) { + in := struct { + Bucket *string `location:"uri" locationName:"bucket"` + Key *string `location:"uri" locationName:"key"` + }{ + Bucket: aws.String("mybucket"), + Key: aws.String("my/cool+thing space/object世界"), + } + + expectURL := `/mybucket/my/cool+thing space/object世界` + expectEscapedURL := `/mybucket/my/cool%2Bthing%20space/object%E4%B8%96%E7%95%8C` + + req := &request.Request{ + HTTPRequest: &http.Request{ + URL: &url.URL{Scheme: "https", Host: "exmaple.com", Path: "/{bucket}/{key+}"}, + }, + Params: &in, + } + + Build(req) + + if req.Error != nil { + t.Fatalf("unexpected error, %v", req.Error) + } + + if a, e := req.HTTPRequest.URL.Path, expectURL; a != e { + t.Errorf("expect %q URI, got %q", e, a) + } + + if a, e := req.HTTPRequest.URL.RawPath, expectEscapedURL; a != e { + t.Errorf("expect %q escaped URI, got %q", e, a) + } + + if a, e := req.HTTPRequest.URL.EscapedPath(), expectEscapedURL; a != e { + t.Errorf("expect %q escaped URI, got %q", e, a) + } + +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go new file mode 100644 index 0000000..4366de2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go @@ -0,0 +1,45 @@ +package rest + +import "reflect" + +// PayloadMember returns the payload field member of i if there is one, or nil. +func PayloadMember(i interface{}) interface{} { + if i == nil { + return nil + } + + v := reflect.ValueOf(i).Elem() + if !v.IsValid() { + return nil + } + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + field, _ := v.Type().FieldByName(payloadName) + if field.Tag.Get("type") != "structure" { + return nil + } + + payload := v.FieldByName(payloadName) + if payload.IsValid() || (payload.Kind() == reflect.Ptr && !payload.IsNil()) { + return payload.Interface() + } + } + } + return nil +} + +// PayloadType returns the type of a payload field member of i if there is one, or "". +func PayloadType(i interface{}) string { + v := reflect.Indirect(reflect.ValueOf(i)) + if !v.IsValid() { + return "" + } + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + if member, ok := v.Type().FieldByName(payloadName); ok { + return member.Tag.Get("type") + } + } + } + return "" +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/rest_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/rest_test.go new file mode 100644 index 0000000..46457b2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/rest_test.go @@ -0,0 +1,63 @@ +package rest_test + +import ( + "bytes" + "io/ioutil" + "net/http" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/private/protocol/rest" +) + +func TestUnsetHeaders(t *testing.T) { + cfg := &aws.Config{Region: aws.String("us-west-2")} + c := unit.Session.ClientConfig("testService", cfg) + svc := client.New( + *cfg, + metadata.ClientInfo{ + ServiceName: "testService", + SigningName: c.SigningName, + SigningRegion: c.SigningRegion, + Endpoint: c.Endpoint, + APIVersion: "", + }, + c.Handlers, + ) + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(rest.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(rest.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(rest.UnmarshalMetaHandler) + op := &request.Operation{ + Name: "test-operation", + HTTPPath: "/", + } + + input := &struct { + Foo aws.JSONValue `location:"header" locationName:"x-amz-foo" type:"jsonvalue"` + Bar aws.JSONValue `location:"header" locationName:"x-amz-bar" type:"jsonvalue"` + }{} + + output := &struct { + Foo aws.JSONValue `location:"header" locationName:"x-amz-foo" type:"jsonvalue"` + Bar aws.JSONValue `location:"header" locationName:"x-amz-bar" type:"jsonvalue"` + }{} + + req := svc.NewRequest(op, input, output) + req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewBuffer(nil)), Header: http.Header{}} + req.HTTPResponse.Header.Set("X-Amz-Foo", "e30=") + + // unmarshal response + rest.UnmarshalMeta(req) + rest.Unmarshal(req) + if req.Error != nil { + t.Fatal(req.Error) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go new file mode 100644 index 0000000..823f045 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go @@ -0,0 +1,221 @@ +package rest + +import ( + "bytes" + "encoding/base64" + "fmt" + "io" + "io/ioutil" + "net/http" + "reflect" + "strconv" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol" +) + +// UnmarshalHandler is a named request handler for unmarshaling rest protocol requests +var UnmarshalHandler = request.NamedHandler{Name: "awssdk.rest.Unmarshal", Fn: Unmarshal} + +// UnmarshalMetaHandler is a named request handler for unmarshaling rest protocol request metadata +var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.rest.UnmarshalMeta", Fn: UnmarshalMeta} + +// Unmarshal unmarshals the REST component of a response in a REST service. +func Unmarshal(r *request.Request) { + if r.DataFilled() { + v := reflect.Indirect(reflect.ValueOf(r.Data)) + unmarshalBody(r, v) + } +} + +// UnmarshalMeta unmarshals the REST metadata of a response in a REST service +func UnmarshalMeta(r *request.Request) { + r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid") + if r.RequestID == "" { + // Alternative version of request id in the header + r.RequestID = r.HTTPResponse.Header.Get("X-Amz-Request-Id") + } + if r.DataFilled() { + v := reflect.Indirect(reflect.ValueOf(r.Data)) + unmarshalLocationElements(r, v) + } +} + +func unmarshalBody(r *request.Request, v reflect.Value) { + if field, ok := v.Type().FieldByName("_"); ok { + if payloadName := field.Tag.Get("payload"); payloadName != "" { + pfield, _ := v.Type().FieldByName(payloadName) + if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { + payload := v.FieldByName(payloadName) + if payload.IsValid() { + switch payload.Interface().(type) { + case []byte: + defer r.HTTPResponse.Body.Close() + b, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + } else { + payload.Set(reflect.ValueOf(b)) + } + case *string: + defer r.HTTPResponse.Body.Close() + b, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + } else { + str := string(b) + payload.Set(reflect.ValueOf(&str)) + } + default: + switch payload.Type().String() { + case "io.ReadCloser": + payload.Set(reflect.ValueOf(r.HTTPResponse.Body)) + case "io.ReadSeeker": + b, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err != nil { + r.Error = awserr.New("SerializationError", + "failed to read response body", err) + return + } + payload.Set(reflect.ValueOf(ioutil.NopCloser(bytes.NewReader(b)))) + default: + io.Copy(ioutil.Discard, r.HTTPResponse.Body) + defer r.HTTPResponse.Body.Close() + r.Error = awserr.New("SerializationError", + "failed to decode REST response", + fmt.Errorf("unknown payload type %s", payload.Type())) + } + } + } + } + } + } +} + +func unmarshalLocationElements(r *request.Request, v reflect.Value) { + for i := 0; i < v.NumField(); i++ { + m, field := v.Field(i), v.Type().Field(i) + if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) { + continue + } + + if m.IsValid() { + name := field.Tag.Get("locationName") + if name == "" { + name = field.Name + } + + switch field.Tag.Get("location") { + case "statusCode": + unmarshalStatusCode(m, r.HTTPResponse.StatusCode) + case "header": + err := unmarshalHeader(m, r.HTTPResponse.Header.Get(name), field.Tag) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + break + } + case "headers": + prefix := field.Tag.Get("locationName") + err := unmarshalHeaderMap(m, r.HTTPResponse.Header, prefix) + if err != nil { + r.Error = awserr.New("SerializationError", "failed to decode REST response", err) + break + } + } + } + if r.Error != nil { + return + } + } +} + +func unmarshalStatusCode(v reflect.Value, statusCode int) { + if !v.IsValid() { + return + } + + switch v.Interface().(type) { + case *int64: + s := int64(statusCode) + v.Set(reflect.ValueOf(&s)) + } +} + +func unmarshalHeaderMap(r reflect.Value, headers http.Header, prefix string) error { + switch r.Interface().(type) { + case map[string]*string: // we only support string map value types + out := map[string]*string{} + for k, v := range headers { + k = http.CanonicalHeaderKey(k) + if strings.HasPrefix(strings.ToLower(k), strings.ToLower(prefix)) { + out[k[len(prefix):]] = &v[0] + } + } + r.Set(reflect.ValueOf(out)) + } + return nil +} + +func unmarshalHeader(v reflect.Value, header string, tag reflect.StructTag) error { + isJSONValue := tag.Get("type") == "jsonvalue" + if isJSONValue { + if len(header) == 0 { + return nil + } + } else if !v.IsValid() || (header == "" && v.Elem().Kind() != reflect.String) { + return nil + } + + switch v.Interface().(type) { + case *string: + v.Set(reflect.ValueOf(&header)) + case []byte: + b, err := base64.StdEncoding.DecodeString(header) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&b)) + case *bool: + b, err := strconv.ParseBool(header) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&b)) + case *int64: + i, err := strconv.ParseInt(header, 10, 64) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&i)) + case *float64: + f, err := strconv.ParseFloat(header, 64) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&f)) + case *time.Time: + t, err := time.Parse(RFC822, header) + if err != nil { + return err + } + v.Set(reflect.ValueOf(&t)) + case aws.JSONValue: + escaping := protocol.NoEscape + if tag.Get("location") == "header" { + escaping = protocol.Base64Escape + } + m, err := protocol.DecodeJSONValue(header, escaping) + if err != nil { + return err + } + v.Set(reflect.ValueOf(m)) + default: + err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type()) + return err + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go new file mode 100644 index 0000000..da1a681 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go @@ -0,0 +1,21 @@ +package protocol + +import ( + "io" + "io/ioutil" + + "github.com/aws/aws-sdk-go/aws/request" +) + +// UnmarshalDiscardBodyHandler is a named request handler to empty and close a response's body +var UnmarshalDiscardBodyHandler = request.NamedHandler{Name: "awssdk.shared.UnmarshalDiscardBody", Fn: UnmarshalDiscardBody} + +// UnmarshalDiscardBody is a request handler to empty a response's body and closing it. +func UnmarshalDiscardBody(r *request.Request) { + if r.HTTPResponse == nil || r.HTTPResponse.Body == nil { + return + } + + io.Copy(ioutil.Discard, r.HTTPResponse.Body) + r.HTTPResponse.Body.Close() +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal_test.go new file mode 100644 index 0000000..2733e99 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal_test.go @@ -0,0 +1,40 @@ +package protocol_test + +import ( + "net/http" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/stretchr/testify/assert" +) + +type mockCloser struct { + *strings.Reader + Closed bool +} + +func (m *mockCloser) Close() error { + m.Closed = true + return nil +} + +func TestUnmarshalDrainBody(t *testing.T) { + b := &mockCloser{Reader: strings.NewReader("example body")} + r := &request.Request{HTTPResponse: &http.Response{ + Body: b, + }} + + protocol.UnmarshalDiscardBody(r) + assert.NoError(t, r.Error) + assert.Equal(t, 0, b.Len()) + assert.True(t, b.Closed) +} + +func TestUnmarshalDrainBodyNoBody(t *testing.T) { + r := &request.Request{HTTPResponse: &http.Response{}} + + protocol.UnmarshalDiscardBody(r) + assert.NoError(t, r.Error) +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go new file mode 100644 index 0000000..7091b45 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go @@ -0,0 +1,296 @@ +// Package xmlutil provides XML serialization of AWS requests and responses. +package xmlutil + +import ( + "encoding/base64" + "encoding/xml" + "fmt" + "reflect" + "sort" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/private/protocol" +) + +// BuildXML will serialize params into an xml.Encoder. +// Error will be returned if the serialization of any of the params or nested values fails. +func BuildXML(params interface{}, e *xml.Encoder) error { + b := xmlBuilder{encoder: e, namespaces: map[string]string{}} + root := NewXMLElement(xml.Name{}) + if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil { + return err + } + for _, c := range root.Children { + for _, v := range c { + return StructToXML(e, v, false) + } + } + return nil +} + +// Returns the reflection element of a value, if it is a pointer. +func elemOf(value reflect.Value) reflect.Value { + for value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value +} + +// A xmlBuilder serializes values from Go code to XML +type xmlBuilder struct { + encoder *xml.Encoder + namespaces map[string]string +} + +// buildValue generic XMLNode builder for any type. Will build value for their specific type +// struct, list, map, scalar. +// +// Also takes a "type" tag value to set what type a value should be converted to XMLNode as. If +// type is not provided reflect will be used to determine the value's type. +func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + value = elemOf(value) + if !value.IsValid() { // no need to handle zero values + return nil + } else if tag.Get("location") != "" { // don't handle non-body location values + return nil + } + + t := tag.Get("type") + if t == "" { + switch value.Kind() { + case reflect.Struct: + t = "structure" + case reflect.Slice: + t = "list" + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := value.Type().FieldByName("_"); ok { + tag = tag + reflect.StructTag(" ") + field.Tag + } + return b.buildStruct(value, current, tag) + case "list": + return b.buildList(value, current, tag) + case "map": + return b.buildMap(value, current, tag) + default: + return b.buildScalar(value, current, tag) + } +} + +// buildStruct adds a struct and its fields to the current XMLNode. All fields any any nested +// types are converted to XMLNodes also. +func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + if !value.IsValid() { + return nil + } + + fieldAdded := false + + // unwrap payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := value.Type().FieldByName(payload) + tag = field.Tag + value = elemOf(value.FieldByName(payload)) + + if !value.IsValid() { + return nil + } + } + + child := NewXMLElement(xml.Name{Local: tag.Get("locationName")}) + + // there is an xmlNamespace associated with this struct + if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" { + ns := xml.Attr{ + Name: xml.Name{Local: "xmlns"}, + Value: uri, + } + if prefix != "" { + b.namespaces[prefix] = uri // register the namespace + ns.Name.Local = "xmlns:" + prefix + } + + child.Attr = append(child.Attr, ns) + } + + t := value.Type() + for i := 0; i < value.NumField(); i++ { + member := elemOf(value.Field(i)) + field := t.Field(i) + + if field.PkgPath != "" { + continue // ignore unexported fields + } + if field.Tag.Get("ignore") != "" { + continue + } + + mTag := field.Tag + if mTag.Get("location") != "" { // skip non-body members + continue + } + + if protocol.CanSetIdempotencyToken(value.Field(i), field) { + token := protocol.GetIdempotencyToken() + member = reflect.ValueOf(token) + } + + memberName := mTag.Get("locationName") + if memberName == "" { + memberName = field.Name + mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`) + } + if err := b.buildValue(member, child, mTag); err != nil { + return err + } + + fieldAdded = true + } + + if fieldAdded { // only append this child if we have one ore more valid members + current.AddChild(child) + } + + return nil +} + +// buildList adds the value's list items to the current XMLNode as children nodes. All +// nested values in the list are converted to XMLNodes also. +func (b *xmlBuilder) buildList(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + if value.IsNil() { // don't build omitted lists + return nil + } + + // check for unflattened list member + flattened := tag.Get("flattened") != "" + + xname := xml.Name{Local: tag.Get("locationName")} + if flattened { + for i := 0; i < value.Len(); i++ { + child := NewXMLElement(xname) + current.AddChild(child) + if err := b.buildValue(value.Index(i), child, ""); err != nil { + return err + } + } + } else { + list := NewXMLElement(xname) + current.AddChild(list) + + for i := 0; i < value.Len(); i++ { + iname := tag.Get("locationNameList") + if iname == "" { + iname = "member" + } + + child := NewXMLElement(xml.Name{Local: iname}) + list.AddChild(child) + if err := b.buildValue(value.Index(i), child, ""); err != nil { + return err + } + } + } + + return nil +} + +// buildMap adds the value's key/value pairs to the current XMLNode as children nodes. All +// nested values in the map are converted to XMLNodes also. +// +// Error will be returned if it is unable to build the map's values into XMLNodes +func (b *xmlBuilder) buildMap(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + if value.IsNil() { // don't build omitted maps + return nil + } + + maproot := NewXMLElement(xml.Name{Local: tag.Get("locationName")}) + current.AddChild(maproot) + current = maproot + + kname, vname := "key", "value" + if n := tag.Get("locationNameKey"); n != "" { + kname = n + } + if n := tag.Get("locationNameValue"); n != "" { + vname = n + } + + // sorting is not required for compliance, but it makes testing easier + keys := make([]string, value.Len()) + for i, k := range value.MapKeys() { + keys[i] = k.String() + } + sort.Strings(keys) + + for _, k := range keys { + v := value.MapIndex(reflect.ValueOf(k)) + + mapcur := current + if tag.Get("flattened") == "" { // add "entry" tag to non-flat maps + child := NewXMLElement(xml.Name{Local: "entry"}) + mapcur.AddChild(child) + mapcur = child + } + + kchild := NewXMLElement(xml.Name{Local: kname}) + kchild.Text = k + vchild := NewXMLElement(xml.Name{Local: vname}) + mapcur.AddChild(kchild) + mapcur.AddChild(vchild) + + if err := b.buildValue(v, vchild, ""); err != nil { + return err + } + } + + return nil +} + +// buildScalar will convert the value into a string and append it as a attribute or child +// of the current XMLNode. +// +// The value will be added as an attribute if tag contains a "xmlAttribute" attribute value. +// +// Error will be returned if the value type is unsupported. +func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag reflect.StructTag) error { + var str string + switch converted := value.Interface().(type) { + case string: + str = converted + case []byte: + if !value.IsNil() { + str = base64.StdEncoding.EncodeToString(converted) + } + case bool: + str = strconv.FormatBool(converted) + case int64: + str = strconv.FormatInt(converted, 10) + case int: + str = strconv.Itoa(converted) + case float64: + str = strconv.FormatFloat(converted, 'f', -1, 64) + case float32: + str = strconv.FormatFloat(float64(converted), 'f', -1, 32) + case time.Time: + const ISO8601UTC = "2006-01-02T15:04:05Z" + str = converted.UTC().Format(ISO8601UTC) + default: + return fmt.Errorf("unsupported value for param %s: %v (%s)", + tag.Get("locationName"), value.Interface(), value.Type().Name()) + } + + xname := xml.Name{Local: tag.Get("locationName")} + if tag.Get("xmlAttribute") != "" { // put into current node's attribute list + attr := xml.Attr{Name: xname, Value: str} + current.Attr = append(current.Attr, attr) + } else { // regular text node + current.AddChild(&XMLNode{Name: xname, Text: str}) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go new file mode 100644 index 0000000..8758462 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go @@ -0,0 +1,260 @@ +package xmlutil + +import ( + "encoding/base64" + "encoding/xml" + "fmt" + "io" + "reflect" + "strconv" + "strings" + "time" +) + +// UnmarshalXML deserializes an xml.Decoder into the container v. V +// needs to match the shape of the XML expected to be decoded. +// If the shape doesn't match unmarshaling will fail. +func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error { + n, err := XMLToStruct(d, nil) + if err != nil { + return err + } + if n.Children != nil { + for _, root := range n.Children { + for _, c := range root { + if wrappedChild, ok := c.Children[wrapper]; ok { + c = wrappedChild[0] // pull out wrapped element + } + + err = parse(reflect.ValueOf(v), c, "") + if err != nil { + if err == io.EOF { + return nil + } + return err + } + } + } + return nil + } + return nil +} + +// parse deserializes any value from the XMLNode. The type tag is used to infer the type, or reflect +// will be used to determine the type from r. +func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + rtype := r.Type() + if rtype.Kind() == reflect.Ptr { + rtype = rtype.Elem() // check kind of actual element type + } + + t := tag.Get("type") + if t == "" { + switch rtype.Kind() { + case reflect.Struct: + t = "structure" + case reflect.Slice: + t = "list" + case reflect.Map: + t = "map" + } + } + + switch t { + case "structure": + if field, ok := rtype.FieldByName("_"); ok { + tag = field.Tag + } + return parseStruct(r, node, tag) + case "list": + return parseList(r, node, tag) + case "map": + return parseMap(r, node, tag) + default: + return parseScalar(r, node, tag) + } +} + +// parseStruct deserializes a structure and its fields from an XMLNode. Any nested +// types in the structure will also be deserialized. +func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + t := r.Type() + if r.Kind() == reflect.Ptr { + if r.IsNil() { // create the structure if it's nil + s := reflect.New(r.Type().Elem()) + r.Set(s) + r = s + } + + r = r.Elem() + t = t.Elem() + } + + // unwrap any payloads + if payload := tag.Get("payload"); payload != "" { + field, _ := t.FieldByName(payload) + return parseStruct(r.FieldByName(payload), node, field.Tag) + } + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if c := field.Name[0:1]; strings.ToLower(c) == c { + continue // ignore unexported fields + } + + // figure out what this field is called + name := field.Name + if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" { + name = field.Tag.Get("locationNameList") + } else if locName := field.Tag.Get("locationName"); locName != "" { + name = locName + } + + // try to find the field by name in elements + elems := node.Children[name] + + if elems == nil { // try to find the field in attributes + if val, ok := node.findElem(name); ok { + elems = []*XMLNode{{Text: val}} + } + } + + member := r.FieldByName(field.Name) + for _, elem := range elems { + err := parse(member, elem, field.Tag) + if err != nil { + return err + } + } + } + return nil +} + +// parseList deserializes a list of values from an XML node. Each list entry +// will also be deserialized. +func parseList(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + t := r.Type() + + if tag.Get("flattened") == "" { // look at all item entries + mname := "member" + if name := tag.Get("locationNameList"); name != "" { + mname = name + } + + if Children, ok := node.Children[mname]; ok { + if r.IsNil() { + r.Set(reflect.MakeSlice(t, len(Children), len(Children))) + } + + for i, c := range Children { + err := parse(r.Index(i), c, "") + if err != nil { + return err + } + } + } + } else { // flattened list means this is a single element + if r.IsNil() { + r.Set(reflect.MakeSlice(t, 0, 0)) + } + + childR := reflect.Zero(t.Elem()) + r.Set(reflect.Append(r, childR)) + err := parse(r.Index(r.Len()-1), node, "") + if err != nil { + return err + } + } + + return nil +} + +// parseMap deserializes a map from an XMLNode. The direct children of the XMLNode +// will also be deserialized as map entries. +func parseMap(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + if r.IsNil() { + r.Set(reflect.MakeMap(r.Type())) + } + + if tag.Get("flattened") == "" { // look at all child entries + for _, entry := range node.Children["entry"] { + parseMapEntry(r, entry, tag) + } + } else { // this element is itself an entry + parseMapEntry(r, node, tag) + } + + return nil +} + +// parseMapEntry deserializes a map entry from a XML node. +func parseMapEntry(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + kname, vname := "key", "value" + if n := tag.Get("locationNameKey"); n != "" { + kname = n + } + if n := tag.Get("locationNameValue"); n != "" { + vname = n + } + + keys, ok := node.Children[kname] + values := node.Children[vname] + if ok { + for i, key := range keys { + keyR := reflect.ValueOf(key.Text) + value := values[i] + valueR := reflect.New(r.Type().Elem()).Elem() + + parse(valueR, value, "") + r.SetMapIndex(keyR, valueR) + } + } + return nil +} + +// parseScaller deserializes an XMLNode value into a concrete type based on the +// interface type of r. +// +// Error is returned if the deserialization fails due to invalid type conversion, +// or unsupported interface type. +func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error { + switch r.Interface().(type) { + case *string: + r.Set(reflect.ValueOf(&node.Text)) + return nil + case []byte: + b, err := base64.StdEncoding.DecodeString(node.Text) + if err != nil { + return err + } + r.Set(reflect.ValueOf(b)) + case *bool: + v, err := strconv.ParseBool(node.Text) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&v)) + case *int64: + v, err := strconv.ParseInt(node.Text, 10, 64) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&v)) + case *float64: + v, err := strconv.ParseFloat(node.Text, 64) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&v)) + case *time.Time: + const ISO8601UTC = "2006-01-02T15:04:05Z" + t, err := time.Parse(ISO8601UTC, node.Text) + if err != nil { + return err + } + r.Set(reflect.ValueOf(&t)) + default: + return fmt.Errorf("unsupported value: %v (%s)", r.Interface(), r.Type()) + } + return nil +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal_test.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal_test.go new file mode 100644 index 0000000..1185d23 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal_test.go @@ -0,0 +1,142 @@ +package xmlutil + +import ( + "encoding/xml" + "fmt" + "io" + "reflect" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" +) + +type mockBody struct { + DoneErr error + Body io.Reader +} + +func (m *mockBody) Read(p []byte) (int, error) { + n, err := m.Body.Read(p) + if (n == 0 || err == io.EOF) && m.DoneErr != nil { + return n, m.DoneErr + } + + return n, err +} + +type mockOutput struct { + _ struct{} `type:"structure"` + String *string `type:"string"` + Integer *int64 `type:"integer"` + Nested *mockNestedStruct `type:"structure"` + List []*mockListElem `locationName:"List" locationNameList:"Elem" type:"list"` + Closed *mockClosedTags `type:"structure"` +} +type mockNestedStruct struct { + _ struct{} `type:"structure"` + NestedString *string `type:"string"` + NestedInt *int64 `type:"integer"` +} +type mockClosedTags struct { + _ struct{} `type:"structure" xmlPrefix:"xsi" xmlURI:"http://www.w3.org/2001/XMLSchema-instance"` + Attr *string `locationName:"xsi:attrval" type:"string" xmlAttribute:"true"` +} +type mockListElem struct { + _ struct{} `type:"structure" xmlPrefix:"xsi" xmlURI:"http://www.w3.org/2001/XMLSchema-instance"` + String *string `type:"string"` + NestedElem *mockNestedListElem `type:"structure"` +} +type mockNestedListElem struct { + _ struct{} `type:"structure" xmlPrefix:"xsi" xmlURI:"http://www.w3.org/2001/XMLSchema-instance"` + + String *string `type:"string"` + Type *string `locationName:"xsi:type" type:"string" xmlAttribute:"true"` +} + +func TestUnmarshal(t *testing.T) { + const xmlBodyStr = ` + + string value + 123 + + + nested string value + 321 + + + + + nested elem string value + + elem string value + + +` + + expect := mockOutput{ + String: aws.String("string value"), + Integer: aws.Int64(123), + Closed: &mockClosedTags{ + Attr: aws.String("attr value"), + }, + Nested: &mockNestedStruct{ + NestedString: aws.String("nested string value"), + NestedInt: aws.Int64(321), + }, + List: []*mockListElem{ + { + String: aws.String("elem string value"), + NestedElem: &mockNestedListElem{ + String: aws.String("nested elem string value"), + Type: aws.String("type"), + }, + }, + }, + } + + actual := mockOutput{} + decoder := xml.NewDecoder(strings.NewReader(xmlBodyStr)) + err := UnmarshalXML(&actual, decoder, "") + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if !reflect.DeepEqual(expect, actual) { + t.Errorf("expect unmarshal to match\nExpect: %s\nActual: %s", + awsutil.Prettify(expect), awsutil.Prettify(actual)) + } +} + +func TestUnmarshal_UnexpectedEOF(t *testing.T) { + const partialXMLBody = ` + first value + Second val` + + out := struct { + First *string `locationName:"First" type:"string"` + Second *string `locationName:"Second" type:"string"` + }{} + + expect := out + expect.First = aws.String("first") + expect.Second = aws.String("second") + + expectErr := fmt.Errorf("expected read error") + + body := &mockBody{ + DoneErr: expectErr, + Body: strings.NewReader(partialXMLBody), + } + + decoder := xml.NewDecoder(body) + err := UnmarshalXML(&out, decoder, "") + + if err == nil { + t.Fatalf("expect error, got none") + } + if e, a := expectErr, err; e != a { + t.Errorf("expect %v error in %v, but was not", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go new file mode 100644 index 0000000..3e970b6 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go @@ -0,0 +1,147 @@ +package xmlutil + +import ( + "encoding/xml" + "fmt" + "io" + "sort" +) + +// A XMLNode contains the values to be encoded or decoded. +type XMLNode struct { + Name xml.Name `json:",omitempty"` + Children map[string][]*XMLNode `json:",omitempty"` + Text string `json:",omitempty"` + Attr []xml.Attr `json:",omitempty"` + + namespaces map[string]string + parent *XMLNode +} + +// NewXMLElement returns a pointer to a new XMLNode initialized to default values. +func NewXMLElement(name xml.Name) *XMLNode { + return &XMLNode{ + Name: name, + Children: map[string][]*XMLNode{}, + Attr: []xml.Attr{}, + } +} + +// AddChild adds child to the XMLNode. +func (n *XMLNode) AddChild(child *XMLNode) { + if _, ok := n.Children[child.Name.Local]; !ok { + n.Children[child.Name.Local] = []*XMLNode{} + } + n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child) +} + +// XMLToStruct converts a xml.Decoder stream to XMLNode with nested values. +func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) { + out := &XMLNode{} + for { + tok, err := d.Token() + if err != nil { + if err == io.EOF { + break + } else { + return out, err + } + } + + if tok == nil { + break + } + + switch typed := tok.(type) { + case xml.CharData: + out.Text = string(typed.Copy()) + case xml.StartElement: + el := typed.Copy() + out.Attr = el.Attr + if out.Children == nil { + out.Children = map[string][]*XMLNode{} + } + + name := typed.Name.Local + slice := out.Children[name] + if slice == nil { + slice = []*XMLNode{} + } + node, e := XMLToStruct(d, &el) + out.findNamespaces() + if e != nil { + return out, e + } + node.Name = typed.Name + node.findNamespaces() + tempOut := *out + // Save into a temp variable, simply because out gets squashed during + // loop iterations + node.parent = &tempOut + slice = append(slice, node) + out.Children[name] = slice + case xml.EndElement: + if s != nil && s.Name.Local == typed.Name.Local { // matching end token + return out, nil + } + out = &XMLNode{} + } + } + return out, nil +} + +func (n *XMLNode) findNamespaces() { + ns := map[string]string{} + for _, a := range n.Attr { + if a.Name.Space == "xmlns" { + ns[a.Value] = a.Name.Local + } + } + + n.namespaces = ns +} + +func (n *XMLNode) findElem(name string) (string, bool) { + for node := n; node != nil; node = node.parent { + for _, a := range node.Attr { + namespace := a.Name.Space + if v, ok := node.namespaces[namespace]; ok { + namespace = v + } + if name == fmt.Sprintf("%s:%s", namespace, a.Name.Local) { + return a.Value, true + } + } + } + return "", false +} + +// StructToXML writes an XMLNode to a xml.Encoder as tokens. +func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error { + e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr}) + + if node.Text != "" { + e.EncodeToken(xml.CharData([]byte(node.Text))) + } else if sorted { + sortedNames := []string{} + for k := range node.Children { + sortedNames = append(sortedNames, k) + } + sort.Strings(sortedNames) + + for _, k := range sortedNames { + for _, v := range node.Children[k] { + StructToXML(e, v, sorted) + } + } + } else { + for _, c := range node.Children { + for _, v := range c { + StructToXML(e, v, sorted) + } + } + } + + e.EncodeToken(xml.EndElement{Name: node.Name}) + return e.Flush() +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/api.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/api.go new file mode 100644 index 0000000..2b33431 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/api.go @@ -0,0 +1,11629 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package dynamodb + +import ( + "fmt" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/private/protocol" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" +) + +const opBatchGetItem = "BatchGetItem" + +// BatchGetItemRequest generates a "aws/request.Request" representing the +// client's request for the BatchGetItem operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See BatchGetItem for more information on using the BatchGetItem +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the BatchGetItemRequest method. +// req, resp := client.BatchGetItemRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchGetItem +func (c *DynamoDB) BatchGetItemRequest(input *BatchGetItemInput) (req *request.Request, output *BatchGetItemOutput) { + op := &request.Operation{ + Name: opBatchGetItem, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"RequestItems"}, + OutputTokens: []string{"UnprocessedKeys"}, + LimitToken: "", + TruncationToken: "", + }, + } + + if input == nil { + input = &BatchGetItemInput{} + } + + output = &BatchGetItemOutput{} + req = c.newRequest(op, input, output) + return +} + +// BatchGetItem API operation for Amazon DynamoDB. +// +// The BatchGetItem operation returns the attributes of one or more items from +// one or more tables. You identify requested items by primary key. +// +// A single operation can retrieve up to 16 MB of data, which can contain as +// many as 100 items. BatchGetItem will return a partial result if the response +// size limit is exceeded, the table's provisioned throughput is exceeded, or +// an internal processing failure occurs. If a partial result is returned, the +// operation returns a value for UnprocessedKeys. You can use this value to +// retry the operation starting with the next item to get. +// +// If you request more than 100 items BatchGetItem will return a ValidationException +// with the message "Too many items requested for the BatchGetItem call". +// +// For example, if you ask to retrieve 100 items, but each individual item is +// 300 KB in size, the system returns 52 items (so as not to exceed the 16 MB +// limit). It also returns an appropriate UnprocessedKeys value so you can get +// the next page of results. If desired, your application can include its own +// logic to assemble the pages of results into one data set. +// +// If none of the items can be processed due to insufficient provisioned throughput +// on all of the tables in the request, then BatchGetItem will return a ProvisionedThroughputExceededException. +// If at least one of the items is successfully processed, then BatchGetItem +// completes successfully, while returning the keys of the unread items in UnprocessedKeys. +// +// If DynamoDB returns any unprocessed items, you should retry the batch operation +// on those items. However, we strongly recommend that you use an exponential +// backoff algorithm. If you retry the batch operation immediately, the underlying +// read or write requests can still fail due to throttling on the individual +// tables. If you delay the batch operation using exponential backoff, the individual +// requests in the batch are much more likely to succeed. +// +// For more information, see Batch Operations and Error Handling (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ErrorHandling.html#BatchOperations) +// in the Amazon DynamoDB Developer Guide. +// +// By default, BatchGetItem performs eventually consistent reads on every table +// in the request. If you want strongly consistent reads instead, you can set +// ConsistentRead to true for any or all tables. +// +// In order to minimize response latency, BatchGetItem retrieves items in parallel. +// +// When designing your application, keep in mind that DynamoDB does not return +// items in any particular order. To help parse the response by item, include +// the primary key values for the items in your request in the ProjectionExpression +// parameter. +// +// If a requested item does not exist, it is not returned in the result. Requests +// for nonexistent items consume the minimum read capacity units according to +// the type of read. For more information, see Capacity Units Calculations (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html#CapacityUnitCalculations) +// in the Amazon DynamoDB Developer Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation BatchGetItem for usage and error information. +// +// Returned Error Codes: +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchGetItem +func (c *DynamoDB) BatchGetItem(input *BatchGetItemInput) (*BatchGetItemOutput, error) { + req, out := c.BatchGetItemRequest(input) + return out, req.Send() +} + +// BatchGetItemWithContext is the same as BatchGetItem with the addition of +// the ability to pass a context and additional request options. +// +// See BatchGetItem for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) BatchGetItemWithContext(ctx aws.Context, input *BatchGetItemInput, opts ...request.Option) (*BatchGetItemOutput, error) { + req, out := c.BatchGetItemRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// BatchGetItemPages iterates over the pages of a BatchGetItem operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See BatchGetItem method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a BatchGetItem operation. +// pageNum := 0 +// err := client.BatchGetItemPages(params, +// func(page *BatchGetItemOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *DynamoDB) BatchGetItemPages(input *BatchGetItemInput, fn func(*BatchGetItemOutput, bool) bool) error { + return c.BatchGetItemPagesWithContext(aws.BackgroundContext(), input, fn) +} + +// BatchGetItemPagesWithContext same as BatchGetItemPages except +// it takes a Context and allows setting request options on the pages. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) BatchGetItemPagesWithContext(ctx aws.Context, input *BatchGetItemInput, fn func(*BatchGetItemOutput, bool) bool, opts ...request.Option) error { + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + var inCpy *BatchGetItemInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.BatchGetItemRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + + cont := true + for p.Next() && cont { + cont = fn(p.Page().(*BatchGetItemOutput), !p.HasNextPage()) + } + return p.Err() +} + +const opBatchWriteItem = "BatchWriteItem" + +// BatchWriteItemRequest generates a "aws/request.Request" representing the +// client's request for the BatchWriteItem operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See BatchWriteItem for more information on using the BatchWriteItem +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the BatchWriteItemRequest method. +// req, resp := client.BatchWriteItemRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchWriteItem +func (c *DynamoDB) BatchWriteItemRequest(input *BatchWriteItemInput) (req *request.Request, output *BatchWriteItemOutput) { + op := &request.Operation{ + Name: opBatchWriteItem, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &BatchWriteItemInput{} + } + + output = &BatchWriteItemOutput{} + req = c.newRequest(op, input, output) + return +} + +// BatchWriteItem API operation for Amazon DynamoDB. +// +// The BatchWriteItem operation puts or deletes multiple items in one or more +// tables. A single call to BatchWriteItem can write up to 16 MB of data, which +// can comprise as many as 25 put or delete requests. Individual items to be +// written can be as large as 400 KB. +// +// BatchWriteItem cannot update items. To update items, use the UpdateItem action. +// +// The individual PutItem and DeleteItem operations specified in BatchWriteItem +// are atomic; however BatchWriteItem as a whole is not. If any requested operations +// fail because the table's provisioned throughput is exceeded or an internal +// processing failure occurs, the failed operations are returned in the UnprocessedItems +// response parameter. You can investigate and optionally resend the requests. +// Typically, you would call BatchWriteItem in a loop. Each iteration would +// check for unprocessed items and submit a new BatchWriteItem request with +// those unprocessed items until all items have been processed. +// +// Note that if none of the items can be processed due to insufficient provisioned +// throughput on all of the tables in the request, then BatchWriteItem will +// return a ProvisionedThroughputExceededException. +// +// If DynamoDB returns any unprocessed items, you should retry the batch operation +// on those items. However, we strongly recommend that you use an exponential +// backoff algorithm. If you retry the batch operation immediately, the underlying +// read or write requests can still fail due to throttling on the individual +// tables. If you delay the batch operation using exponential backoff, the individual +// requests in the batch are much more likely to succeed. +// +// For more information, see Batch Operations and Error Handling (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ErrorHandling.html#BatchOperations) +// in the Amazon DynamoDB Developer Guide. +// +// With BatchWriteItem, you can efficiently write or delete large amounts of +// data, such as from Amazon Elastic MapReduce (EMR), or copy data from another +// database into DynamoDB. In order to improve performance with these large-scale +// operations, BatchWriteItem does not behave in the same way as individual +// PutItem and DeleteItem calls would. For example, you cannot specify conditions +// on individual put and delete requests, and BatchWriteItem does not return +// deleted items in the response. +// +// If you use a programming language that supports concurrency, you can use +// threads to write items in parallel. Your application must include the necessary +// logic to manage the threads. With languages that don't support threading, +// you must update or delete the specified items one at a time. In both situations, +// BatchWriteItem performs the specified put and delete operations in parallel, +// giving you the power of the thread pool approach without having to introduce +// complexity into your application. +// +// Parallel processing reduces latency, but each specified put and delete request +// consumes the same number of write capacity units whether it is processed +// in parallel or not. Delete operations on nonexistent items consume one write +// capacity unit. +// +// If one or more of the following is true, DynamoDB rejects the entire batch +// write operation: +// +// * One or more tables specified in the BatchWriteItem request does not +// exist. +// +// * Primary key attributes specified on an item in the request do not match +// those in the corresponding table's primary key schema. +// +// * You try to perform multiple operations on the same item in the same +// BatchWriteItem request. For example, you cannot put and delete the same +// item in the same BatchWriteItem request. +// +// * There are more than 25 requests in the batch. +// +// * Any individual item in a batch exceeds 400 KB. +// +// * The total request size exceeds 16 MB. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation BatchWriteItem for usage and error information. +// +// Returned Error Codes: +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeItemCollectionSizeLimitExceededException "ItemCollectionSizeLimitExceededException" +// An item collection is too large. This exception is only returned for tables +// that have one or more local secondary indexes. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchWriteItem +func (c *DynamoDB) BatchWriteItem(input *BatchWriteItemInput) (*BatchWriteItemOutput, error) { + req, out := c.BatchWriteItemRequest(input) + return out, req.Send() +} + +// BatchWriteItemWithContext is the same as BatchWriteItem with the addition of +// the ability to pass a context and additional request options. +// +// See BatchWriteItem for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) BatchWriteItemWithContext(ctx aws.Context, input *BatchWriteItemInput, opts ...request.Option) (*BatchWriteItemOutput, error) { + req, out := c.BatchWriteItemRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opCreateBackup = "CreateBackup" + +// CreateBackupRequest generates a "aws/request.Request" representing the +// client's request for the CreateBackup operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See CreateBackup for more information on using the CreateBackup +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the CreateBackupRequest method. +// req, resp := client.CreateBackupRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateBackup +func (c *DynamoDB) CreateBackupRequest(input *CreateBackupInput) (req *request.Request, output *CreateBackupOutput) { + op := &request.Operation{ + Name: opCreateBackup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateBackupInput{} + } + + output = &CreateBackupOutput{} + req = c.newRequest(op, input, output) + return +} + +// CreateBackup API operation for Amazon DynamoDB. +// +// Creates a backup for an existing table. +// +// Each time you create an On-Demand Backup, the entire table data is backed +// up. There is no limit to the number of on-demand backups that can be taken. +// +// You can call CreateBackup at a maximum rate of 50 times per second. +// +// All backups in DynamoDB work without consuming any provisioned throughput +// on the table. This results in a fast, low-cost, and scalable backup process. +// In general, the larger the table, the more time it takes to back up. The +// backup is stored in an S3 data store that is maintained and managed by DynamoDB. +// +// Backups incorporate all writes (delete, put, update) that were completed +// within the last minute before the backup request was initiated. Backups might +// include some writes (delete, put, update) that were completed before the +// backup request was finished. +// +// For example, if you submit the backup request on 2018-12-14 at 14:25:00, +// the backup is guaranteed to contain all data committed to the table up to +// 14:24:00, and data committed after 14:26:00 will not be. The backup may or +// may not contain data modifications made between 14:24:00 and 14:26:00. On-Demand +// Backup does not support causal consistency. +// +// Along with data, the following are also included on the backups: +// +// * Global secondary indexes (GSIs) +// +// * Local secondary indexes (LSIs) +// +// * Streams +// +// * Provisioned read and write capacity +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation CreateBackup for usage and error information. +// +// Returned Error Codes: +// * ErrCodeTableNotFoundException "TableNotFoundException" +// A table with the name TableName does not currently exist within the subscriber's +// account. +// +// * ErrCodeTableInUseException "TableInUseException" +// A table by that name is either being created or deleted. +// +// * ErrCodeContinuousBackupsUnavailableException "ContinuousBackupsUnavailableException" +// Backups have not yet been enabled for this table. +// +// * ErrCodeBackupInUseException "BackupInUseException" +// There is another ongoing conflicting backup control plane operation on the +// table. The backups is either being created, deleted or restored to a table. +// +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateBackup +func (c *DynamoDB) CreateBackup(input *CreateBackupInput) (*CreateBackupOutput, error) { + req, out := c.CreateBackupRequest(input) + return out, req.Send() +} + +// CreateBackupWithContext is the same as CreateBackup with the addition of +// the ability to pass a context and additional request options. +// +// See CreateBackup for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) CreateBackupWithContext(ctx aws.Context, input *CreateBackupInput, opts ...request.Option) (*CreateBackupOutput, error) { + req, out := c.CreateBackupRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opCreateGlobalTable = "CreateGlobalTable" + +// CreateGlobalTableRequest generates a "aws/request.Request" representing the +// client's request for the CreateGlobalTable operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See CreateGlobalTable for more information on using the CreateGlobalTable +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the CreateGlobalTableRequest method. +// req, resp := client.CreateGlobalTableRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateGlobalTable +func (c *DynamoDB) CreateGlobalTableRequest(input *CreateGlobalTableInput) (req *request.Request, output *CreateGlobalTableOutput) { + op := &request.Operation{ + Name: opCreateGlobalTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateGlobalTableInput{} + } + + output = &CreateGlobalTableOutput{} + req = c.newRequest(op, input, output) + return +} + +// CreateGlobalTable API operation for Amazon DynamoDB. +// +// Creates a global table from an existing table. A global table creates a replication +// relationship between two or more DynamoDB tables with the same table name +// in the provided regions. +// +// Tables can only be added as the replicas of a global table group under the +// following conditions: +// +// * The tables must have the same name. +// +// * The tables must contain no items. +// +// * The tables must have the same hash key and sort key (if present). +// +// * The tables must have DynamoDB Streams enabled (NEW_AND_OLD_IMAGES). +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation CreateGlobalTable for usage and error information. +// +// Returned Error Codes: +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// * ErrCodeGlobalTableAlreadyExistsException "GlobalTableAlreadyExistsException" +// The specified global table already exists. +// +// * ErrCodeTableNotFoundException "TableNotFoundException" +// A table with the name TableName does not currently exist within the subscriber's +// account. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateGlobalTable +func (c *DynamoDB) CreateGlobalTable(input *CreateGlobalTableInput) (*CreateGlobalTableOutput, error) { + req, out := c.CreateGlobalTableRequest(input) + return out, req.Send() +} + +// CreateGlobalTableWithContext is the same as CreateGlobalTable with the addition of +// the ability to pass a context and additional request options. +// +// See CreateGlobalTable for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) CreateGlobalTableWithContext(ctx aws.Context, input *CreateGlobalTableInput, opts ...request.Option) (*CreateGlobalTableOutput, error) { + req, out := c.CreateGlobalTableRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opCreateTable = "CreateTable" + +// CreateTableRequest generates a "aws/request.Request" representing the +// client's request for the CreateTable operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See CreateTable for more information on using the CreateTable +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the CreateTableRequest method. +// req, resp := client.CreateTableRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateTable +func (c *DynamoDB) CreateTableRequest(input *CreateTableInput) (req *request.Request, output *CreateTableOutput) { + op := &request.Operation{ + Name: opCreateTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &CreateTableInput{} + } + + output = &CreateTableOutput{} + req = c.newRequest(op, input, output) + return +} + +// CreateTable API operation for Amazon DynamoDB. +// +// The CreateTable operation adds a new table to your account. In an AWS account, +// table names must be unique within each region. That is, you can have two +// tables with same name if you create the tables in different regions. +// +// CreateTable is an asynchronous operation. Upon receiving a CreateTable request, +// DynamoDB immediately returns a response with a TableStatus of CREATING. After +// the table is created, DynamoDB sets the TableStatus to ACTIVE. You can perform +// read and write operations only on an ACTIVE table. +// +// You can optionally define secondary indexes on the new table, as part of +// the CreateTable operation. If you want to create multiple tables with secondary +// indexes on them, you must create the tables sequentially. Only one table +// with secondary indexes can be in the CREATING state at any given time. +// +// You can use the DescribeTable action to check the table status. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation CreateTable for usage and error information. +// +// Returned Error Codes: +// * ErrCodeResourceInUseException "ResourceInUseException" +// The operation conflicts with the resource's availability. For example, you +// attempted to recreate an existing table, or tried to delete a table currently +// in the CREATING state. +// +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateTable +func (c *DynamoDB) CreateTable(input *CreateTableInput) (*CreateTableOutput, error) { + req, out := c.CreateTableRequest(input) + return out, req.Send() +} + +// CreateTableWithContext is the same as CreateTable with the addition of +// the ability to pass a context and additional request options. +// +// See CreateTable for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) CreateTableWithContext(ctx aws.Context, input *CreateTableInput, opts ...request.Option) (*CreateTableOutput, error) { + req, out := c.CreateTableRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDeleteBackup = "DeleteBackup" + +// DeleteBackupRequest generates a "aws/request.Request" representing the +// client's request for the DeleteBackup operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DeleteBackup for more information on using the DeleteBackup +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DeleteBackupRequest method. +// req, resp := client.DeleteBackupRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteBackup +func (c *DynamoDB) DeleteBackupRequest(input *DeleteBackupInput) (req *request.Request, output *DeleteBackupOutput) { + op := &request.Operation{ + Name: opDeleteBackup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteBackupInput{} + } + + output = &DeleteBackupOutput{} + req = c.newRequest(op, input, output) + return +} + +// DeleteBackup API operation for Amazon DynamoDB. +// +// Deletes an existing backup of a table. +// +// You can call DeleteBackup at a maximum rate of 10 times per second. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DeleteBackup for usage and error information. +// +// Returned Error Codes: +// * ErrCodeBackupNotFoundException "BackupNotFoundException" +// Backup not found for the given BackupARN. +// +// * ErrCodeBackupInUseException "BackupInUseException" +// There is another ongoing conflicting backup control plane operation on the +// table. The backups is either being created, deleted or restored to a table. +// +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteBackup +func (c *DynamoDB) DeleteBackup(input *DeleteBackupInput) (*DeleteBackupOutput, error) { + req, out := c.DeleteBackupRequest(input) + return out, req.Send() +} + +// DeleteBackupWithContext is the same as DeleteBackup with the addition of +// the ability to pass a context and additional request options. +// +// See DeleteBackup for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DeleteBackupWithContext(ctx aws.Context, input *DeleteBackupInput, opts ...request.Option) (*DeleteBackupOutput, error) { + req, out := c.DeleteBackupRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDeleteItem = "DeleteItem" + +// DeleteItemRequest generates a "aws/request.Request" representing the +// client's request for the DeleteItem operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DeleteItem for more information on using the DeleteItem +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DeleteItemRequest method. +// req, resp := client.DeleteItemRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteItem +func (c *DynamoDB) DeleteItemRequest(input *DeleteItemInput) (req *request.Request, output *DeleteItemOutput) { + op := &request.Operation{ + Name: opDeleteItem, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteItemInput{} + } + + output = &DeleteItemOutput{} + req = c.newRequest(op, input, output) + return +} + +// DeleteItem API operation for Amazon DynamoDB. +// +// Deletes a single item in a table by primary key. You can perform a conditional +// delete operation that deletes the item if it exists, or if it has an expected +// attribute value. +// +// In addition to deleting an item, you can also return the item's attribute +// values in the same operation, using the ReturnValues parameter. +// +// Unless you specify conditions, the DeleteItem is an idempotent operation; +// running it multiple times on the same item or attribute does not result in +// an error response. +// +// Conditional deletes are useful for deleting items only if specific conditions +// are met. If those conditions are met, DynamoDB performs the delete. Otherwise, +// the item is not deleted. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DeleteItem for usage and error information. +// +// Returned Error Codes: +// * ErrCodeConditionalCheckFailedException "ConditionalCheckFailedException" +// A condition specified in the operation could not be evaluated. +// +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeItemCollectionSizeLimitExceededException "ItemCollectionSizeLimitExceededException" +// An item collection is too large. This exception is only returned for tables +// that have one or more local secondary indexes. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteItem +func (c *DynamoDB) DeleteItem(input *DeleteItemInput) (*DeleteItemOutput, error) { + req, out := c.DeleteItemRequest(input) + return out, req.Send() +} + +// DeleteItemWithContext is the same as DeleteItem with the addition of +// the ability to pass a context and additional request options. +// +// See DeleteItem for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DeleteItemWithContext(ctx aws.Context, input *DeleteItemInput, opts ...request.Option) (*DeleteItemOutput, error) { + req, out := c.DeleteItemRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDeleteTable = "DeleteTable" + +// DeleteTableRequest generates a "aws/request.Request" representing the +// client's request for the DeleteTable operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DeleteTable for more information on using the DeleteTable +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DeleteTableRequest method. +// req, resp := client.DeleteTableRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteTable +func (c *DynamoDB) DeleteTableRequest(input *DeleteTableInput) (req *request.Request, output *DeleteTableOutput) { + op := &request.Operation{ + Name: opDeleteTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DeleteTableInput{} + } + + output = &DeleteTableOutput{} + req = c.newRequest(op, input, output) + return +} + +// DeleteTable API operation for Amazon DynamoDB. +// +// The DeleteTable operation deletes a table and all of its items. After a DeleteTable +// request, the specified table is in the DELETING state until DynamoDB completes +// the deletion. If the table is in the ACTIVE state, you can delete it. If +// a table is in CREATING or UPDATING states, then DynamoDB returns a ResourceInUseException. +// If the specified table does not exist, DynamoDB returns a ResourceNotFoundException. +// If table is already in the DELETING state, no error is returned. +// +// DynamoDB might continue to accept data read and write operations, such as +// GetItem and PutItem, on a table in the DELETING state until the table deletion +// is complete. +// +// When you delete a table, any indexes on that table are also deleted. +// +// If you have DynamoDB Streams enabled on the table, then the corresponding +// stream on that table goes into the DISABLED state, and the stream is automatically +// deleted after 24 hours. +// +// Use the DescribeTable action to check the status of the table. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DeleteTable for usage and error information. +// +// Returned Error Codes: +// * ErrCodeResourceInUseException "ResourceInUseException" +// The operation conflicts with the resource's availability. For example, you +// attempted to recreate an existing table, or tried to delete a table currently +// in the CREATING state. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteTable +func (c *DynamoDB) DeleteTable(input *DeleteTableInput) (*DeleteTableOutput, error) { + req, out := c.DeleteTableRequest(input) + return out, req.Send() +} + +// DeleteTableWithContext is the same as DeleteTable with the addition of +// the ability to pass a context and additional request options. +// +// See DeleteTable for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DeleteTableWithContext(ctx aws.Context, input *DeleteTableInput, opts ...request.Option) (*DeleteTableOutput, error) { + req, out := c.DeleteTableRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDescribeBackup = "DescribeBackup" + +// DescribeBackupRequest generates a "aws/request.Request" representing the +// client's request for the DescribeBackup operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DescribeBackup for more information on using the DescribeBackup +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DescribeBackupRequest method. +// req, resp := client.DescribeBackupRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeBackup +func (c *DynamoDB) DescribeBackupRequest(input *DescribeBackupInput) (req *request.Request, output *DescribeBackupOutput) { + op := &request.Operation{ + Name: opDescribeBackup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeBackupInput{} + } + + output = &DescribeBackupOutput{} + req = c.newRequest(op, input, output) + return +} + +// DescribeBackup API operation for Amazon DynamoDB. +// +// Describes an existing backup of a table. +// +// You can call DescribeBackup at a maximum rate of 10 times per second. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DescribeBackup for usage and error information. +// +// Returned Error Codes: +// * ErrCodeBackupNotFoundException "BackupNotFoundException" +// Backup not found for the given BackupARN. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeBackup +func (c *DynamoDB) DescribeBackup(input *DescribeBackupInput) (*DescribeBackupOutput, error) { + req, out := c.DescribeBackupRequest(input) + return out, req.Send() +} + +// DescribeBackupWithContext is the same as DescribeBackup with the addition of +// the ability to pass a context and additional request options. +// +// See DescribeBackup for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DescribeBackupWithContext(ctx aws.Context, input *DescribeBackupInput, opts ...request.Option) (*DescribeBackupOutput, error) { + req, out := c.DescribeBackupRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDescribeContinuousBackups = "DescribeContinuousBackups" + +// DescribeContinuousBackupsRequest generates a "aws/request.Request" representing the +// client's request for the DescribeContinuousBackups operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DescribeContinuousBackups for more information on using the DescribeContinuousBackups +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DescribeContinuousBackupsRequest method. +// req, resp := client.DescribeContinuousBackupsRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeContinuousBackups +func (c *DynamoDB) DescribeContinuousBackupsRequest(input *DescribeContinuousBackupsInput) (req *request.Request, output *DescribeContinuousBackupsOutput) { + op := &request.Operation{ + Name: opDescribeContinuousBackups, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeContinuousBackupsInput{} + } + + output = &DescribeContinuousBackupsOutput{} + req = c.newRequest(op, input, output) + return +} + +// DescribeContinuousBackups API operation for Amazon DynamoDB. +// +// Checks the status of the backup restore settings on the specified table. +// If backups are enabled, ContinuousBackupsStatus will bet set to ENABLED. +// +// You can call DescribeContinuousBackups at a maximum rate of 10 times per +// second. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DescribeContinuousBackups for usage and error information. +// +// Returned Error Codes: +// * ErrCodeTableNotFoundException "TableNotFoundException" +// A table with the name TableName does not currently exist within the subscriber's +// account. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeContinuousBackups +func (c *DynamoDB) DescribeContinuousBackups(input *DescribeContinuousBackupsInput) (*DescribeContinuousBackupsOutput, error) { + req, out := c.DescribeContinuousBackupsRequest(input) + return out, req.Send() +} + +// DescribeContinuousBackupsWithContext is the same as DescribeContinuousBackups with the addition of +// the ability to pass a context and additional request options. +// +// See DescribeContinuousBackups for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DescribeContinuousBackupsWithContext(ctx aws.Context, input *DescribeContinuousBackupsInput, opts ...request.Option) (*DescribeContinuousBackupsOutput, error) { + req, out := c.DescribeContinuousBackupsRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDescribeGlobalTable = "DescribeGlobalTable" + +// DescribeGlobalTableRequest generates a "aws/request.Request" representing the +// client's request for the DescribeGlobalTable operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DescribeGlobalTable for more information on using the DescribeGlobalTable +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DescribeGlobalTableRequest method. +// req, resp := client.DescribeGlobalTableRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeGlobalTable +func (c *DynamoDB) DescribeGlobalTableRequest(input *DescribeGlobalTableInput) (req *request.Request, output *DescribeGlobalTableOutput) { + op := &request.Operation{ + Name: opDescribeGlobalTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeGlobalTableInput{} + } + + output = &DescribeGlobalTableOutput{} + req = c.newRequest(op, input, output) + return +} + +// DescribeGlobalTable API operation for Amazon DynamoDB. +// +// Returns information about the global table. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DescribeGlobalTable for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// * ErrCodeGlobalTableNotFoundException "GlobalTableNotFoundException" +// The specified global table does not exist. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeGlobalTable +func (c *DynamoDB) DescribeGlobalTable(input *DescribeGlobalTableInput) (*DescribeGlobalTableOutput, error) { + req, out := c.DescribeGlobalTableRequest(input) + return out, req.Send() +} + +// DescribeGlobalTableWithContext is the same as DescribeGlobalTable with the addition of +// the ability to pass a context and additional request options. +// +// See DescribeGlobalTable for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DescribeGlobalTableWithContext(ctx aws.Context, input *DescribeGlobalTableInput, opts ...request.Option) (*DescribeGlobalTableOutput, error) { + req, out := c.DescribeGlobalTableRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDescribeLimits = "DescribeLimits" + +// DescribeLimitsRequest generates a "aws/request.Request" representing the +// client's request for the DescribeLimits operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DescribeLimits for more information on using the DescribeLimits +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DescribeLimitsRequest method. +// req, resp := client.DescribeLimitsRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeLimits +func (c *DynamoDB) DescribeLimitsRequest(input *DescribeLimitsInput) (req *request.Request, output *DescribeLimitsOutput) { + op := &request.Operation{ + Name: opDescribeLimits, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeLimitsInput{} + } + + output = &DescribeLimitsOutput{} + req = c.newRequest(op, input, output) + return +} + +// DescribeLimits API operation for Amazon DynamoDB. +// +// Returns the current provisioned-capacity limits for your AWS account in a +// region, both for the region as a whole and for any one DynamoDB table that +// you create there. +// +// When you establish an AWS account, the account has initial limits on the +// maximum read capacity units and write capacity units that you can provision +// across all of your DynamoDB tables in a given region. Also, there are per-table +// limits that apply when you create a table there. For more information, see +// Limits (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) +// page in the Amazon DynamoDB Developer Guide. +// +// Although you can increase these limits by filing a case at AWS Support Center +// (https://console.aws.amazon.com/support/home#/), obtaining the increase is +// not instantaneous. The DescribeLimits action lets you write code to compare +// the capacity you are currently using to those limits imposed by your account +// so that you have enough time to apply for an increase before you hit a limit. +// +// For example, you could use one of the AWS SDKs to do the following: +// +// Call DescribeLimits for a particular region to obtain your current account +// limits on provisioned capacity there. +// +// Create a variable to hold the aggregate read capacity units provisioned for +// all your tables in that region, and one to hold the aggregate write capacity +// units. Zero them both. +// +// Call ListTables to obtain a list of all your DynamoDB tables. +// +// For each table name listed by ListTables, do the following: +// +// Call DescribeTable with the table name. +// +// Use the data returned by DescribeTable to add the read capacity units and +// write capacity units provisioned for the table itself to your variables. +// +// If the table has one or more global secondary indexes (GSIs), loop over these +// GSIs and add their provisioned capacity values to your variables as well. +// +// Report the account limits for that region returned by DescribeLimits, along +// with the total current provisioned capacity levels you have calculated. +// +// This will let you see whether you are getting close to your account-level +// limits. +// +// The per-table limits apply only when you are creating a new table. They restrict +// the sum of the provisioned capacity of the new table itself and all its global +// secondary indexes. +// +// For existing tables and their GSIs, DynamoDB will not let you increase provisioned +// capacity extremely rapidly, but the only upper limit that applies is that +// the aggregate provisioned capacity over all your tables and GSIs cannot exceed +// either of the per-account limits. +// +// DescribeLimits should only be called periodically. You can expect throttling +// errors if you call it more than once in a minute. +// +// The DescribeLimits Request element has no content. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DescribeLimits for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeLimits +func (c *DynamoDB) DescribeLimits(input *DescribeLimitsInput) (*DescribeLimitsOutput, error) { + req, out := c.DescribeLimitsRequest(input) + return out, req.Send() +} + +// DescribeLimitsWithContext is the same as DescribeLimits with the addition of +// the ability to pass a context and additional request options. +// +// See DescribeLimits for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DescribeLimitsWithContext(ctx aws.Context, input *DescribeLimitsInput, opts ...request.Option) (*DescribeLimitsOutput, error) { + req, out := c.DescribeLimitsRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDescribeTable = "DescribeTable" + +// DescribeTableRequest generates a "aws/request.Request" representing the +// client's request for the DescribeTable operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DescribeTable for more information on using the DescribeTable +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DescribeTableRequest method. +// req, resp := client.DescribeTableRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTable +func (c *DynamoDB) DescribeTableRequest(input *DescribeTableInput) (req *request.Request, output *DescribeTableOutput) { + op := &request.Operation{ + Name: opDescribeTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeTableInput{} + } + + output = &DescribeTableOutput{} + req = c.newRequest(op, input, output) + return +} + +// DescribeTable API operation for Amazon DynamoDB. +// +// Returns information about the table, including the current status of the +// table, when it was created, the primary key schema, and any indexes on the +// table. +// +// If you issue a DescribeTable request immediately after a CreateTable request, +// DynamoDB might return a ResourceNotFoundException. This is because DescribeTable +// uses an eventually consistent query, and the metadata for your table might +// not be available at that moment. Wait for a few seconds, and then try the +// DescribeTable request again. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DescribeTable for usage and error information. +// +// Returned Error Codes: +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTable +func (c *DynamoDB) DescribeTable(input *DescribeTableInput) (*DescribeTableOutput, error) { + req, out := c.DescribeTableRequest(input) + return out, req.Send() +} + +// DescribeTableWithContext is the same as DescribeTable with the addition of +// the ability to pass a context and additional request options. +// +// See DescribeTable for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DescribeTableWithContext(ctx aws.Context, input *DescribeTableInput, opts ...request.Option) (*DescribeTableOutput, error) { + req, out := c.DescribeTableRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDescribeTimeToLive = "DescribeTimeToLive" + +// DescribeTimeToLiveRequest generates a "aws/request.Request" representing the +// client's request for the DescribeTimeToLive operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DescribeTimeToLive for more information on using the DescribeTimeToLive +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DescribeTimeToLiveRequest method. +// req, resp := client.DescribeTimeToLiveRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTimeToLive +func (c *DynamoDB) DescribeTimeToLiveRequest(input *DescribeTimeToLiveInput) (req *request.Request, output *DescribeTimeToLiveOutput) { + op := &request.Operation{ + Name: opDescribeTimeToLive, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeTimeToLiveInput{} + } + + output = &DescribeTimeToLiveOutput{} + req = c.newRequest(op, input, output) + return +} + +// DescribeTimeToLive API operation for Amazon DynamoDB. +// +// Gives a description of the Time to Live (TTL) status on the specified table. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation DescribeTimeToLive for usage and error information. +// +// Returned Error Codes: +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTimeToLive +func (c *DynamoDB) DescribeTimeToLive(input *DescribeTimeToLiveInput) (*DescribeTimeToLiveOutput, error) { + req, out := c.DescribeTimeToLiveRequest(input) + return out, req.Send() +} + +// DescribeTimeToLiveWithContext is the same as DescribeTimeToLive with the addition of +// the ability to pass a context and additional request options. +// +// See DescribeTimeToLive for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) DescribeTimeToLiveWithContext(ctx aws.Context, input *DescribeTimeToLiveInput, opts ...request.Option) (*DescribeTimeToLiveOutput, error) { + req, out := c.DescribeTimeToLiveRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opGetItem = "GetItem" + +// GetItemRequest generates a "aws/request.Request" representing the +// client's request for the GetItem operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See GetItem for more information on using the GetItem +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the GetItemRequest method. +// req, resp := client.GetItemRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GetItem +func (c *DynamoDB) GetItemRequest(input *GetItemInput) (req *request.Request, output *GetItemOutput) { + op := &request.Operation{ + Name: opGetItem, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetItemInput{} + } + + output = &GetItemOutput{} + req = c.newRequest(op, input, output) + return +} + +// GetItem API operation for Amazon DynamoDB. +// +// The GetItem operation returns a set of attributes for the item with the given +// primary key. If there is no matching item, GetItem does not return any data +// and there will be no Item element in the response. +// +// GetItem provides an eventually consistent read by default. If your application +// requires a strongly consistent read, set ConsistentRead to true. Although +// a strongly consistent read might take more time than an eventually consistent +// read, it always returns the last updated value. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation GetItem for usage and error information. +// +// Returned Error Codes: +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GetItem +func (c *DynamoDB) GetItem(input *GetItemInput) (*GetItemOutput, error) { + req, out := c.GetItemRequest(input) + return out, req.Send() +} + +// GetItemWithContext is the same as GetItem with the addition of +// the ability to pass a context and additional request options. +// +// See GetItem for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) GetItemWithContext(ctx aws.Context, input *GetItemInput, opts ...request.Option) (*GetItemOutput, error) { + req, out := c.GetItemRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opListBackups = "ListBackups" + +// ListBackupsRequest generates a "aws/request.Request" representing the +// client's request for the ListBackups operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See ListBackups for more information on using the ListBackups +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the ListBackupsRequest method. +// req, resp := client.ListBackupsRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListBackups +func (c *DynamoDB) ListBackupsRequest(input *ListBackupsInput) (req *request.Request, output *ListBackupsOutput) { + op := &request.Operation{ + Name: opListBackups, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ListBackupsInput{} + } + + output = &ListBackupsOutput{} + req = c.newRequest(op, input, output) + return +} + +// ListBackups API operation for Amazon DynamoDB. +// +// List backups associated with an AWS account. To list backups for a given +// table, specify TableName. ListBackups returns a paginated list of results +// with at most 1MB worth of items in a page. You can also specify a limit for +// the maximum number of entries to be returned in a page. +// +// In the request, start time is inclusive but end time is exclusive. Note that +// these limits are for the time at which the original backup was requested. +// +// You can call ListBackups a maximum of 5 times per second. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation ListBackups for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListBackups +func (c *DynamoDB) ListBackups(input *ListBackupsInput) (*ListBackupsOutput, error) { + req, out := c.ListBackupsRequest(input) + return out, req.Send() +} + +// ListBackupsWithContext is the same as ListBackups with the addition of +// the ability to pass a context and additional request options. +// +// See ListBackups for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) ListBackupsWithContext(ctx aws.Context, input *ListBackupsInput, opts ...request.Option) (*ListBackupsOutput, error) { + req, out := c.ListBackupsRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opListGlobalTables = "ListGlobalTables" + +// ListGlobalTablesRequest generates a "aws/request.Request" representing the +// client's request for the ListGlobalTables operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See ListGlobalTables for more information on using the ListGlobalTables +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the ListGlobalTablesRequest method. +// req, resp := client.ListGlobalTablesRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListGlobalTables +func (c *DynamoDB) ListGlobalTablesRequest(input *ListGlobalTablesInput) (req *request.Request, output *ListGlobalTablesOutput) { + op := &request.Operation{ + Name: opListGlobalTables, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ListGlobalTablesInput{} + } + + output = &ListGlobalTablesOutput{} + req = c.newRequest(op, input, output) + return +} + +// ListGlobalTables API operation for Amazon DynamoDB. +// +// Lists all the global tables. Only those global tables that have replicas +// in the region specified as input are returned. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation ListGlobalTables for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListGlobalTables +func (c *DynamoDB) ListGlobalTables(input *ListGlobalTablesInput) (*ListGlobalTablesOutput, error) { + req, out := c.ListGlobalTablesRequest(input) + return out, req.Send() +} + +// ListGlobalTablesWithContext is the same as ListGlobalTables with the addition of +// the ability to pass a context and additional request options. +// +// See ListGlobalTables for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) ListGlobalTablesWithContext(ctx aws.Context, input *ListGlobalTablesInput, opts ...request.Option) (*ListGlobalTablesOutput, error) { + req, out := c.ListGlobalTablesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opListTables = "ListTables" + +// ListTablesRequest generates a "aws/request.Request" representing the +// client's request for the ListTables operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See ListTables for more information on using the ListTables +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the ListTablesRequest method. +// req, resp := client.ListTablesRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTables +func (c *DynamoDB) ListTablesRequest(input *ListTablesInput) (req *request.Request, output *ListTablesOutput) { + op := &request.Operation{ + Name: opListTables, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"ExclusiveStartTableName"}, + OutputTokens: []string{"LastEvaluatedTableName"}, + LimitToken: "Limit", + TruncationToken: "", + }, + } + + if input == nil { + input = &ListTablesInput{} + } + + output = &ListTablesOutput{} + req = c.newRequest(op, input, output) + return +} + +// ListTables API operation for Amazon DynamoDB. +// +// Returns an array of table names associated with the current account and endpoint. +// The output from ListTables is paginated, with each page returning a maximum +// of 100 table names. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation ListTables for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTables +func (c *DynamoDB) ListTables(input *ListTablesInput) (*ListTablesOutput, error) { + req, out := c.ListTablesRequest(input) + return out, req.Send() +} + +// ListTablesWithContext is the same as ListTables with the addition of +// the ability to pass a context and additional request options. +// +// See ListTables for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) ListTablesWithContext(ctx aws.Context, input *ListTablesInput, opts ...request.Option) (*ListTablesOutput, error) { + req, out := c.ListTablesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// ListTablesPages iterates over the pages of a ListTables operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See ListTables method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a ListTables operation. +// pageNum := 0 +// err := client.ListTablesPages(params, +// func(page *ListTablesOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *DynamoDB) ListTablesPages(input *ListTablesInput, fn func(*ListTablesOutput, bool) bool) error { + return c.ListTablesPagesWithContext(aws.BackgroundContext(), input, fn) +} + +// ListTablesPagesWithContext same as ListTablesPages except +// it takes a Context and allows setting request options on the pages. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) ListTablesPagesWithContext(ctx aws.Context, input *ListTablesInput, fn func(*ListTablesOutput, bool) bool, opts ...request.Option) error { + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + var inCpy *ListTablesInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.ListTablesRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + + cont := true + for p.Next() && cont { + cont = fn(p.Page().(*ListTablesOutput), !p.HasNextPage()) + } + return p.Err() +} + +const opListTagsOfResource = "ListTagsOfResource" + +// ListTagsOfResourceRequest generates a "aws/request.Request" representing the +// client's request for the ListTagsOfResource operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See ListTagsOfResource for more information on using the ListTagsOfResource +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the ListTagsOfResourceRequest method. +// req, resp := client.ListTagsOfResourceRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTagsOfResource +func (c *DynamoDB) ListTagsOfResourceRequest(input *ListTagsOfResourceInput) (req *request.Request, output *ListTagsOfResourceOutput) { + op := &request.Operation{ + Name: opListTagsOfResource, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &ListTagsOfResourceInput{} + } + + output = &ListTagsOfResourceOutput{} + req = c.newRequest(op, input, output) + return +} + +// ListTagsOfResource API operation for Amazon DynamoDB. +// +// List all tags on an Amazon DynamoDB resource. You can call ListTagsOfResource +// up to 10 times per second, per account. +// +// For an overview on tagging DynamoDB resources, see Tagging for DynamoDB (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tagging.html) +// in the Amazon DynamoDB Developer Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation ListTagsOfResource for usage and error information. +// +// Returned Error Codes: +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTagsOfResource +func (c *DynamoDB) ListTagsOfResource(input *ListTagsOfResourceInput) (*ListTagsOfResourceOutput, error) { + req, out := c.ListTagsOfResourceRequest(input) + return out, req.Send() +} + +// ListTagsOfResourceWithContext is the same as ListTagsOfResource with the addition of +// the ability to pass a context and additional request options. +// +// See ListTagsOfResource for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) ListTagsOfResourceWithContext(ctx aws.Context, input *ListTagsOfResourceInput, opts ...request.Option) (*ListTagsOfResourceOutput, error) { + req, out := c.ListTagsOfResourceRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opPutItem = "PutItem" + +// PutItemRequest generates a "aws/request.Request" representing the +// client's request for the PutItem operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See PutItem for more information on using the PutItem +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the PutItemRequest method. +// req, resp := client.PutItemRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/PutItem +func (c *DynamoDB) PutItemRequest(input *PutItemInput) (req *request.Request, output *PutItemOutput) { + op := &request.Operation{ + Name: opPutItem, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &PutItemInput{} + } + + output = &PutItemOutput{} + req = c.newRequest(op, input, output) + return +} + +// PutItem API operation for Amazon DynamoDB. +// +// Creates a new item, or replaces an old item with a new item. If an item that +// has the same primary key as the new item already exists in the specified +// table, the new item completely replaces the existing item. You can perform +// a conditional put operation (add a new item if one with the specified primary +// key doesn't exist), or replace an existing item if it has certain attribute +// values. You can return the item's attribute values in the same operation, +// using the ReturnValues parameter. +// +// This topic provides general information about the PutItem API. +// +// For information on how to call the PutItem API using the AWS SDK in specific +// languages, see the following: +// +// PutItem in the AWS Command Line Interface (http://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for .NET (http://docs.aws.amazon.com/goto/DotNetSDKV3/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for C++ (http://docs.aws.amazon.com/goto/SdkForCpp/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for Go (http://docs.aws.amazon.com/goto/SdkForGoV1/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for Java (http://docs.aws.amazon.com/goto/SdkForJava/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for JavaScript (http://docs.aws.amazon.com/goto/AWSJavaScriptSDK/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for PHP V3 (http://docs.aws.amazon.com/goto/SdkForPHPV3/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for Python (http://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/PutItem) +// +// PutItem in the AWS SDK for Ruby V2 (http://docs.aws.amazon.com/goto/SdkForRubyV2/dynamodb-2012-08-10/PutItem) +// +// When you add an item, the primary key attribute(s) are the only required +// attributes. Attribute values cannot be null. String and Binary type attributes +// must have lengths greater than zero. Set type attributes cannot be empty. +// Requests with empty values will be rejected with a ValidationException exception. +// +// To prevent a new item from replacing an existing item, use a conditional +// expression that contains the attribute_not_exists function with the name +// of the attribute being used as the partition key for the table. Since every +// record must contain that attribute, the attribute_not_exists function will +// only succeed if no matching item exists. +// +// For more information about PutItem, see Working with Items (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html) +// in the Amazon DynamoDB Developer Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation PutItem for usage and error information. +// +// Returned Error Codes: +// * ErrCodeConditionalCheckFailedException "ConditionalCheckFailedException" +// A condition specified in the operation could not be evaluated. +// +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeItemCollectionSizeLimitExceededException "ItemCollectionSizeLimitExceededException" +// An item collection is too large. This exception is only returned for tables +// that have one or more local secondary indexes. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/PutItem +func (c *DynamoDB) PutItem(input *PutItemInput) (*PutItemOutput, error) { + req, out := c.PutItemRequest(input) + return out, req.Send() +} + +// PutItemWithContext is the same as PutItem with the addition of +// the ability to pass a context and additional request options. +// +// See PutItem for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) PutItemWithContext(ctx aws.Context, input *PutItemInput, opts ...request.Option) (*PutItemOutput, error) { + req, out := c.PutItemRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opQuery = "Query" + +// QueryRequest generates a "aws/request.Request" representing the +// client's request for the Query operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See Query for more information on using the Query +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the QueryRequest method. +// req, resp := client.QueryRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Query +func (c *DynamoDB) QueryRequest(input *QueryInput) (req *request.Request, output *QueryOutput) { + op := &request.Operation{ + Name: opQuery, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"ExclusiveStartKey"}, + OutputTokens: []string{"LastEvaluatedKey"}, + LimitToken: "Limit", + TruncationToken: "", + }, + } + + if input == nil { + input = &QueryInput{} + } + + output = &QueryOutput{} + req = c.newRequest(op, input, output) + return +} + +// Query API operation for Amazon DynamoDB. +// +// The Query operation finds items based on primary key values. You can query +// any table or secondary index that has a composite primary key (a partition +// key and a sort key). +// +// Use the KeyConditionExpression parameter to provide a specific value for +// the partition key. The Query operation will return all of the items from +// the table or index with that partition key value. You can optionally narrow +// the scope of the Query operation by specifying a sort key value and a comparison +// operator in KeyConditionExpression. To further refine the Query results, +// you can optionally provide a FilterExpression. A FilterExpression determines +// which items within the results should be returned to you. All of the other +// results are discarded. +// +// A Query operation always returns a result set. If no matching items are found, +// the result set will be empty. Queries that do not return results consume +// the minimum number of read capacity units for that type of read operation. +// +// DynamoDB calculates the number of read capacity units consumed based on item +// size, not on the amount of data that is returned to an application. The number +// of capacity units consumed will be the same whether you request all of the +// attributes (the default behavior) or just some of them (using a projection +// expression). The number will also be the same whether or not you use a FilterExpression. +// +// Query results are always sorted by the sort key value. If the data type of +// the sort key is Number, the results are returned in numeric order; otherwise, +// the results are returned in order of UTF-8 bytes. By default, the sort order +// is ascending. To reverse the order, set the ScanIndexForward parameter to +// false. +// +// A single Query operation will read up to the maximum number of items set +// (if using the Limit parameter) or a maximum of 1 MB of data and then apply +// any filtering to the results using FilterExpression. If LastEvaluatedKey +// is present in the response, you will need to paginate the result set. For +// more information, see Paginating the Results (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.Pagination) +// in the Amazon DynamoDB Developer Guide. +// +// FilterExpression is applied after a Query finishes, but before the results +// are returned. A FilterExpression cannot contain partition key or sort key +// attributes. You need to specify those attributes in the KeyConditionExpression. +// +// A Query operation can return an empty result set and a LastEvaluatedKey if +// all the items read for the page of results are filtered out. +// +// You can query a table, a local secondary index, or a global secondary index. +// For a query on a table or on a local secondary index, you can set the ConsistentRead +// parameter to true and obtain a strongly consistent result. Global secondary +// indexes support eventually consistent reads only, so do not specify ConsistentRead +// when querying a global secondary index. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation Query for usage and error information. +// +// Returned Error Codes: +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Query +func (c *DynamoDB) Query(input *QueryInput) (*QueryOutput, error) { + req, out := c.QueryRequest(input) + return out, req.Send() +} + +// QueryWithContext is the same as Query with the addition of +// the ability to pass a context and additional request options. +// +// See Query for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) QueryWithContext(ctx aws.Context, input *QueryInput, opts ...request.Option) (*QueryOutput, error) { + req, out := c.QueryRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// QueryPages iterates over the pages of a Query operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See Query method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a Query operation. +// pageNum := 0 +// err := client.QueryPages(params, +// func(page *QueryOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *DynamoDB) QueryPages(input *QueryInput, fn func(*QueryOutput, bool) bool) error { + return c.QueryPagesWithContext(aws.BackgroundContext(), input, fn) +} + +// QueryPagesWithContext same as QueryPages except +// it takes a Context and allows setting request options on the pages. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) QueryPagesWithContext(ctx aws.Context, input *QueryInput, fn func(*QueryOutput, bool) bool, opts ...request.Option) error { + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + var inCpy *QueryInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.QueryRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + + cont := true + for p.Next() && cont { + cont = fn(p.Page().(*QueryOutput), !p.HasNextPage()) + } + return p.Err() +} + +const opRestoreTableFromBackup = "RestoreTableFromBackup" + +// RestoreTableFromBackupRequest generates a "aws/request.Request" representing the +// client's request for the RestoreTableFromBackup operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See RestoreTableFromBackup for more information on using the RestoreTableFromBackup +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the RestoreTableFromBackupRequest method. +// req, resp := client.RestoreTableFromBackupRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/RestoreTableFromBackup +func (c *DynamoDB) RestoreTableFromBackupRequest(input *RestoreTableFromBackupInput) (req *request.Request, output *RestoreTableFromBackupOutput) { + op := &request.Operation{ + Name: opRestoreTableFromBackup, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &RestoreTableFromBackupInput{} + } + + output = &RestoreTableFromBackupOutput{} + req = c.newRequest(op, input, output) + return +} + +// RestoreTableFromBackup API operation for Amazon DynamoDB. +// +// Creates a new table from an existing backup. Any number of users can execute +// up to 10 concurrent restores in a given account. +// +// You can call RestoreTableFromBackup at a maximum rate of 10 times per second. +// +// You must manually set up the following on the restored table: +// +// * Auto scaling policies +// +// * IAM policies +// +// * Cloudwatch metrics and alarms +// +// * Tags +// +// * Time to Live (TTL) settings +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation RestoreTableFromBackup for usage and error information. +// +// Returned Error Codes: +// * ErrCodeTableAlreadyExistsException "TableAlreadyExistsException" +// A table with the name already exists. +// +// * ErrCodeTableInUseException "TableInUseException" +// A table by that name is either being created or deleted. +// +// * ErrCodeBackupNotFoundException "BackupNotFoundException" +// Backup not found for the given BackupARN. +// +// * ErrCodeBackupInUseException "BackupInUseException" +// There is another ongoing conflicting backup control plane operation on the +// table. The backups is either being created, deleted or restored to a table. +// +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/RestoreTableFromBackup +func (c *DynamoDB) RestoreTableFromBackup(input *RestoreTableFromBackupInput) (*RestoreTableFromBackupOutput, error) { + req, out := c.RestoreTableFromBackupRequest(input) + return out, req.Send() +} + +// RestoreTableFromBackupWithContext is the same as RestoreTableFromBackup with the addition of +// the ability to pass a context and additional request options. +// +// See RestoreTableFromBackup for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) RestoreTableFromBackupWithContext(ctx aws.Context, input *RestoreTableFromBackupInput, opts ...request.Option) (*RestoreTableFromBackupOutput, error) { + req, out := c.RestoreTableFromBackupRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opScan = "Scan" + +// ScanRequest generates a "aws/request.Request" representing the +// client's request for the Scan operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See Scan for more information on using the Scan +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the ScanRequest method. +// req, resp := client.ScanRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Scan +func (c *DynamoDB) ScanRequest(input *ScanInput) (req *request.Request, output *ScanOutput) { + op := &request.Operation{ + Name: opScan, + HTTPMethod: "POST", + HTTPPath: "/", + Paginator: &request.Paginator{ + InputTokens: []string{"ExclusiveStartKey"}, + OutputTokens: []string{"LastEvaluatedKey"}, + LimitToken: "Limit", + TruncationToken: "", + }, + } + + if input == nil { + input = &ScanInput{} + } + + output = &ScanOutput{} + req = c.newRequest(op, input, output) + return +} + +// Scan API operation for Amazon DynamoDB. +// +// The Scan operation returns one or more items and item attributes by accessing +// every item in a table or a secondary index. To have DynamoDB return fewer +// items, you can provide a FilterExpression operation. +// +// If the total number of scanned items exceeds the maximum data set size limit +// of 1 MB, the scan stops and results are returned to the user as a LastEvaluatedKey +// value to continue the scan in a subsequent operation. The results also include +// the number of items exceeding the limit. A scan can result in no table data +// meeting the filter criteria. +// +// A single Scan operation will read up to the maximum number of items set (if +// using the Limit parameter) or a maximum of 1 MB of data and then apply any +// filtering to the results using FilterExpression. If LastEvaluatedKey is present +// in the response, you will need to paginate the result set. For more information, +// see Paginating the Results (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.Pagination) +// in the Amazon DynamoDB Developer Guide. +// +// Scan operations proceed sequentially; however, for faster performance on +// a large table or secondary index, applications can request a parallel Scan +// operation by providing the Segment and TotalSegments parameters. For more +// information, see Parallel Scan (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.ParallelScan) +// in the Amazon DynamoDB Developer Guide. +// +// Scan uses eventually consistent reads when accessing the data in a table; +// therefore, the result set might not include the changes to data in the table +// immediately before the operation began. If you need a consistent copy of +// the data, as of the time that the Scan begins, you can set the ConsistentRead +// parameter to true. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation Scan for usage and error information. +// +// Returned Error Codes: +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Scan +func (c *DynamoDB) Scan(input *ScanInput) (*ScanOutput, error) { + req, out := c.ScanRequest(input) + return out, req.Send() +} + +// ScanWithContext is the same as Scan with the addition of +// the ability to pass a context and additional request options. +// +// See Scan for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) ScanWithContext(ctx aws.Context, input *ScanInput, opts ...request.Option) (*ScanOutput, error) { + req, out := c.ScanRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// ScanPages iterates over the pages of a Scan operation, +// calling the "fn" function with the response data for each page. To stop +// iterating, return false from the fn function. +// +// See Scan method for more information on how to use this operation. +// +// Note: This operation can generate multiple requests to a service. +// +// // Example iterating over at most 3 pages of a Scan operation. +// pageNum := 0 +// err := client.ScanPages(params, +// func(page *ScanOutput, lastPage bool) bool { +// pageNum++ +// fmt.Println(page) +// return pageNum <= 3 +// }) +// +func (c *DynamoDB) ScanPages(input *ScanInput, fn func(*ScanOutput, bool) bool) error { + return c.ScanPagesWithContext(aws.BackgroundContext(), input, fn) +} + +// ScanPagesWithContext same as ScanPages except +// it takes a Context and allows setting request options on the pages. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) ScanPagesWithContext(ctx aws.Context, input *ScanInput, fn func(*ScanOutput, bool) bool, opts ...request.Option) error { + p := request.Pagination{ + NewRequest: func() (*request.Request, error) { + var inCpy *ScanInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.ScanRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + + cont := true + for p.Next() && cont { + cont = fn(p.Page().(*ScanOutput), !p.HasNextPage()) + } + return p.Err() +} + +const opTagResource = "TagResource" + +// TagResourceRequest generates a "aws/request.Request" representing the +// client's request for the TagResource operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See TagResource for more information on using the TagResource +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the TagResourceRequest method. +// req, resp := client.TagResourceRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/TagResource +func (c *DynamoDB) TagResourceRequest(input *TagResourceInput) (req *request.Request, output *TagResourceOutput) { + op := &request.Operation{ + Name: opTagResource, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &TagResourceInput{} + } + + output = &TagResourceOutput{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// TagResource API operation for Amazon DynamoDB. +// +// Associate a set of tags with an Amazon DynamoDB resource. You can then activate +// these user-defined tags so that they appear on the Billing and Cost Management +// console for cost allocation tracking. You can call TagResource up to 5 times +// per second, per account. +// +// For an overview on tagging DynamoDB resources, see Tagging for DynamoDB (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tagging.html) +// in the Amazon DynamoDB Developer Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation TagResource for usage and error information. +// +// Returned Error Codes: +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// * ErrCodeResourceInUseException "ResourceInUseException" +// The operation conflicts with the resource's availability. For example, you +// attempted to recreate an existing table, or tried to delete a table currently +// in the CREATING state. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/TagResource +func (c *DynamoDB) TagResource(input *TagResourceInput) (*TagResourceOutput, error) { + req, out := c.TagResourceRequest(input) + return out, req.Send() +} + +// TagResourceWithContext is the same as TagResource with the addition of +// the ability to pass a context and additional request options. +// +// See TagResource for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) TagResourceWithContext(ctx aws.Context, input *TagResourceInput, opts ...request.Option) (*TagResourceOutput, error) { + req, out := c.TagResourceRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opUntagResource = "UntagResource" + +// UntagResourceRequest generates a "aws/request.Request" representing the +// client's request for the UntagResource operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See UntagResource for more information on using the UntagResource +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the UntagResourceRequest method. +// req, resp := client.UntagResourceRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UntagResource +func (c *DynamoDB) UntagResourceRequest(input *UntagResourceInput) (req *request.Request, output *UntagResourceOutput) { + op := &request.Operation{ + Name: opUntagResource, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UntagResourceInput{} + } + + output = &UntagResourceOutput{} + req = c.newRequest(op, input, output) + req.Handlers.Unmarshal.Remove(jsonrpc.UnmarshalHandler) + req.Handlers.Unmarshal.PushBackNamed(protocol.UnmarshalDiscardBodyHandler) + return +} + +// UntagResource API operation for Amazon DynamoDB. +// +// Removes the association of tags from an Amazon DynamoDB resource. You can +// call UntagResource up to 5 times per second, per account. +// +// For an overview on tagging DynamoDB resources, see Tagging for DynamoDB (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tagging.html) +// in the Amazon DynamoDB Developer Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation UntagResource for usage and error information. +// +// Returned Error Codes: +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// * ErrCodeResourceInUseException "ResourceInUseException" +// The operation conflicts with the resource's availability. For example, you +// attempted to recreate an existing table, or tried to delete a table currently +// in the CREATING state. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UntagResource +func (c *DynamoDB) UntagResource(input *UntagResourceInput) (*UntagResourceOutput, error) { + req, out := c.UntagResourceRequest(input) + return out, req.Send() +} + +// UntagResourceWithContext is the same as UntagResource with the addition of +// the ability to pass a context and additional request options. +// +// See UntagResource for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) UntagResourceWithContext(ctx aws.Context, input *UntagResourceInput, opts ...request.Option) (*UntagResourceOutput, error) { + req, out := c.UntagResourceRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opUpdateGlobalTable = "UpdateGlobalTable" + +// UpdateGlobalTableRequest generates a "aws/request.Request" representing the +// client's request for the UpdateGlobalTable operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See UpdateGlobalTable for more information on using the UpdateGlobalTable +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the UpdateGlobalTableRequest method. +// req, resp := client.UpdateGlobalTableRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateGlobalTable +func (c *DynamoDB) UpdateGlobalTableRequest(input *UpdateGlobalTableInput) (req *request.Request, output *UpdateGlobalTableOutput) { + op := &request.Operation{ + Name: opUpdateGlobalTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UpdateGlobalTableInput{} + } + + output = &UpdateGlobalTableOutput{} + req = c.newRequest(op, input, output) + return +} + +// UpdateGlobalTable API operation for Amazon DynamoDB. +// +// Adds or removes replicas to the specified global table. The global table +// should already exist to be able to use this operation. Currently, the replica +// to be added should be empty. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation UpdateGlobalTable for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// * ErrCodeGlobalTableNotFoundException "GlobalTableNotFoundException" +// The specified global table does not exist. +// +// * ErrCodeReplicaAlreadyExistsException "ReplicaAlreadyExistsException" +// The specified replica is already part of the global table. +// +// * ErrCodeReplicaNotFoundException "ReplicaNotFoundException" +// The specified replica is no longer part of the global table. +// +// * ErrCodeTableNotFoundException "TableNotFoundException" +// A table with the name TableName does not currently exist within the subscriber's +// account. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateGlobalTable +func (c *DynamoDB) UpdateGlobalTable(input *UpdateGlobalTableInput) (*UpdateGlobalTableOutput, error) { + req, out := c.UpdateGlobalTableRequest(input) + return out, req.Send() +} + +// UpdateGlobalTableWithContext is the same as UpdateGlobalTable with the addition of +// the ability to pass a context and additional request options. +// +// See UpdateGlobalTable for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) UpdateGlobalTableWithContext(ctx aws.Context, input *UpdateGlobalTableInput, opts ...request.Option) (*UpdateGlobalTableOutput, error) { + req, out := c.UpdateGlobalTableRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opUpdateItem = "UpdateItem" + +// UpdateItemRequest generates a "aws/request.Request" representing the +// client's request for the UpdateItem operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See UpdateItem for more information on using the UpdateItem +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the UpdateItemRequest method. +// req, resp := client.UpdateItemRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateItem +func (c *DynamoDB) UpdateItemRequest(input *UpdateItemInput) (req *request.Request, output *UpdateItemOutput) { + op := &request.Operation{ + Name: opUpdateItem, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UpdateItemInput{} + } + + output = &UpdateItemOutput{} + req = c.newRequest(op, input, output) + return +} + +// UpdateItem API operation for Amazon DynamoDB. +// +// Edits an existing item's attributes, or adds a new item to the table if it +// does not already exist. You can put, delete, or add attribute values. You +// can also perform a conditional update on an existing item (insert a new attribute +// name-value pair if it doesn't exist, or replace an existing name-value pair +// if it has certain expected attribute values). +// +// You can also return the item's attribute values in the same UpdateItem operation +// using the ReturnValues parameter. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation UpdateItem for usage and error information. +// +// Returned Error Codes: +// * ErrCodeConditionalCheckFailedException "ConditionalCheckFailedException" +// A condition specified in the operation could not be evaluated. +// +// * ErrCodeProvisionedThroughputExceededException "ProvisionedThroughputExceededException" +// Your request rate is too high. The AWS SDKs for DynamoDB automatically retry +// requests that receive this exception. Your request is eventually successful, +// unless your retry queue is too large to finish. Reduce the frequency of requests +// and use exponential backoff. For more information, go to Error Retries and +// Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) +// in the Amazon DynamoDB Developer Guide. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeItemCollectionSizeLimitExceededException "ItemCollectionSizeLimitExceededException" +// An item collection is too large. This exception is only returned for tables +// that have one or more local secondary indexes. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateItem +func (c *DynamoDB) UpdateItem(input *UpdateItemInput) (*UpdateItemOutput, error) { + req, out := c.UpdateItemRequest(input) + return out, req.Send() +} + +// UpdateItemWithContext is the same as UpdateItem with the addition of +// the ability to pass a context and additional request options. +// +// See UpdateItem for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) UpdateItemWithContext(ctx aws.Context, input *UpdateItemInput, opts ...request.Option) (*UpdateItemOutput, error) { + req, out := c.UpdateItemRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opUpdateTable = "UpdateTable" + +// UpdateTableRequest generates a "aws/request.Request" representing the +// client's request for the UpdateTable operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See UpdateTable for more information on using the UpdateTable +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the UpdateTableRequest method. +// req, resp := client.UpdateTableRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTable +func (c *DynamoDB) UpdateTableRequest(input *UpdateTableInput) (req *request.Request, output *UpdateTableOutput) { + op := &request.Operation{ + Name: opUpdateTable, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UpdateTableInput{} + } + + output = &UpdateTableOutput{} + req = c.newRequest(op, input, output) + return +} + +// UpdateTable API operation for Amazon DynamoDB. +// +// Modifies the provisioned throughput settings, global secondary indexes, or +// DynamoDB Streams settings for a given table. +// +// You can only perform one of the following operations at once: +// +// * Modify the provisioned throughput settings of the table. +// +// * Enable or disable Streams on the table. +// +// * Remove a global secondary index from the table. +// +// * Create a new global secondary index on the table. Once the index begins +// backfilling, you can use UpdateTable to perform other operations. +// +// UpdateTable is an asynchronous operation; while it is executing, the table +// status changes from ACTIVE to UPDATING. While it is UPDATING, you cannot +// issue another UpdateTable request. When the table returns to the ACTIVE state, +// the UpdateTable operation is complete. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation UpdateTable for usage and error information. +// +// Returned Error Codes: +// * ErrCodeResourceInUseException "ResourceInUseException" +// The operation conflicts with the resource's availability. For example, you +// attempted to recreate an existing table, or tried to delete a table currently +// in the CREATING state. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTable +func (c *DynamoDB) UpdateTable(input *UpdateTableInput) (*UpdateTableOutput, error) { + req, out := c.UpdateTableRequest(input) + return out, req.Send() +} + +// UpdateTableWithContext is the same as UpdateTable with the addition of +// the ability to pass a context and additional request options. +// +// See UpdateTable for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) UpdateTableWithContext(ctx aws.Context, input *UpdateTableInput, opts ...request.Option) (*UpdateTableOutput, error) { + req, out := c.UpdateTableRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opUpdateTimeToLive = "UpdateTimeToLive" + +// UpdateTimeToLiveRequest generates a "aws/request.Request" representing the +// client's request for the UpdateTimeToLive operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See UpdateTimeToLive for more information on using the UpdateTimeToLive +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the UpdateTimeToLiveRequest method. +// req, resp := client.UpdateTimeToLiveRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTimeToLive +func (c *DynamoDB) UpdateTimeToLiveRequest(input *UpdateTimeToLiveInput) (req *request.Request, output *UpdateTimeToLiveOutput) { + op := &request.Operation{ + Name: opUpdateTimeToLive, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &UpdateTimeToLiveInput{} + } + + output = &UpdateTimeToLiveOutput{} + req = c.newRequest(op, input, output) + return +} + +// UpdateTimeToLive API operation for Amazon DynamoDB. +// +// The UpdateTimeToLive method will enable or disable TTL for the specified +// table. A successful UpdateTimeToLive call returns the current TimeToLiveSpecification; +// it may take up to one hour for the change to fully process. Any additional +// UpdateTimeToLive calls for the same table during this one hour duration result +// in a ValidationException. +// +// TTL compares the current time in epoch time format to the time stored in +// the TTL attribute of an item. If the epoch time value stored in the attribute +// is less than the current time, the item is marked as expired and subsequently +// deleted. +// +// The epoch time format is the number of seconds elapsed since 12:00:00 AM +// January 1st, 1970 UTC. +// +// DynamoDB deletes expired items on a best-effort basis to ensure availability +// of throughput for other data operations. +// +// DynamoDB typically deletes expired items within two days of expiration. The +// exact duration within which an item gets deleted after expiration is specific +// to the nature of the workload. Items that have expired and not been deleted +// will still show up in reads, queries, and scans. +// +// As items are deleted, they are removed from any Local Secondary Index and +// Global Secondary Index immediately in the same eventually consistent way +// as a standard delete operation. +// +// For more information, see Time To Live (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html) +// in the Amazon DynamoDB Developer Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for Amazon DynamoDB's +// API operation UpdateTimeToLive for usage and error information. +// +// Returned Error Codes: +// * ErrCodeResourceInUseException "ResourceInUseException" +// The operation conflicts with the resource's availability. For example, you +// attempted to recreate an existing table, or tried to delete a table currently +// in the CREATING state. +// +// * ErrCodeResourceNotFoundException "ResourceNotFoundException" +// The operation tried to access a nonexistent table or index. The resource +// might not be specified correctly, or its status might not be ACTIVE. +// +// * ErrCodeLimitExceededException "LimitExceededException" +// The number of concurrent table requests (cumulative number of tables in the +// CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. +// +// Also, for tables with secondary indexes, only one of those tables can be +// in the CREATING state at any point in time. Do not attempt to create more +// than one such table simultaneously. +// +// The total limit of tables in the ACTIVE state is 250. +// +// * ErrCodeInternalServerError "InternalServerError" +// An error occurred on the server side. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTimeToLive +func (c *DynamoDB) UpdateTimeToLive(input *UpdateTimeToLiveInput) (*UpdateTimeToLiveOutput, error) { + req, out := c.UpdateTimeToLiveRequest(input) + return out, req.Send() +} + +// UpdateTimeToLiveWithContext is the same as UpdateTimeToLive with the addition of +// the ability to pass a context and additional request options. +// +// See UpdateTimeToLive for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) UpdateTimeToLiveWithContext(ctx aws.Context, input *UpdateTimeToLiveInput, opts ...request.Option) (*UpdateTimeToLiveOutput, error) { + req, out := c.UpdateTimeToLiveRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// Represents an attribute for describing the key schema for the table and indexes. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/AttributeDefinition +type AttributeDefinition struct { + _ struct{} `type:"structure"` + + // A name for the attribute. + // + // AttributeName is a required field + AttributeName *string `min:"1" type:"string" required:"true"` + + // The data type for the attribute, where: + // + // * S - the attribute is of type String + // + // * N - the attribute is of type Number + // + // * B - the attribute is of type Binary + // + // AttributeType is a required field + AttributeType *string `type:"string" required:"true" enum:"ScalarAttributeType"` +} + +// String returns the string representation +func (s AttributeDefinition) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttributeDefinition) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *AttributeDefinition) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "AttributeDefinition"} + if s.AttributeName == nil { + invalidParams.Add(request.NewErrParamRequired("AttributeName")) + } + if s.AttributeName != nil && len(*s.AttributeName) < 1 { + invalidParams.Add(request.NewErrParamMinLen("AttributeName", 1)) + } + if s.AttributeType == nil { + invalidParams.Add(request.NewErrParamRequired("AttributeType")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributeName sets the AttributeName field's value. +func (s *AttributeDefinition) SetAttributeName(v string) *AttributeDefinition { + s.AttributeName = &v + return s +} + +// SetAttributeType sets the AttributeType field's value. +func (s *AttributeDefinition) SetAttributeType(v string) *AttributeDefinition { + s.AttributeType = &v + return s +} + +// Represents the data for an attribute. +// +// Each attribute value is described as a name-value pair. The name is the data +// type, and the value is the data itself. +// +// For more information, see Data Types (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) +// in the Amazon DynamoDB Developer Guide. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/AttributeValue +type AttributeValue struct { + _ struct{} `type:"structure"` + + // An attribute of type Binary. For example: + // + // "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" + // + // B is automatically base64 encoded/decoded by the SDK. + B []byte `type:"blob"` + + // An attribute of type Boolean. For example: + // + // "BOOL": true + BOOL *bool `type:"boolean"` + + // An attribute of type Binary Set. For example: + // + // "BS": ["U3Vubnk=", "UmFpbnk=", "U25vd3k="] + BS [][]byte `type:"list"` + + // An attribute of type List. For example: + // + // "L": ["Cookies", "Coffee", 3.14159] + L []*AttributeValue `type:"list"` + + // An attribute of type Map. For example: + // + // "M": {"Name": {"S": "Joe"}, "Age": {"N": "35"}} + M map[string]*AttributeValue `type:"map"` + + // An attribute of type Number. For example: + // + // "N": "123.45" + // + // Numbers are sent across the network to DynamoDB as strings, to maximize compatibility + // across languages and libraries. However, DynamoDB treats them as number type + // attributes for mathematical operations. + N *string `type:"string"` + + // An attribute of type Number Set. For example: + // + // "NS": ["42.2", "-19", "7.5", "3.14"] + // + // Numbers are sent across the network to DynamoDB as strings, to maximize compatibility + // across languages and libraries. However, DynamoDB treats them as number type + // attributes for mathematical operations. + NS []*string `type:"list"` + + // An attribute of type Null. For example: + // + // "NULL": true + NULL *bool `type:"boolean"` + + // An attribute of type String. For example: + // + // "S": "Hello" + S *string `type:"string"` + + // An attribute of type String Set. For example: + // + // "SS": ["Giraffe", "Hippo" ,"Zebra"] + SS []*string `type:"list"` +} + +// String returns the string representation +func (s AttributeValue) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttributeValue) GoString() string { + return s.String() +} + +// SetB sets the B field's value. +func (s *AttributeValue) SetB(v []byte) *AttributeValue { + s.B = v + return s +} + +// SetBOOL sets the BOOL field's value. +func (s *AttributeValue) SetBOOL(v bool) *AttributeValue { + s.BOOL = &v + return s +} + +// SetBS sets the BS field's value. +func (s *AttributeValue) SetBS(v [][]byte) *AttributeValue { + s.BS = v + return s +} + +// SetL sets the L field's value. +func (s *AttributeValue) SetL(v []*AttributeValue) *AttributeValue { + s.L = v + return s +} + +// SetM sets the M field's value. +func (s *AttributeValue) SetM(v map[string]*AttributeValue) *AttributeValue { + s.M = v + return s +} + +// SetN sets the N field's value. +func (s *AttributeValue) SetN(v string) *AttributeValue { + s.N = &v + return s +} + +// SetNS sets the NS field's value. +func (s *AttributeValue) SetNS(v []*string) *AttributeValue { + s.NS = v + return s +} + +// SetNULL sets the NULL field's value. +func (s *AttributeValue) SetNULL(v bool) *AttributeValue { + s.NULL = &v + return s +} + +// SetS sets the S field's value. +func (s *AttributeValue) SetS(v string) *AttributeValue { + s.S = &v + return s +} + +// SetSS sets the SS field's value. +func (s *AttributeValue) SetSS(v []*string) *AttributeValue { + s.SS = v + return s +} + +// For the UpdateItem operation, represents the attributes to be modified, the +// action to perform on each, and the new value for each. +// +// You cannot use UpdateItem to update any primary key attributes. Instead, +// you will need to delete the item, and then use PutItem to create a new item +// with new attributes. +// +// Attribute values cannot be null; string and binary type attributes must have +// lengths greater than zero; and set type attributes must not be empty. Requests +// with empty values will be rejected with a ValidationException exception. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/AttributeValueUpdate +type AttributeValueUpdate struct { + _ struct{} `type:"structure"` + + // Specifies how to perform the update. Valid values are PUT (default), DELETE, + // and ADD. The behavior depends on whether the specified primary key already + // exists in the table. + // + // If an item with the specified Key is found in the table: + // + // * PUT - Adds the specified attribute to the item. If the attribute already + // exists, it is replaced by the new value. + // + // * DELETE - If no value is specified, the attribute and its value are removed + // from the item. The data type of the specified value must match the existing + // value's data type. + // + // If a set of values is specified, then those values are subtracted from the + // old set. For example, if the attribute value was the set [a,b,c] and the + // DELETE action specified [a,c], then the final attribute value would be + // [b]. Specifying an empty set is an error. + // + // * ADD - If the attribute does not already exist, then the attribute and + // its values are added to the item. If the attribute does exist, then the + // behavior of ADD depends on the data type of the attribute: + // + // If the existing attribute is a number, and if Value is also a number, then + // the Value is mathematically added to the existing attribute. If Value + // is a negative number, then it is subtracted from the existing attribute. + // + // If you use ADD to increment or decrement a number value for an item that + // doesn't exist before the update, DynamoDB uses 0 as the initial value. + // + // In addition, if you use ADD to update an existing item, and intend to increment + // or decrement an attribute value which does not yet exist, DynamoDB uses + // 0 as the initial value. For example, suppose that the item you want to + // update does not yet have an attribute named itemcount, but you decide + // to ADD the number 3 to this attribute anyway, even though it currently + // does not exist. DynamoDB will create the itemcount attribute, set its + // initial value to 0, and finally add 3 to it. The result will be a new + // itemcount attribute in the item, with a value of 3. + // + // If the existing data type is a set, and if the Value is also a set, then + // the Value is added to the existing set. (This is a set operation, not + // mathematical addition.) For example, if the attribute value was the set + // [1,2], and the ADD action specified [3], then the final attribute value + // would be [1,2,3]. An error occurs if an Add action is specified for a + // set attribute and the attribute type specified does not match the existing + // set type. + // + // Both sets must have the same primitive data type. For example, if the existing + // data type is a set of strings, the Value must also be a set of strings. + // The same holds true for number sets and binary sets. + // + // This action is only valid for an existing attribute whose data type is number + // or is a set. Do not use ADD for any other data types. + // + // If no item with the specified Key is found: + // + // * PUT - DynamoDB creates a new item with the specified primary key, and + // then adds the attribute. + // + // * DELETE - Nothing happens; there is no attribute to delete. + // + // * ADD - DynamoDB creates an item with the supplied primary key and number + // (or set of numbers) for the attribute value. The only data types allowed + // are number and number set; no other data types can be specified. + Action *string `type:"string" enum:"AttributeAction"` + + // Represents the data for an attribute. + // + // Each attribute value is described as a name-value pair. The name is the data + // type, and the value is the data itself. + // + // For more information, see Data TYpes (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) + // in the Amazon DynamoDB Developer Guide. + Value *AttributeValue `type:"structure"` +} + +// String returns the string representation +func (s AttributeValueUpdate) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AttributeValueUpdate) GoString() string { + return s.String() +} + +// SetAction sets the Action field's value. +func (s *AttributeValueUpdate) SetAction(v string) *AttributeValueUpdate { + s.Action = &v + return s +} + +// SetValue sets the Value field's value. +func (s *AttributeValueUpdate) SetValue(v *AttributeValue) *AttributeValueUpdate { + s.Value = v + return s +} + +// Contains the description of the backup created for the table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BackupDescription +type BackupDescription struct { + _ struct{} `type:"structure"` + + // Contains the details of the backup created for the table. + BackupDetails *BackupDetails `type:"structure"` + + // Contains the details of the table when the backup was created. + SourceTableDetails *SourceTableDetails `type:"structure"` + + // Contains the details of the features enabled on the table when the backup + // was created. For example, LSIs, GSIs, streams, TTL. + SourceTableFeatureDetails *SourceTableFeatureDetails `type:"structure"` +} + +// String returns the string representation +func (s BackupDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BackupDescription) GoString() string { + return s.String() +} + +// SetBackupDetails sets the BackupDetails field's value. +func (s *BackupDescription) SetBackupDetails(v *BackupDetails) *BackupDescription { + s.BackupDetails = v + return s +} + +// SetSourceTableDetails sets the SourceTableDetails field's value. +func (s *BackupDescription) SetSourceTableDetails(v *SourceTableDetails) *BackupDescription { + s.SourceTableDetails = v + return s +} + +// SetSourceTableFeatureDetails sets the SourceTableFeatureDetails field's value. +func (s *BackupDescription) SetSourceTableFeatureDetails(v *SourceTableFeatureDetails) *BackupDescription { + s.SourceTableFeatureDetails = v + return s +} + +// Contains the details of the backup created for the table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BackupDetails +type BackupDetails struct { + _ struct{} `type:"structure"` + + // ARN associated with the backup. + // + // BackupArn is a required field + BackupArn *string `min:"37" type:"string" required:"true"` + + // Time at which the backup was created. This is the request time of the backup. + // + // BackupCreationDateTime is a required field + BackupCreationDateTime *time.Time `type:"timestamp" timestampFormat:"unix" required:"true"` + + // Name of the requested backup. + // + // BackupName is a required field + BackupName *string `min:"3" type:"string" required:"true"` + + // Size of the backup in bytes. + BackupSizeBytes *int64 `type:"long"` + + // Backup can be in one of the following states: CREATING, ACTIVE, DELETED. + // + // BackupStatus is a required field + BackupStatus *string `type:"string" required:"true" enum:"BackupStatus"` +} + +// String returns the string representation +func (s BackupDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BackupDetails) GoString() string { + return s.String() +} + +// SetBackupArn sets the BackupArn field's value. +func (s *BackupDetails) SetBackupArn(v string) *BackupDetails { + s.BackupArn = &v + return s +} + +// SetBackupCreationDateTime sets the BackupCreationDateTime field's value. +func (s *BackupDetails) SetBackupCreationDateTime(v time.Time) *BackupDetails { + s.BackupCreationDateTime = &v + return s +} + +// SetBackupName sets the BackupName field's value. +func (s *BackupDetails) SetBackupName(v string) *BackupDetails { + s.BackupName = &v + return s +} + +// SetBackupSizeBytes sets the BackupSizeBytes field's value. +func (s *BackupDetails) SetBackupSizeBytes(v int64) *BackupDetails { + s.BackupSizeBytes = &v + return s +} + +// SetBackupStatus sets the BackupStatus field's value. +func (s *BackupDetails) SetBackupStatus(v string) *BackupDetails { + s.BackupStatus = &v + return s +} + +// Contains details for the backup. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BackupSummary +type BackupSummary struct { + _ struct{} `type:"structure"` + + // ARN associated with the backup. + BackupArn *string `min:"37" type:"string"` + + // Time at which the backup was created. + BackupCreationDateTime *time.Time `type:"timestamp" timestampFormat:"unix"` + + // Name of the specified backup. + BackupName *string `min:"3" type:"string"` + + // Size of the backup in bytes. + BackupSizeBytes *int64 `type:"long"` + + // Backup can be in one of the following states: CREATING, ACTIVE, DELETED. + BackupStatus *string `type:"string" enum:"BackupStatus"` + + // ARN associated with the table. + TableArn *string `type:"string"` + + // Unique identifier for the table. + TableId *string `type:"string"` + + // Name of the table. + TableName *string `min:"3" type:"string"` +} + +// String returns the string representation +func (s BackupSummary) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BackupSummary) GoString() string { + return s.String() +} + +// SetBackupArn sets the BackupArn field's value. +func (s *BackupSummary) SetBackupArn(v string) *BackupSummary { + s.BackupArn = &v + return s +} + +// SetBackupCreationDateTime sets the BackupCreationDateTime field's value. +func (s *BackupSummary) SetBackupCreationDateTime(v time.Time) *BackupSummary { + s.BackupCreationDateTime = &v + return s +} + +// SetBackupName sets the BackupName field's value. +func (s *BackupSummary) SetBackupName(v string) *BackupSummary { + s.BackupName = &v + return s +} + +// SetBackupSizeBytes sets the BackupSizeBytes field's value. +func (s *BackupSummary) SetBackupSizeBytes(v int64) *BackupSummary { + s.BackupSizeBytes = &v + return s +} + +// SetBackupStatus sets the BackupStatus field's value. +func (s *BackupSummary) SetBackupStatus(v string) *BackupSummary { + s.BackupStatus = &v + return s +} + +// SetTableArn sets the TableArn field's value. +func (s *BackupSummary) SetTableArn(v string) *BackupSummary { + s.TableArn = &v + return s +} + +// SetTableId sets the TableId field's value. +func (s *BackupSummary) SetTableId(v string) *BackupSummary { + s.TableId = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *BackupSummary) SetTableName(v string) *BackupSummary { + s.TableName = &v + return s +} + +// Represents the input of a BatchGetItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchGetItemInput +type BatchGetItemInput struct { + _ struct{} `type:"structure"` + + // A map of one or more table names and, for each table, a map that describes + // one or more items to retrieve from that table. Each table name can be used + // only once per BatchGetItem request. + // + // Each element in the map of items to retrieve consists of the following: + // + // * ConsistentRead - If true, a strongly consistent read is used; if false + // (the default), an eventually consistent read is used. + // + // * ExpressionAttributeNames - One or more substitution tokens for attribute + // names in the ProjectionExpression parameter. The following are some use + // cases for using ExpressionAttributeNames: + // + // To access an attribute whose name conflicts with a DynamoDB reserved word. + // + // To create a placeholder for repeating occurrences of an attribute name in + // an expression. + // + // To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could + // specify the following for ExpressionAttributeNames: + // + // {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + // + // * Keys - An array of primary key attribute values that define specific + // items in the table. For each primary key, you must provide all of the + // key attributes. For example, with a simple primary key, you only need + // to provide the partition key value. For a composite key, you must provide + // both the partition key value and the sort key value. + // + // * ProjectionExpression - A string that identifies one or more attributes + // to retrieve from the table. These attributes can include scalars, sets, + // or elements of a JSON document. The attributes in the expression must + // be separated by commas. + // + // If no attribute names are specified, then all attributes will be returned. + // If any of the requested attributes are not found, they will not appear + // in the result. + // + // For more information, see Accessing Item Attributes (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + // + // * AttributesToGet - This is a legacy parameter. Use ProjectionExpression + // instead. For more information, see AttributesToGet (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributesToGet.html) + // in the Amazon DynamoDB Developer Guide. + // + // RequestItems is a required field + RequestItems map[string]*KeysAndAttributes `min:"1" type:"map" required:"true"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` +} + +// String returns the string representation +func (s BatchGetItemInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BatchGetItemInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *BatchGetItemInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "BatchGetItemInput"} + if s.RequestItems == nil { + invalidParams.Add(request.NewErrParamRequired("RequestItems")) + } + if s.RequestItems != nil && len(s.RequestItems) < 1 { + invalidParams.Add(request.NewErrParamMinLen("RequestItems", 1)) + } + if s.RequestItems != nil { + for i, v := range s.RequestItems { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "RequestItems", i), err.(request.ErrInvalidParams)) + } + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetRequestItems sets the RequestItems field's value. +func (s *BatchGetItemInput) SetRequestItems(v map[string]*KeysAndAttributes) *BatchGetItemInput { + s.RequestItems = v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *BatchGetItemInput) SetReturnConsumedCapacity(v string) *BatchGetItemInput { + s.ReturnConsumedCapacity = &v + return s +} + +// Represents the output of a BatchGetItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchGetItemOutput +type BatchGetItemOutput struct { + _ struct{} `type:"structure"` + + // The read capacity units consumed by the entire BatchGetItem operation. + // + // Each element consists of: + // + // * TableName - The table that consumed the provisioned throughput. + // + // * CapacityUnits - The total number of capacity units consumed. + ConsumedCapacity []*ConsumedCapacity `type:"list"` + + // A map of table name to a list of items. Each object in Responses consists + // of a table name, along with a map of attribute data consisting of the data + // type and attribute value. + Responses map[string][]map[string]*AttributeValue `type:"map"` + + // A map of tables and their respective keys that were not processed with the + // current response. The UnprocessedKeys value is in the same form as RequestItems, + // so the value can be provided directly to a subsequent BatchGetItem operation. + // For more information, see RequestItems in the Request Parameters section. + // + // Each element consists of: + // + // * Keys - An array of primary key attribute values that define specific + // items in the table. + // + // * ProjectionExpression - One or more attributes to be retrieved from the + // table or index. By default, all attributes are returned. If a requested + // attribute is not found, it does not appear in the result. + // + // * ConsistentRead - The consistency of a read operation. If set to true, + // then a strongly consistent read is used; otherwise, an eventually consistent + // read is used. + // + // If there are no unprocessed keys remaining, the response contains an empty + // UnprocessedKeys map. + UnprocessedKeys map[string]*KeysAndAttributes `min:"1" type:"map"` +} + +// String returns the string representation +func (s BatchGetItemOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BatchGetItemOutput) GoString() string { + return s.String() +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *BatchGetItemOutput) SetConsumedCapacity(v []*ConsumedCapacity) *BatchGetItemOutput { + s.ConsumedCapacity = v + return s +} + +// SetResponses sets the Responses field's value. +func (s *BatchGetItemOutput) SetResponses(v map[string][]map[string]*AttributeValue) *BatchGetItemOutput { + s.Responses = v + return s +} + +// SetUnprocessedKeys sets the UnprocessedKeys field's value. +func (s *BatchGetItemOutput) SetUnprocessedKeys(v map[string]*KeysAndAttributes) *BatchGetItemOutput { + s.UnprocessedKeys = v + return s +} + +// Represents the input of a BatchWriteItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchWriteItemInput +type BatchWriteItemInput struct { + _ struct{} `type:"structure"` + + // A map of one or more table names and, for each table, a list of operations + // to be performed (DeleteRequest or PutRequest). Each element in the map consists + // of the following: + // + // * DeleteRequest - Perform a DeleteItem operation on the specified item. + // The item to be deleted is identified by a Key subelement: + // + // Key - A map of primary key attribute values that uniquely identify the item. + // Each entry in this map consists of an attribute name and an attribute + // value. For each primary key, you must provide all of the key attributes. + // For example, with a simple primary key, you only need to provide a value + // for the partition key. For a composite primary key, you must provide values + // for both the partition key and the sort key. + // + // * PutRequest - Perform a PutItem operation on the specified item. The + // item to be put is identified by an Item subelement: + // + // Item - A map of attributes and their values. Each entry in this map consists + // of an attribute name and an attribute value. Attribute values must not + // be null; string and binary type attributes must have lengths greater than + // zero; and set type attributes must not be empty. Requests that contain + // empty values will be rejected with a ValidationException exception. + // + // If you specify any attributes that are part of an index key, then the data + // types for those attributes must match those of the schema in the table's + // attribute definition. + // + // RequestItems is a required field + RequestItems map[string][]*WriteRequest `min:"1" type:"map" required:"true"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` + + // Determines whether item collection metrics are returned. If set to SIZE, + // the response includes statistics about item collections, if any, that were + // modified during the operation are returned in the response. If set to NONE + // (the default), no statistics are returned. + ReturnItemCollectionMetrics *string `type:"string" enum:"ReturnItemCollectionMetrics"` +} + +// String returns the string representation +func (s BatchWriteItemInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BatchWriteItemInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *BatchWriteItemInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "BatchWriteItemInput"} + if s.RequestItems == nil { + invalidParams.Add(request.NewErrParamRequired("RequestItems")) + } + if s.RequestItems != nil && len(s.RequestItems) < 1 { + invalidParams.Add(request.NewErrParamMinLen("RequestItems", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetRequestItems sets the RequestItems field's value. +func (s *BatchWriteItemInput) SetRequestItems(v map[string][]*WriteRequest) *BatchWriteItemInput { + s.RequestItems = v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *BatchWriteItemInput) SetReturnConsumedCapacity(v string) *BatchWriteItemInput { + s.ReturnConsumedCapacity = &v + return s +} + +// SetReturnItemCollectionMetrics sets the ReturnItemCollectionMetrics field's value. +func (s *BatchWriteItemInput) SetReturnItemCollectionMetrics(v string) *BatchWriteItemInput { + s.ReturnItemCollectionMetrics = &v + return s +} + +// Represents the output of a BatchWriteItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/BatchWriteItemOutput +type BatchWriteItemOutput struct { + _ struct{} `type:"structure"` + + // The capacity units consumed by the entire BatchWriteItem operation. + // + // Each element consists of: + // + // * TableName - The table that consumed the provisioned throughput. + // + // * CapacityUnits - The total number of capacity units consumed. + ConsumedCapacity []*ConsumedCapacity `type:"list"` + + // A list of tables that were processed by BatchWriteItem and, for each table, + // information about any item collections that were affected by individual DeleteItem + // or PutItem operations. + // + // Each entry consists of the following subelements: + // + // * ItemCollectionKey - The partition key value of the item collection. + // This is the same as the partition key value of the item. + // + // * SizeEstimateRangeGB - An estimate of item collection size, expressed + // in GB. This is a two-element array containing a lower bound and an upper + // bound for the estimate. The estimate includes the size of all the items + // in the table, plus the size of all attributes projected into all of the + // local secondary indexes on the table. Use this estimate to measure whether + // a local secondary index is approaching its size limit. + // + // The estimate is subject to change over time; therefore, do not rely on the + // precision or accuracy of the estimate. + ItemCollectionMetrics map[string][]*ItemCollectionMetrics `type:"map"` + + // A map of tables and requests against those tables that were not processed. + // The UnprocessedItems value is in the same form as RequestItems, so you can + // provide this value directly to a subsequent BatchGetItem operation. For more + // information, see RequestItems in the Request Parameters section. + // + // Each UnprocessedItems entry consists of a table name and, for that table, + // a list of operations to perform (DeleteRequest or PutRequest). + // + // * DeleteRequest - Perform a DeleteItem operation on the specified item. + // The item to be deleted is identified by a Key subelement: + // + // Key - A map of primary key attribute values that uniquely identify the item. + // Each entry in this map consists of an attribute name and an attribute + // value. + // + // * PutRequest - Perform a PutItem operation on the specified item. The + // item to be put is identified by an Item subelement: + // + // Item - A map of attributes and their values. Each entry in this map consists + // of an attribute name and an attribute value. Attribute values must not + // be null; string and binary type attributes must have lengths greater than + // zero; and set type attributes must not be empty. Requests that contain + // empty values will be rejected with a ValidationException exception. + // + // If you specify any attributes that are part of an index key, then the data + // types for those attributes must match those of the schema in the table's + // attribute definition. + // + // If there are no unprocessed items remaining, the response contains an empty + // UnprocessedItems map. + UnprocessedItems map[string][]*WriteRequest `min:"1" type:"map"` +} + +// String returns the string representation +func (s BatchWriteItemOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s BatchWriteItemOutput) GoString() string { + return s.String() +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *BatchWriteItemOutput) SetConsumedCapacity(v []*ConsumedCapacity) *BatchWriteItemOutput { + s.ConsumedCapacity = v + return s +} + +// SetItemCollectionMetrics sets the ItemCollectionMetrics field's value. +func (s *BatchWriteItemOutput) SetItemCollectionMetrics(v map[string][]*ItemCollectionMetrics) *BatchWriteItemOutput { + s.ItemCollectionMetrics = v + return s +} + +// SetUnprocessedItems sets the UnprocessedItems field's value. +func (s *BatchWriteItemOutput) SetUnprocessedItems(v map[string][]*WriteRequest) *BatchWriteItemOutput { + s.UnprocessedItems = v + return s +} + +// Represents the amount of provisioned throughput capacity consumed on a table +// or an index. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Capacity +type Capacity struct { + _ struct{} `type:"structure"` + + // The total number of capacity units consumed on a table or an index. + CapacityUnits *float64 `type:"double"` +} + +// String returns the string representation +func (s Capacity) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Capacity) GoString() string { + return s.String() +} + +// SetCapacityUnits sets the CapacityUnits field's value. +func (s *Capacity) SetCapacityUnits(v float64) *Capacity { + s.CapacityUnits = &v + return s +} + +// Represents the selection criteria for a Query or Scan operation: +// +// * For a Query operation, Condition is used for specifying the KeyConditions +// to use when querying a table or an index. For KeyConditions, only the +// following comparison operators are supported: +// +// EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN +// +// Condition is also used in a QueryFilter, which evaluates the query results +// and returns only the desired values. +// +// * For a Scan operation, Condition is used in a ScanFilter, which evaluates +// the scan results and returns only the desired values. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Condition +type Condition struct { + _ struct{} `type:"structure"` + + // One or more values to evaluate against the supplied attribute. The number + // of values in the list depends on the ComparisonOperator being used. + // + // For type Number, value comparisons are numeric. + // + // String value comparisons for greater than, equals, or less than are based + // on ASCII character code values. For example, a is greater than A, and a is + // greater than B. For a list of code values, see http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters + // (http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters). + // + // For Binary, DynamoDB treats each byte of the binary data as unsigned when + // it compares binary values. + AttributeValueList []*AttributeValue `type:"list"` + + // A comparator for evaluating attributes. For example, equals, greater than, + // less than, etc. + // + // The following comparison operators are available: + // + // EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | + // BEGINS_WITH | IN | BETWEEN + // + // The following are descriptions of each comparison operator. + // + // * EQ : Equal. EQ is supported for all data types, including lists and + // maps. + // + // AttributeValueList can contain only one AttributeValue element of type String, + // Number, Binary, String Set, Number Set, or Binary Set. If an item contains + // an AttributeValue element of a different type than the one provided in + // the request, the value does not match. For example, {"S":"6"} does not + // equal {"N":"6"}. Also, {"N":"6"} does not equal {"NS":["6", "2", "1"]}. + // + // * NE : Not equal. NE is supported for all data types, including lists + // and maps. + // + // * AttributeValueList can contain only one AttributeValue of type String, + // Number, Binary, String Set, Number Set, or Binary Set. If an item contains + // an AttributeValue of a different type than the one provided in the request, + // the value does not match. For example, {"S":"6"} does not equal {"N":"6"}. + // Also, {"N":"6"} does not equal {"NS":["6", "2", "1"]}. + // + // * LE : Less than or equal. + // + // AttributeValueList can contain only one AttributeValue element of type String, + // Number, or Binary (not a set type). If an item contains an AttributeValue + // element of a different type than the one provided in the request, the value + // does not match. For example, {"S":"6"} does not equal {"N":"6"}. Also, {"N":"6"} + // does not compare to {"NS":["6", "2", "1"]}. + // + // LT: Less than. + // + // AttributeValueListcan contain only one AttributeValueof type String, Number, or Binary (not a set type). If an item contains an + // AttributeValueelement of a different type than the one provided in the request, the value + // does not match. For example, {"S":"6"}does not equal {"N":"6"}. Also, {"N":"6"}does not compare to {"NS":["6", "2", "1"]} + // + // ComparisonOperator is a required field + ComparisonOperator *string `type:"string" required:"true" enum:"ComparisonOperator"` +} + +// String returns the string representation +func (s Condition) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Condition) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *Condition) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "Condition"} + if s.ComparisonOperator == nil { + invalidParams.Add(request.NewErrParamRequired("ComparisonOperator")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributeValueList sets the AttributeValueList field's value. +func (s *Condition) SetAttributeValueList(v []*AttributeValue) *Condition { + s.AttributeValueList = v + return s +} + +// SetComparisonOperator sets the ComparisonOperator field's value. +func (s *Condition) SetComparisonOperator(v string) *Condition { + s.ComparisonOperator = &v + return s +} + +// The capacity units consumed by an operation. The data returned includes the +// total provisioned throughput consumed, along with statistics for the table +// and any indexes involved in the operation. ConsumedCapacity is only returned +// if the request asked for it. For more information, see Provisioned Throughput +// (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) +// in the Amazon DynamoDB Developer Guide. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ConsumedCapacity +type ConsumedCapacity struct { + _ struct{} `type:"structure"` + + // The total number of capacity units consumed by the operation. + CapacityUnits *float64 `type:"double"` + + // The amount of throughput consumed on each global index affected by the operation. + GlobalSecondaryIndexes map[string]*Capacity `type:"map"` + + // The amount of throughput consumed on each local index affected by the operation. + LocalSecondaryIndexes map[string]*Capacity `type:"map"` + + // The amount of throughput consumed on the table affected by the operation. + Table *Capacity `type:"structure"` + + // The name of the table that was affected by the operation. + TableName *string `min:"3" type:"string"` +} + +// String returns the string representation +func (s ConsumedCapacity) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ConsumedCapacity) GoString() string { + return s.String() +} + +// SetCapacityUnits sets the CapacityUnits field's value. +func (s *ConsumedCapacity) SetCapacityUnits(v float64) *ConsumedCapacity { + s.CapacityUnits = &v + return s +} + +// SetGlobalSecondaryIndexes sets the GlobalSecondaryIndexes field's value. +func (s *ConsumedCapacity) SetGlobalSecondaryIndexes(v map[string]*Capacity) *ConsumedCapacity { + s.GlobalSecondaryIndexes = v + return s +} + +// SetLocalSecondaryIndexes sets the LocalSecondaryIndexes field's value. +func (s *ConsumedCapacity) SetLocalSecondaryIndexes(v map[string]*Capacity) *ConsumedCapacity { + s.LocalSecondaryIndexes = v + return s +} + +// SetTable sets the Table field's value. +func (s *ConsumedCapacity) SetTable(v *Capacity) *ConsumedCapacity { + s.Table = v + return s +} + +// SetTableName sets the TableName field's value. +func (s *ConsumedCapacity) SetTableName(v string) *ConsumedCapacity { + s.TableName = &v + return s +} + +// Represents the backup and restore settings on the table when the backup was +// created. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ContinuousBackupsDescription +type ContinuousBackupsDescription struct { + _ struct{} `type:"structure"` + + // ContinuousBackupsStatus can be one of the following states : ENABLED, DISABLED + // + // ContinuousBackupsStatus is a required field + ContinuousBackupsStatus *string `type:"string" required:"true" enum:"ContinuousBackupsStatus"` +} + +// String returns the string representation +func (s ContinuousBackupsDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ContinuousBackupsDescription) GoString() string { + return s.String() +} + +// SetContinuousBackupsStatus sets the ContinuousBackupsStatus field's value. +func (s *ContinuousBackupsDescription) SetContinuousBackupsStatus(v string) *ContinuousBackupsDescription { + s.ContinuousBackupsStatus = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateBackupInput +type CreateBackupInput struct { + _ struct{} `type:"structure"` + + // Specified name for the backup. + // + // BackupName is a required field + BackupName *string `min:"3" type:"string" required:"true"` + + // The name of the table. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateBackupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateBackupInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *CreateBackupInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "CreateBackupInput"} + if s.BackupName == nil { + invalidParams.Add(request.NewErrParamRequired("BackupName")) + } + if s.BackupName != nil && len(*s.BackupName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("BackupName", 3)) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetBackupName sets the BackupName field's value. +func (s *CreateBackupInput) SetBackupName(v string) *CreateBackupInput { + s.BackupName = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *CreateBackupInput) SetTableName(v string) *CreateBackupInput { + s.TableName = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateBackupOutput +type CreateBackupOutput struct { + _ struct{} `type:"structure"` + + // Contains the details of the backup created for the table. + BackupDetails *BackupDetails `type:"structure"` +} + +// String returns the string representation +func (s CreateBackupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateBackupOutput) GoString() string { + return s.String() +} + +// SetBackupDetails sets the BackupDetails field's value. +func (s *CreateBackupOutput) SetBackupDetails(v *BackupDetails) *CreateBackupOutput { + s.BackupDetails = v + return s +} + +// Represents a new global secondary index to be added to an existing table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateGlobalSecondaryIndexAction +type CreateGlobalSecondaryIndexAction struct { + _ struct{} `type:"structure"` + + // The name of the global secondary index to be created. + // + // IndexName is a required field + IndexName *string `min:"3" type:"string" required:"true"` + + // The key schema for the global secondary index. + // + // KeySchema is a required field + KeySchema []*KeySchemaElement `min:"1" type:"list" required:"true"` + + // Represents attributes that are copied (projected) from the table into an + // index. These are in addition to the primary key attributes and index key + // attributes, which are automatically projected. + // + // Projection is a required field + Projection *Projection `type:"structure" required:"true"` + + // Represents the provisioned throughput settings for the specified global secondary + // index. + // + // For current minimum and maximum provisioned throughput values, see Limits + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) + // in the Amazon DynamoDB Developer Guide. + // + // ProvisionedThroughput is a required field + ProvisionedThroughput *ProvisionedThroughput `type:"structure" required:"true"` +} + +// String returns the string representation +func (s CreateGlobalSecondaryIndexAction) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateGlobalSecondaryIndexAction) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *CreateGlobalSecondaryIndexAction) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "CreateGlobalSecondaryIndexAction"} + if s.IndexName == nil { + invalidParams.Add(request.NewErrParamRequired("IndexName")) + } + if s.IndexName != nil && len(*s.IndexName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("IndexName", 3)) + } + if s.KeySchema == nil { + invalidParams.Add(request.NewErrParamRequired("KeySchema")) + } + if s.KeySchema != nil && len(s.KeySchema) < 1 { + invalidParams.Add(request.NewErrParamMinLen("KeySchema", 1)) + } + if s.Projection == nil { + invalidParams.Add(request.NewErrParamRequired("Projection")) + } + if s.ProvisionedThroughput == nil { + invalidParams.Add(request.NewErrParamRequired("ProvisionedThroughput")) + } + if s.KeySchema != nil { + for i, v := range s.KeySchema { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "KeySchema", i), err.(request.ErrInvalidParams)) + } + } + } + if s.Projection != nil { + if err := s.Projection.Validate(); err != nil { + invalidParams.AddNested("Projection", err.(request.ErrInvalidParams)) + } + } + if s.ProvisionedThroughput != nil { + if err := s.ProvisionedThroughput.Validate(); err != nil { + invalidParams.AddNested("ProvisionedThroughput", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetIndexName sets the IndexName field's value. +func (s *CreateGlobalSecondaryIndexAction) SetIndexName(v string) *CreateGlobalSecondaryIndexAction { + s.IndexName = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *CreateGlobalSecondaryIndexAction) SetKeySchema(v []*KeySchemaElement) *CreateGlobalSecondaryIndexAction { + s.KeySchema = v + return s +} + +// SetProjection sets the Projection field's value. +func (s *CreateGlobalSecondaryIndexAction) SetProjection(v *Projection) *CreateGlobalSecondaryIndexAction { + s.Projection = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *CreateGlobalSecondaryIndexAction) SetProvisionedThroughput(v *ProvisionedThroughput) *CreateGlobalSecondaryIndexAction { + s.ProvisionedThroughput = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateGlobalTableInput +type CreateGlobalTableInput struct { + _ struct{} `type:"structure"` + + // The global table name. + // + // GlobalTableName is a required field + GlobalTableName *string `min:"3" type:"string" required:"true"` + + // The regions where the global table needs to be created. + // + // ReplicationGroup is a required field + ReplicationGroup []*Replica `type:"list" required:"true"` +} + +// String returns the string representation +func (s CreateGlobalTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateGlobalTableInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *CreateGlobalTableInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "CreateGlobalTableInput"} + if s.GlobalTableName == nil { + invalidParams.Add(request.NewErrParamRequired("GlobalTableName")) + } + if s.GlobalTableName != nil && len(*s.GlobalTableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("GlobalTableName", 3)) + } + if s.ReplicationGroup == nil { + invalidParams.Add(request.NewErrParamRequired("ReplicationGroup")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetGlobalTableName sets the GlobalTableName field's value. +func (s *CreateGlobalTableInput) SetGlobalTableName(v string) *CreateGlobalTableInput { + s.GlobalTableName = &v + return s +} + +// SetReplicationGroup sets the ReplicationGroup field's value. +func (s *CreateGlobalTableInput) SetReplicationGroup(v []*Replica) *CreateGlobalTableInput { + s.ReplicationGroup = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateGlobalTableOutput +type CreateGlobalTableOutput struct { + _ struct{} `type:"structure"` + + // Contains the details of the global table. + GlobalTableDescription *GlobalTableDescription `type:"structure"` +} + +// String returns the string representation +func (s CreateGlobalTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateGlobalTableOutput) GoString() string { + return s.String() +} + +// SetGlobalTableDescription sets the GlobalTableDescription field's value. +func (s *CreateGlobalTableOutput) SetGlobalTableDescription(v *GlobalTableDescription) *CreateGlobalTableOutput { + s.GlobalTableDescription = v + return s +} + +// Represents a replica to be added. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateReplicaAction +type CreateReplicaAction struct { + _ struct{} `type:"structure"` + + // The region of the replica to be added. + // + // RegionName is a required field + RegionName *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateReplicaAction) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateReplicaAction) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *CreateReplicaAction) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "CreateReplicaAction"} + if s.RegionName == nil { + invalidParams.Add(request.NewErrParamRequired("RegionName")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetRegionName sets the RegionName field's value. +func (s *CreateReplicaAction) SetRegionName(v string) *CreateReplicaAction { + s.RegionName = &v + return s +} + +// Represents the input of a CreateTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateTableInput +type CreateTableInput struct { + _ struct{} `type:"structure"` + + // An array of attributes that describe the key schema for the table and indexes. + // + // AttributeDefinitions is a required field + AttributeDefinitions []*AttributeDefinition `type:"list" required:"true"` + + // One or more global secondary indexes (the maximum is five) to be created + // on the table. Each global secondary index in the array includes the following: + // + // * IndexName - The name of the global secondary index. Must be unique only + // for this table. + // + // * KeySchema - Specifies the key schema for the global secondary index. + // + // * Projection - Specifies attributes that are copied (projected) from the + // table into the index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. Each attribute + // specification is composed of: + // + // * ProjectionType - One of the following: + // + // KEYS_ONLY - Only the index and primary keys are projected into the index. + // + // INCLUDE - Only the specified table attributes are projected into the index. + // The list of projected attributes are in NonKeyAttributes. + // + // ALL - All of the table attributes are projected into the index. + // + // NonKeyAttributes - A list of one or more non-key attribute names that are + // projected into the secondary index. The total count of attributes provided + // in NonKeyAttributes, summed across all of the secondary indexes, must + // not exceed 20. If you project the same attribute into two different indexes, + // this counts as two distinct attributes when determining the total. + // + // * ProvisionedThroughput - The provisioned throughput settings for the + // global secondary index, consisting of read and write capacity units. + GlobalSecondaryIndexes []*GlobalSecondaryIndex `type:"list"` + + // Specifies the attributes that make up the primary key for a table or an index. + // The attributes in KeySchema must also be defined in the AttributeDefinitions + // array. For more information, see Data Model (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataModel.html) + // in the Amazon DynamoDB Developer Guide. + // + // Each KeySchemaElement in the array is composed of: + // + // * AttributeName - The name of this key attribute. + // + // * KeyType - The role that the key attribute will assume: + // + // HASH - partition key + // + // RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + // + // For a simple primary key (partition key), you must provide exactly one element + // with a KeyType of HASH. + // + // For a composite primary key (partition key and sort key), you must provide + // exactly two elements, in this order: The first element must have a KeyType + // of HASH, and the second element must have a KeyType of RANGE. + // + // For more information, see Specifying the Primary Key (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html#WorkingWithTables.primary.key) + // in the Amazon DynamoDB Developer Guide. + // + // KeySchema is a required field + KeySchema []*KeySchemaElement `min:"1" type:"list" required:"true"` + + // One or more local secondary indexes (the maximum is five) to be created on + // the table. Each index is scoped to a given partition key value. There is + // a 10 GB size limit per partition key value; otherwise, the size of a local + // secondary index is unconstrained. + // + // Each local secondary index in the array includes the following: + // + // * IndexName - The name of the local secondary index. Must be unique only + // for this table. + // + // * KeySchema - Specifies the key schema for the local secondary index. + // The key schema must begin with the same partition key as the table. + // + // * Projection - Specifies attributes that are copied (projected) from the + // table into the index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. Each attribute + // specification is composed of: + // + // * ProjectionType - One of the following: + // + // KEYS_ONLY - Only the index and primary keys are projected into the index. + // + // INCLUDE - Only the specified table attributes are projected into the index. + // The list of projected attributes are in NonKeyAttributes. + // + // ALL - All of the table attributes are projected into the index. + // + // NonKeyAttributes - A list of one or more non-key attribute names that are + // projected into the secondary index. The total count of attributes provided + // in NonKeyAttributes, summed across all of the secondary indexes, must + // not exceed 20. If you project the same attribute into two different indexes, + // this counts as two distinct attributes when determining the total. + LocalSecondaryIndexes []*LocalSecondaryIndex `type:"list"` + + // Represents the provisioned throughput settings for a specified table or index. + // The settings can be modified using the UpdateTable operation. + // + // For current minimum and maximum provisioned throughput values, see Limits + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) + // in the Amazon DynamoDB Developer Guide. + // + // ProvisionedThroughput is a required field + ProvisionedThroughput *ProvisionedThroughput `type:"structure" required:"true"` + + // The settings for DynamoDB Streams on the table. These settings consist of: + // + // * StreamEnabled - Indicates whether Streams is to be enabled (true) or + // disabled (false). + // + // * StreamViewType - When an item in the table is modified, StreamViewType + // determines what information is written to the table's stream. Valid values + // for StreamViewType are: + // + // KEYS_ONLY - Only the key attributes of the modified item are written to the + // stream. + // + // NEW_IMAGE - The entire item, as it appears after it was modified, is written + // to the stream. + // + // OLD_IMAGE - The entire item, as it appeared before it was modified, is written + // to the stream. + // + // NEW_AND_OLD_IMAGES - Both the new and the old item images of the item are + // written to the stream. + StreamSpecification *StreamSpecification `type:"structure"` + + // The name of the table to create. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s CreateTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateTableInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *CreateTableInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "CreateTableInput"} + if s.AttributeDefinitions == nil { + invalidParams.Add(request.NewErrParamRequired("AttributeDefinitions")) + } + if s.KeySchema == nil { + invalidParams.Add(request.NewErrParamRequired("KeySchema")) + } + if s.KeySchema != nil && len(s.KeySchema) < 1 { + invalidParams.Add(request.NewErrParamMinLen("KeySchema", 1)) + } + if s.ProvisionedThroughput == nil { + invalidParams.Add(request.NewErrParamRequired("ProvisionedThroughput")) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + if s.AttributeDefinitions != nil { + for i, v := range s.AttributeDefinitions { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "AttributeDefinitions", i), err.(request.ErrInvalidParams)) + } + } + } + if s.GlobalSecondaryIndexes != nil { + for i, v := range s.GlobalSecondaryIndexes { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "GlobalSecondaryIndexes", i), err.(request.ErrInvalidParams)) + } + } + } + if s.KeySchema != nil { + for i, v := range s.KeySchema { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "KeySchema", i), err.(request.ErrInvalidParams)) + } + } + } + if s.LocalSecondaryIndexes != nil { + for i, v := range s.LocalSecondaryIndexes { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "LocalSecondaryIndexes", i), err.(request.ErrInvalidParams)) + } + } + } + if s.ProvisionedThroughput != nil { + if err := s.ProvisionedThroughput.Validate(); err != nil { + invalidParams.AddNested("ProvisionedThroughput", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributeDefinitions sets the AttributeDefinitions field's value. +func (s *CreateTableInput) SetAttributeDefinitions(v []*AttributeDefinition) *CreateTableInput { + s.AttributeDefinitions = v + return s +} + +// SetGlobalSecondaryIndexes sets the GlobalSecondaryIndexes field's value. +func (s *CreateTableInput) SetGlobalSecondaryIndexes(v []*GlobalSecondaryIndex) *CreateTableInput { + s.GlobalSecondaryIndexes = v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *CreateTableInput) SetKeySchema(v []*KeySchemaElement) *CreateTableInput { + s.KeySchema = v + return s +} + +// SetLocalSecondaryIndexes sets the LocalSecondaryIndexes field's value. +func (s *CreateTableInput) SetLocalSecondaryIndexes(v []*LocalSecondaryIndex) *CreateTableInput { + s.LocalSecondaryIndexes = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *CreateTableInput) SetProvisionedThroughput(v *ProvisionedThroughput) *CreateTableInput { + s.ProvisionedThroughput = v + return s +} + +// SetStreamSpecification sets the StreamSpecification field's value. +func (s *CreateTableInput) SetStreamSpecification(v *StreamSpecification) *CreateTableInput { + s.StreamSpecification = v + return s +} + +// SetTableName sets the TableName field's value. +func (s *CreateTableInput) SetTableName(v string) *CreateTableInput { + s.TableName = &v + return s +} + +// Represents the output of a CreateTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/CreateTableOutput +type CreateTableOutput struct { + _ struct{} `type:"structure"` + + // Represents the properties of the table. + TableDescription *TableDescription `type:"structure"` +} + +// String returns the string representation +func (s CreateTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s CreateTableOutput) GoString() string { + return s.String() +} + +// SetTableDescription sets the TableDescription field's value. +func (s *CreateTableOutput) SetTableDescription(v *TableDescription) *CreateTableOutput { + s.TableDescription = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteBackupInput +type DeleteBackupInput struct { + _ struct{} `type:"structure"` + + // The ARN associated with the backup. + // + // BackupArn is a required field + BackupArn *string `min:"37" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteBackupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteBackupInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DeleteBackupInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DeleteBackupInput"} + if s.BackupArn == nil { + invalidParams.Add(request.NewErrParamRequired("BackupArn")) + } + if s.BackupArn != nil && len(*s.BackupArn) < 37 { + invalidParams.Add(request.NewErrParamMinLen("BackupArn", 37)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetBackupArn sets the BackupArn field's value. +func (s *DeleteBackupInput) SetBackupArn(v string) *DeleteBackupInput { + s.BackupArn = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteBackupOutput +type DeleteBackupOutput struct { + _ struct{} `type:"structure"` + + // Contains the description of the backup created for the table. + BackupDescription *BackupDescription `type:"structure"` +} + +// String returns the string representation +func (s DeleteBackupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteBackupOutput) GoString() string { + return s.String() +} + +// SetBackupDescription sets the BackupDescription field's value. +func (s *DeleteBackupOutput) SetBackupDescription(v *BackupDescription) *DeleteBackupOutput { + s.BackupDescription = v + return s +} + +// Represents a global secondary index to be deleted from an existing table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteGlobalSecondaryIndexAction +type DeleteGlobalSecondaryIndexAction struct { + _ struct{} `type:"structure"` + + // The name of the global secondary index to be deleted. + // + // IndexName is a required field + IndexName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteGlobalSecondaryIndexAction) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteGlobalSecondaryIndexAction) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DeleteGlobalSecondaryIndexAction) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DeleteGlobalSecondaryIndexAction"} + if s.IndexName == nil { + invalidParams.Add(request.NewErrParamRequired("IndexName")) + } + if s.IndexName != nil && len(*s.IndexName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("IndexName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetIndexName sets the IndexName field's value. +func (s *DeleteGlobalSecondaryIndexAction) SetIndexName(v string) *DeleteGlobalSecondaryIndexAction { + s.IndexName = &v + return s +} + +// Represents the input of a DeleteItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteItemInput +type DeleteItemInput struct { + _ struct{} `type:"structure"` + + // A condition that must be satisfied in order for a conditional DeleteItem + // to succeed. + // + // An expression can contain any of the following: + // + // * Functions: attribute_exists | attribute_not_exists | attribute_type + // | contains | begins_with | size + // + // These function names are case-sensitive. + // + // * Comparison operators: = | <> | < | > | <= | >= | BETWEEN | IN + // + // * Logical operators: AND | OR | NOT + // + // For more information on condition expressions, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ConditionExpression *string `type:"string"` + + // This is a legacy parameter. Use ConditionExpression instead. For more information, + // see ConditionalOperator (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ConditionalOperator.html) + // in the Amazon DynamoDB Developer Guide. + ConditionalOperator *string `type:"string" enum:"ConditionalOperator"` + + // This is a legacy parameter. Use ConditionExpression instead. For more information, + // see Expected (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.Expected.html) + // in the Amazon DynamoDB Developer Guide. + Expected map[string]*ExpectedAttributeValue `type:"map"` + + // One or more substitution tokens for attribute names in an expression. The + // following are some use cases for using ExpressionAttributeNames: + // + // * To access an attribute whose name conflicts with a DynamoDB reserved + // word. + // + // * To create a placeholder for repeating occurrences of an attribute name + // in an expression. + // + // * To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // * Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could specify + // the following for ExpressionAttributeNames: + // + // * {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // * #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeNames map[string]*string `type:"map"` + + // One or more values that can be substituted in an expression. + // + // Use the : (colon) character in an expression to dereference an attribute + // value. For example, suppose that you wanted to check whether the value of + // the ProductStatus attribute was one of the following: + // + // Available | Backordered | Discontinued + // + // You would first need to specify ExpressionAttributeValues as follows: + // + // { ":avail":{"S":"Available"}, ":back":{"S":"Backordered"}, ":disc":{"S":"Discontinued"} + // } + // + // You could then use these values in an expression, such as this: + // + // ProductStatus IN (:avail, :back, :disc) + // + // For more information on expression attribute values, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeValues map[string]*AttributeValue `type:"map"` + + // A map of attribute names to AttributeValue objects, representing the primary + // key of the item to delete. + // + // For the primary key, you must provide all of the attributes. For example, + // with a simple primary key, you only need to provide a value for the partition + // key. For a composite primary key, you must provide values for both the partition + // key and the sort key. + // + // Key is a required field + Key map[string]*AttributeValue `type:"map" required:"true"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` + + // Determines whether item collection metrics are returned. If set to SIZE, + // the response includes statistics about item collections, if any, that were + // modified during the operation are returned in the response. If set to NONE + // (the default), no statistics are returned. + ReturnItemCollectionMetrics *string `type:"string" enum:"ReturnItemCollectionMetrics"` + + // Use ReturnValues if you want to get the item attributes as they appeared + // before they were deleted. For DeleteItem, the valid values are: + // + // * NONE - If ReturnValues is not specified, or if its value is NONE, then + // nothing is returned. (This setting is the default for ReturnValues.) + // + // * ALL_OLD - The content of the old item is returned. + // + // The ReturnValues parameter is used by several DynamoDB operations; however, + // DeleteItem does not recognize any values other than NONE or ALL_OLD. + ReturnValues *string `type:"string" enum:"ReturnValue"` + + // The name of the table from which to delete the item. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteItemInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteItemInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DeleteItemInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DeleteItemInput"} + if s.Key == nil { + invalidParams.Add(request.NewErrParamRequired("Key")) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetConditionExpression sets the ConditionExpression field's value. +func (s *DeleteItemInput) SetConditionExpression(v string) *DeleteItemInput { + s.ConditionExpression = &v + return s +} + +// SetConditionalOperator sets the ConditionalOperator field's value. +func (s *DeleteItemInput) SetConditionalOperator(v string) *DeleteItemInput { + s.ConditionalOperator = &v + return s +} + +// SetExpected sets the Expected field's value. +func (s *DeleteItemInput) SetExpected(v map[string]*ExpectedAttributeValue) *DeleteItemInput { + s.Expected = v + return s +} + +// SetExpressionAttributeNames sets the ExpressionAttributeNames field's value. +func (s *DeleteItemInput) SetExpressionAttributeNames(v map[string]*string) *DeleteItemInput { + s.ExpressionAttributeNames = v + return s +} + +// SetExpressionAttributeValues sets the ExpressionAttributeValues field's value. +func (s *DeleteItemInput) SetExpressionAttributeValues(v map[string]*AttributeValue) *DeleteItemInput { + s.ExpressionAttributeValues = v + return s +} + +// SetKey sets the Key field's value. +func (s *DeleteItemInput) SetKey(v map[string]*AttributeValue) *DeleteItemInput { + s.Key = v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *DeleteItemInput) SetReturnConsumedCapacity(v string) *DeleteItemInput { + s.ReturnConsumedCapacity = &v + return s +} + +// SetReturnItemCollectionMetrics sets the ReturnItemCollectionMetrics field's value. +func (s *DeleteItemInput) SetReturnItemCollectionMetrics(v string) *DeleteItemInput { + s.ReturnItemCollectionMetrics = &v + return s +} + +// SetReturnValues sets the ReturnValues field's value. +func (s *DeleteItemInput) SetReturnValues(v string) *DeleteItemInput { + s.ReturnValues = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *DeleteItemInput) SetTableName(v string) *DeleteItemInput { + s.TableName = &v + return s +} + +// Represents the output of a DeleteItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteItemOutput +type DeleteItemOutput struct { + _ struct{} `type:"structure"` + + // A map of attribute names to AttributeValue objects, representing the item + // as it appeared before the DeleteItem operation. This map appears in the response + // only if ReturnValues was specified as ALL_OLD in the request. + Attributes map[string]*AttributeValue `type:"map"` + + // The capacity units consumed by the DeleteItem operation. The data returned + // includes the total provisioned throughput consumed, along with statistics + // for the table and any indexes involved in the operation. ConsumedCapacity + // is only returned if the ReturnConsumedCapacity parameter was specified. For + // more information, see Provisioned Throughput (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) + // in the Amazon DynamoDB Developer Guide. + ConsumedCapacity *ConsumedCapacity `type:"structure"` + + // Information about item collections, if any, that were affected by the DeleteItem + // operation. ItemCollectionMetrics is only returned if the ReturnItemCollectionMetrics + // parameter was specified. If the table does not have any local secondary indexes, + // this information is not returned in the response. + // + // Each ItemCollectionMetrics element consists of: + // + // * ItemCollectionKey - The partition key value of the item collection. + // This is the same as the partition key value of the item itself. + // + // * SizeEstimateRangeGB - An estimate of item collection size, in gigabytes. + // This value is a two-element array containing a lower bound and an upper + // bound for the estimate. The estimate includes the size of all the items + // in the table, plus the size of all attributes projected into all of the + // local secondary indexes on that table. Use this estimate to measure whether + // a local secondary index is approaching its size limit. + // + // The estimate is subject to change over time; therefore, do not rely on the + // precision or accuracy of the estimate. + ItemCollectionMetrics *ItemCollectionMetrics `type:"structure"` +} + +// String returns the string representation +func (s DeleteItemOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteItemOutput) GoString() string { + return s.String() +} + +// SetAttributes sets the Attributes field's value. +func (s *DeleteItemOutput) SetAttributes(v map[string]*AttributeValue) *DeleteItemOutput { + s.Attributes = v + return s +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *DeleteItemOutput) SetConsumedCapacity(v *ConsumedCapacity) *DeleteItemOutput { + s.ConsumedCapacity = v + return s +} + +// SetItemCollectionMetrics sets the ItemCollectionMetrics field's value. +func (s *DeleteItemOutput) SetItemCollectionMetrics(v *ItemCollectionMetrics) *DeleteItemOutput { + s.ItemCollectionMetrics = v + return s +} + +// Represents a replica to be removed. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteReplicaAction +type DeleteReplicaAction struct { + _ struct{} `type:"structure"` + + // The region of the replica to be removed. + // + // RegionName is a required field + RegionName *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteReplicaAction) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteReplicaAction) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DeleteReplicaAction) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DeleteReplicaAction"} + if s.RegionName == nil { + invalidParams.Add(request.NewErrParamRequired("RegionName")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetRegionName sets the RegionName field's value. +func (s *DeleteReplicaAction) SetRegionName(v string) *DeleteReplicaAction { + s.RegionName = &v + return s +} + +// Represents a request to perform a DeleteItem operation on an item. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteRequest +type DeleteRequest struct { + _ struct{} `type:"structure"` + + // A map of attribute name to attribute values, representing the primary key + // of the item to delete. All of the table's primary key attributes must be + // specified, and their data types must match those of the table's key schema. + // + // Key is a required field + Key map[string]*AttributeValue `type:"map" required:"true"` +} + +// String returns the string representation +func (s DeleteRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteRequest) GoString() string { + return s.String() +} + +// SetKey sets the Key field's value. +func (s *DeleteRequest) SetKey(v map[string]*AttributeValue) *DeleteRequest { + s.Key = v + return s +} + +// Represents the input of a DeleteTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteTableInput +type DeleteTableInput struct { + _ struct{} `type:"structure"` + + // The name of the table to delete. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s DeleteTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteTableInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DeleteTableInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DeleteTableInput"} + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetTableName sets the TableName field's value. +func (s *DeleteTableInput) SetTableName(v string) *DeleteTableInput { + s.TableName = &v + return s +} + +// Represents the output of a DeleteTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DeleteTableOutput +type DeleteTableOutput struct { + _ struct{} `type:"structure"` + + // Represents the properties of a table. + TableDescription *TableDescription `type:"structure"` +} + +// String returns the string representation +func (s DeleteTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DeleteTableOutput) GoString() string { + return s.String() +} + +// SetTableDescription sets the TableDescription field's value. +func (s *DeleteTableOutput) SetTableDescription(v *TableDescription) *DeleteTableOutput { + s.TableDescription = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeBackupInput +type DescribeBackupInput struct { + _ struct{} `type:"structure"` + + // The ARN associated with the backup. + // + // BackupArn is a required field + BackupArn *string `min:"37" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeBackupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeBackupInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DescribeBackupInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DescribeBackupInput"} + if s.BackupArn == nil { + invalidParams.Add(request.NewErrParamRequired("BackupArn")) + } + if s.BackupArn != nil && len(*s.BackupArn) < 37 { + invalidParams.Add(request.NewErrParamMinLen("BackupArn", 37)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetBackupArn sets the BackupArn field's value. +func (s *DescribeBackupInput) SetBackupArn(v string) *DescribeBackupInput { + s.BackupArn = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeBackupOutput +type DescribeBackupOutput struct { + _ struct{} `type:"structure"` + + // Contains the description of the backup created for the table. + BackupDescription *BackupDescription `type:"structure"` +} + +// String returns the string representation +func (s DescribeBackupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeBackupOutput) GoString() string { + return s.String() +} + +// SetBackupDescription sets the BackupDescription field's value. +func (s *DescribeBackupOutput) SetBackupDescription(v *BackupDescription) *DescribeBackupOutput { + s.BackupDescription = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeContinuousBackupsInput +type DescribeContinuousBackupsInput struct { + _ struct{} `type:"structure"` + + // Name of the table for which the customer wants to check the backup and restore + // settings. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeContinuousBackupsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeContinuousBackupsInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DescribeContinuousBackupsInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DescribeContinuousBackupsInput"} + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetTableName sets the TableName field's value. +func (s *DescribeContinuousBackupsInput) SetTableName(v string) *DescribeContinuousBackupsInput { + s.TableName = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeContinuousBackupsOutput +type DescribeContinuousBackupsOutput struct { + _ struct{} `type:"structure"` + + // ContinuousBackupsDescription can be one of the following : ENABLED, DISABLED. + ContinuousBackupsDescription *ContinuousBackupsDescription `type:"structure"` +} + +// String returns the string representation +func (s DescribeContinuousBackupsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeContinuousBackupsOutput) GoString() string { + return s.String() +} + +// SetContinuousBackupsDescription sets the ContinuousBackupsDescription field's value. +func (s *DescribeContinuousBackupsOutput) SetContinuousBackupsDescription(v *ContinuousBackupsDescription) *DescribeContinuousBackupsOutput { + s.ContinuousBackupsDescription = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeGlobalTableInput +type DescribeGlobalTableInput struct { + _ struct{} `type:"structure"` + + // The name of the global table. + // + // GlobalTableName is a required field + GlobalTableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeGlobalTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeGlobalTableInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DescribeGlobalTableInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DescribeGlobalTableInput"} + if s.GlobalTableName == nil { + invalidParams.Add(request.NewErrParamRequired("GlobalTableName")) + } + if s.GlobalTableName != nil && len(*s.GlobalTableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("GlobalTableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetGlobalTableName sets the GlobalTableName field's value. +func (s *DescribeGlobalTableInput) SetGlobalTableName(v string) *DescribeGlobalTableInput { + s.GlobalTableName = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeGlobalTableOutput +type DescribeGlobalTableOutput struct { + _ struct{} `type:"structure"` + + // Contains the details of the global table. + GlobalTableDescription *GlobalTableDescription `type:"structure"` +} + +// String returns the string representation +func (s DescribeGlobalTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeGlobalTableOutput) GoString() string { + return s.String() +} + +// SetGlobalTableDescription sets the GlobalTableDescription field's value. +func (s *DescribeGlobalTableOutput) SetGlobalTableDescription(v *GlobalTableDescription) *DescribeGlobalTableOutput { + s.GlobalTableDescription = v + return s +} + +// Represents the input of a DescribeLimits operation. Has no content. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeLimitsInput +type DescribeLimitsInput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s DescribeLimitsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeLimitsInput) GoString() string { + return s.String() +} + +// Represents the output of a DescribeLimits operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeLimitsOutput +type DescribeLimitsOutput struct { + _ struct{} `type:"structure"` + + // The maximum total read capacity units that your account allows you to provision + // across all of your tables in this region. + AccountMaxReadCapacityUnits *int64 `min:"1" type:"long"` + + // The maximum total write capacity units that your account allows you to provision + // across all of your tables in this region. + AccountMaxWriteCapacityUnits *int64 `min:"1" type:"long"` + + // The maximum read capacity units that your account allows you to provision + // for a new table that you are creating in this region, including the read + // capacity units provisioned for its global secondary indexes (GSIs). + TableMaxReadCapacityUnits *int64 `min:"1" type:"long"` + + // The maximum write capacity units that your account allows you to provision + // for a new table that you are creating in this region, including the write + // capacity units provisioned for its global secondary indexes (GSIs). + TableMaxWriteCapacityUnits *int64 `min:"1" type:"long"` +} + +// String returns the string representation +func (s DescribeLimitsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeLimitsOutput) GoString() string { + return s.String() +} + +// SetAccountMaxReadCapacityUnits sets the AccountMaxReadCapacityUnits field's value. +func (s *DescribeLimitsOutput) SetAccountMaxReadCapacityUnits(v int64) *DescribeLimitsOutput { + s.AccountMaxReadCapacityUnits = &v + return s +} + +// SetAccountMaxWriteCapacityUnits sets the AccountMaxWriteCapacityUnits field's value. +func (s *DescribeLimitsOutput) SetAccountMaxWriteCapacityUnits(v int64) *DescribeLimitsOutput { + s.AccountMaxWriteCapacityUnits = &v + return s +} + +// SetTableMaxReadCapacityUnits sets the TableMaxReadCapacityUnits field's value. +func (s *DescribeLimitsOutput) SetTableMaxReadCapacityUnits(v int64) *DescribeLimitsOutput { + s.TableMaxReadCapacityUnits = &v + return s +} + +// SetTableMaxWriteCapacityUnits sets the TableMaxWriteCapacityUnits field's value. +func (s *DescribeLimitsOutput) SetTableMaxWriteCapacityUnits(v int64) *DescribeLimitsOutput { + s.TableMaxWriteCapacityUnits = &v + return s +} + +// Represents the input of a DescribeTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTableInput +type DescribeTableInput struct { + _ struct{} `type:"structure"` + + // The name of the table to describe. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeTableInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DescribeTableInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DescribeTableInput"} + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetTableName sets the TableName field's value. +func (s *DescribeTableInput) SetTableName(v string) *DescribeTableInput { + s.TableName = &v + return s +} + +// Represents the output of a DescribeTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTableOutput +type DescribeTableOutput struct { + _ struct{} `type:"structure"` + + // The properties of the table. + Table *TableDescription `type:"structure"` +} + +// String returns the string representation +func (s DescribeTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeTableOutput) GoString() string { + return s.String() +} + +// SetTable sets the Table field's value. +func (s *DescribeTableOutput) SetTable(v *TableDescription) *DescribeTableOutput { + s.Table = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTimeToLiveInput +type DescribeTimeToLiveInput struct { + _ struct{} `type:"structure"` + + // The name of the table to be described. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s DescribeTimeToLiveInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeTimeToLiveInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DescribeTimeToLiveInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DescribeTimeToLiveInput"} + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetTableName sets the TableName field's value. +func (s *DescribeTimeToLiveInput) SetTableName(v string) *DescribeTimeToLiveInput { + s.TableName = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/DescribeTimeToLiveOutput +type DescribeTimeToLiveOutput struct { + _ struct{} `type:"structure"` + + // The description of the Time to Live (TTL) status on the specified table. + TimeToLiveDescription *TimeToLiveDescription `type:"structure"` +} + +// String returns the string representation +func (s DescribeTimeToLiveOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DescribeTimeToLiveOutput) GoString() string { + return s.String() +} + +// SetTimeToLiveDescription sets the TimeToLiveDescription field's value. +func (s *DescribeTimeToLiveOutput) SetTimeToLiveDescription(v *TimeToLiveDescription) *DescribeTimeToLiveOutput { + s.TimeToLiveDescription = v + return s +} + +// Represents a condition to be compared with an attribute value. This condition +// can be used with DeleteItem, PutItem or UpdateItem operations; if the comparison +// evaluates to true, the operation succeeds; if not, the operation fails. You +// can use ExpectedAttributeValue in one of two different ways: +// +// * Use AttributeValueList to specify one or more values to compare against +// an attribute. Use ComparisonOperator to specify how you want to perform +// the comparison. If the comparison evaluates to true, then the conditional +// operation succeeds. +// +// * Use Value to specify a value that DynamoDB will compare against an attribute. +// If the values match, then ExpectedAttributeValue evaluates to true and +// the conditional operation succeeds. Optionally, you can also set Exists +// to false, indicating that you do not expect to find the attribute value +// in the table. In this case, the conditional operation succeeds only if +// the comparison evaluates to false. +// +// Value and Exists are incompatible with AttributeValueList and ComparisonOperator. +// Note that if you use both sets of parameters at once, DynamoDB will return +// a ValidationException exception. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ExpectedAttributeValue +type ExpectedAttributeValue struct { + _ struct{} `type:"structure"` + + // One or more values to evaluate against the supplied attribute. The number + // of values in the list depends on the ComparisonOperator being used. + // + // For type Number, value comparisons are numeric. + // + // String value comparisons for greater than, equals, or less than are based + // on ASCII character code values. For example, a is greater than A, and a is + // greater than B. For a list of code values, see http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters + // (http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters). + // + // For Binary, DynamoDB treats each byte of the binary data as unsigned when + // it compares binary values. + // + // For information on specifying data types in JSON, see JSON Data Format (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataFormat.html) + // in the Amazon DynamoDB Developer Guide. + AttributeValueList []*AttributeValue `type:"list"` + + // A comparator for evaluating attributes in the AttributeValueList. For example, + // equals, greater than, less than, etc. + // + // The following comparison operators are available: + // + // EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | + // BEGINS_WITH | IN | BETWEEN + // + // The following are descriptions of each comparison operator. + // + // * EQ : Equal. EQ is supported for all data types, including lists and + // maps. + // + // AttributeValueList can contain only one AttributeValue element of type String, + // Number, Binary, String Set, Number Set, or Binary Set. If an item contains + // an AttributeValue element of a different type than the one provided in + // the request, the value does not match. For example, {"S":"6"} does not + // equal {"N":"6"}. Also, {"N":"6"} does not equal {"NS":["6", "2", "1"]}. + // + // * NE : Not equal. NE is supported for all data types, including lists + // and maps. + // + // * AttributeValueList can contain only one AttributeValue of type String, + // Number, Binary, String Set, Number Set, or Binary Set. If an item contains + // an AttributeValue of a different type than the one provided in the request, + // the value does not match. For example, {"S":"6"} does not equal {"N":"6"}. + // Also, {"N":"6"} does not equal {"NS":["6", "2", "1"]}. + // + // * LE : Less than or equal. + // + // AttributeValueList can contain only one AttributeValue element of type String, + // Number, or Binary (not a set type). If an item contains an AttributeValue + // element of a different type than the one provided in the request, the value + // does not match. For example, {"S":"6"} does not equal {"N":"6"}. Also, {"N":"6"} + // does not compare to {"NS":["6", "2", "1"]}. + // + // LT: Less than. + // + // AttributeValueListcan contain only one AttributeValueof type String, Number, or Binary (not a set type). If an item contains an + // AttributeValueelement of a different type than the one provided in the request, the value + // does not match. For example, {"S":"6"}does not equal {"N":"6"}. Also, {"N":"6"}does not compare to {"NS":["6", "2", "1"]} + ComparisonOperator *string `type:"string" enum:"ComparisonOperator"` + + // Causes DynamoDB to evaluate the value before attempting a conditional operation: + // + // * If Exists is true, DynamoDB will check to see if that attribute value + // already exists in the table. If it is found, then the operation succeeds. + // If it is not found, the operation fails with a ConditionalCheckFailedException. + // + // * If Exists is false, DynamoDB assumes that the attribute value does not + // exist in the table. If in fact the value does not exist, then the assumption + // is valid and the operation succeeds. If the value is found, despite the + // assumption that it does not exist, the operation fails with a ConditionalCheckFailedException. + // + // The default setting for Exists is true. If you supply a Value all by itself, + // DynamoDB assumes the attribute exists: You don't have to set Exists to true, + // because it is implied. + // + // DynamoDB returns a ValidationException if: + // + // * Exists is true but there is no Value to check. (You expect a value to + // exist, but don't specify what that value is.) + // + // * Exists is false but you also provide a Value. (You cannot expect an + // attribute to have a value, while also expecting it not to exist.) + Exists *bool `type:"boolean"` + + // Represents the data for the expected attribute. + // + // Each attribute value is described as a name-value pair. The name is the data + // type, and the value is the data itself. + // + // For more information, see Data Types (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) + // in the Amazon DynamoDB Developer Guide. + Value *AttributeValue `type:"structure"` +} + +// String returns the string representation +func (s ExpectedAttributeValue) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ExpectedAttributeValue) GoString() string { + return s.String() +} + +// SetAttributeValueList sets the AttributeValueList field's value. +func (s *ExpectedAttributeValue) SetAttributeValueList(v []*AttributeValue) *ExpectedAttributeValue { + s.AttributeValueList = v + return s +} + +// SetComparisonOperator sets the ComparisonOperator field's value. +func (s *ExpectedAttributeValue) SetComparisonOperator(v string) *ExpectedAttributeValue { + s.ComparisonOperator = &v + return s +} + +// SetExists sets the Exists field's value. +func (s *ExpectedAttributeValue) SetExists(v bool) *ExpectedAttributeValue { + s.Exists = &v + return s +} + +// SetValue sets the Value field's value. +func (s *ExpectedAttributeValue) SetValue(v *AttributeValue) *ExpectedAttributeValue { + s.Value = v + return s +} + +// Represents the input of a GetItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GetItemInput +type GetItemInput struct { + _ struct{} `type:"structure"` + + // This is a legacy parameter. Use ProjectionExpression instead. For more information, + // see AttributesToGet (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributesToGet.html) + // in the Amazon DynamoDB Developer Guide. + AttributesToGet []*string `min:"1" type:"list"` + + // Determines the read consistency model: If set to true, then the operation + // uses strongly consistent reads; otherwise, the operation uses eventually + // consistent reads. + ConsistentRead *bool `type:"boolean"` + + // One or more substitution tokens for attribute names in an expression. The + // following are some use cases for using ExpressionAttributeNames: + // + // * To access an attribute whose name conflicts with a DynamoDB reserved + // word. + // + // * To create a placeholder for repeating occurrences of an attribute name + // in an expression. + // + // * To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // * Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could specify + // the following for ExpressionAttributeNames: + // + // * {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // * #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeNames map[string]*string `type:"map"` + + // A map of attribute names to AttributeValue objects, representing the primary + // key of the item to retrieve. + // + // For the primary key, you must provide all of the attributes. For example, + // with a simple primary key, you only need to provide a value for the partition + // key. For a composite primary key, you must provide values for both the partition + // key and the sort key. + // + // Key is a required field + Key map[string]*AttributeValue `type:"map" required:"true"` + + // A string that identifies one or more attributes to retrieve from the table. + // These attributes can include scalars, sets, or elements of a JSON document. + // The attributes in the expression must be separated by commas. + // + // If no attribute names are specified, then all attributes will be returned. + // If any of the requested attributes are not found, they will not appear in + // the result. + // + // For more information, see Accessing Item Attributes (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ProjectionExpression *string `type:"string"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` + + // The name of the table containing the requested item. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s GetItemInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetItemInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetItemInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetItemInput"} + if s.AttributesToGet != nil && len(s.AttributesToGet) < 1 { + invalidParams.Add(request.NewErrParamMinLen("AttributesToGet", 1)) + } + if s.Key == nil { + invalidParams.Add(request.NewErrParamRequired("Key")) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributesToGet sets the AttributesToGet field's value. +func (s *GetItemInput) SetAttributesToGet(v []*string) *GetItemInput { + s.AttributesToGet = v + return s +} + +// SetConsistentRead sets the ConsistentRead field's value. +func (s *GetItemInput) SetConsistentRead(v bool) *GetItemInput { + s.ConsistentRead = &v + return s +} + +// SetExpressionAttributeNames sets the ExpressionAttributeNames field's value. +func (s *GetItemInput) SetExpressionAttributeNames(v map[string]*string) *GetItemInput { + s.ExpressionAttributeNames = v + return s +} + +// SetKey sets the Key field's value. +func (s *GetItemInput) SetKey(v map[string]*AttributeValue) *GetItemInput { + s.Key = v + return s +} + +// SetProjectionExpression sets the ProjectionExpression field's value. +func (s *GetItemInput) SetProjectionExpression(v string) *GetItemInput { + s.ProjectionExpression = &v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *GetItemInput) SetReturnConsumedCapacity(v string) *GetItemInput { + s.ReturnConsumedCapacity = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *GetItemInput) SetTableName(v string) *GetItemInput { + s.TableName = &v + return s +} + +// Represents the output of a GetItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GetItemOutput +type GetItemOutput struct { + _ struct{} `type:"structure"` + + // The capacity units consumed by the GetItem operation. The data returned includes + // the total provisioned throughput consumed, along with statistics for the + // table and any indexes involved in the operation. ConsumedCapacity is only + // returned if the ReturnConsumedCapacity parameter was specified. For more + // information, see Provisioned Throughput (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) + // in the Amazon DynamoDB Developer Guide. + ConsumedCapacity *ConsumedCapacity `type:"structure"` + + // A map of attribute names to AttributeValue objects, as specified by ProjectionExpression. + Item map[string]*AttributeValue `type:"map"` +} + +// String returns the string representation +func (s GetItemOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetItemOutput) GoString() string { + return s.String() +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *GetItemOutput) SetConsumedCapacity(v *ConsumedCapacity) *GetItemOutput { + s.ConsumedCapacity = v + return s +} + +// SetItem sets the Item field's value. +func (s *GetItemOutput) SetItem(v map[string]*AttributeValue) *GetItemOutput { + s.Item = v + return s +} + +// Represents the properties of a global secondary index. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GlobalSecondaryIndex +type GlobalSecondaryIndex struct { + _ struct{} `type:"structure"` + + // The name of the global secondary index. The name must be unique among all + // other indexes on this table. + // + // IndexName is a required field + IndexName *string `min:"3" type:"string" required:"true"` + + // The complete key schema for a global secondary index, which consists of one + // or more pairs of attribute names and key types: + // + // * HASH - partition key + // + // * RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + // + // KeySchema is a required field + KeySchema []*KeySchemaElement `min:"1" type:"list" required:"true"` + + // Represents attributes that are copied (projected) from the table into the + // global secondary index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. + // + // Projection is a required field + Projection *Projection `type:"structure" required:"true"` + + // Represents the provisioned throughput settings for the specified global secondary + // index. + // + // For current minimum and maximum provisioned throughput values, see Limits + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) + // in the Amazon DynamoDB Developer Guide. + // + // ProvisionedThroughput is a required field + ProvisionedThroughput *ProvisionedThroughput `type:"structure" required:"true"` +} + +// String returns the string representation +func (s GlobalSecondaryIndex) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GlobalSecondaryIndex) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GlobalSecondaryIndex) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GlobalSecondaryIndex"} + if s.IndexName == nil { + invalidParams.Add(request.NewErrParamRequired("IndexName")) + } + if s.IndexName != nil && len(*s.IndexName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("IndexName", 3)) + } + if s.KeySchema == nil { + invalidParams.Add(request.NewErrParamRequired("KeySchema")) + } + if s.KeySchema != nil && len(s.KeySchema) < 1 { + invalidParams.Add(request.NewErrParamMinLen("KeySchema", 1)) + } + if s.Projection == nil { + invalidParams.Add(request.NewErrParamRequired("Projection")) + } + if s.ProvisionedThroughput == nil { + invalidParams.Add(request.NewErrParamRequired("ProvisionedThroughput")) + } + if s.KeySchema != nil { + for i, v := range s.KeySchema { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "KeySchema", i), err.(request.ErrInvalidParams)) + } + } + } + if s.Projection != nil { + if err := s.Projection.Validate(); err != nil { + invalidParams.AddNested("Projection", err.(request.ErrInvalidParams)) + } + } + if s.ProvisionedThroughput != nil { + if err := s.ProvisionedThroughput.Validate(); err != nil { + invalidParams.AddNested("ProvisionedThroughput", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetIndexName sets the IndexName field's value. +func (s *GlobalSecondaryIndex) SetIndexName(v string) *GlobalSecondaryIndex { + s.IndexName = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *GlobalSecondaryIndex) SetKeySchema(v []*KeySchemaElement) *GlobalSecondaryIndex { + s.KeySchema = v + return s +} + +// SetProjection sets the Projection field's value. +func (s *GlobalSecondaryIndex) SetProjection(v *Projection) *GlobalSecondaryIndex { + s.Projection = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *GlobalSecondaryIndex) SetProvisionedThroughput(v *ProvisionedThroughput) *GlobalSecondaryIndex { + s.ProvisionedThroughput = v + return s +} + +// Represents the properties of a global secondary index. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GlobalSecondaryIndexDescription +type GlobalSecondaryIndexDescription struct { + _ struct{} `type:"structure"` + + // Indicates whether the index is currently backfilling. Backfilling is the + // process of reading items from the table and determining whether they can + // be added to the index. (Not all items will qualify: For example, a partition + // key cannot have any duplicate values.) If an item can be added to the index, + // DynamoDB will do so. After all items have been processed, the backfilling + // operation is complete and Backfilling is false. + // + // For indexes that were created during a CreateTable operation, the Backfilling + // attribute does not appear in the DescribeTable output. + Backfilling *bool `type:"boolean"` + + // The Amazon Resource Name (ARN) that uniquely identifies the index. + IndexArn *string `type:"string"` + + // The name of the global secondary index. + IndexName *string `min:"3" type:"string"` + + // The total size of the specified index, in bytes. DynamoDB updates this value + // approximately every six hours. Recent changes might not be reflected in this + // value. + IndexSizeBytes *int64 `type:"long"` + + // The current state of the global secondary index: + // + // * CREATING - The index is being created. + // + // * UPDATING - The index is being updated. + // + // * DELETING - The index is being deleted. + // + // * ACTIVE - The index is ready for use. + IndexStatus *string `type:"string" enum:"IndexStatus"` + + // The number of items in the specified index. DynamoDB updates this value approximately + // every six hours. Recent changes might not be reflected in this value. + ItemCount *int64 `type:"long"` + + // The complete key schema for a global secondary index, which consists of one + // or more pairs of attribute names and key types: + // + // * HASH - partition key + // + // * RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + KeySchema []*KeySchemaElement `min:"1" type:"list"` + + // Represents attributes that are copied (projected) from the table into the + // global secondary index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. + Projection *Projection `type:"structure"` + + // Represents the provisioned throughput settings for the specified global secondary + // index. + // + // For current minimum and maximum provisioned throughput values, see Limits + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) + // in the Amazon DynamoDB Developer Guide. + ProvisionedThroughput *ProvisionedThroughputDescription `type:"structure"` +} + +// String returns the string representation +func (s GlobalSecondaryIndexDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GlobalSecondaryIndexDescription) GoString() string { + return s.String() +} + +// SetBackfilling sets the Backfilling field's value. +func (s *GlobalSecondaryIndexDescription) SetBackfilling(v bool) *GlobalSecondaryIndexDescription { + s.Backfilling = &v + return s +} + +// SetIndexArn sets the IndexArn field's value. +func (s *GlobalSecondaryIndexDescription) SetIndexArn(v string) *GlobalSecondaryIndexDescription { + s.IndexArn = &v + return s +} + +// SetIndexName sets the IndexName field's value. +func (s *GlobalSecondaryIndexDescription) SetIndexName(v string) *GlobalSecondaryIndexDescription { + s.IndexName = &v + return s +} + +// SetIndexSizeBytes sets the IndexSizeBytes field's value. +func (s *GlobalSecondaryIndexDescription) SetIndexSizeBytes(v int64) *GlobalSecondaryIndexDescription { + s.IndexSizeBytes = &v + return s +} + +// SetIndexStatus sets the IndexStatus field's value. +func (s *GlobalSecondaryIndexDescription) SetIndexStatus(v string) *GlobalSecondaryIndexDescription { + s.IndexStatus = &v + return s +} + +// SetItemCount sets the ItemCount field's value. +func (s *GlobalSecondaryIndexDescription) SetItemCount(v int64) *GlobalSecondaryIndexDescription { + s.ItemCount = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *GlobalSecondaryIndexDescription) SetKeySchema(v []*KeySchemaElement) *GlobalSecondaryIndexDescription { + s.KeySchema = v + return s +} + +// SetProjection sets the Projection field's value. +func (s *GlobalSecondaryIndexDescription) SetProjection(v *Projection) *GlobalSecondaryIndexDescription { + s.Projection = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *GlobalSecondaryIndexDescription) SetProvisionedThroughput(v *ProvisionedThroughputDescription) *GlobalSecondaryIndexDescription { + s.ProvisionedThroughput = v + return s +} + +// Represents the properties of a global secondary index for the table when +// the backup was created. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GlobalSecondaryIndexInfo +type GlobalSecondaryIndexInfo struct { + _ struct{} `type:"structure"` + + // The name of the global secondary index. + IndexName *string `min:"3" type:"string"` + + // The complete key schema for a global secondary index, which consists of one + // or more pairs of attribute names and key types: + // + // * HASH - partition key + // + // * RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + KeySchema []*KeySchemaElement `min:"1" type:"list"` + + // Represents attributes that are copied (projected) from the table into the + // global secondary index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. + Projection *Projection `type:"structure"` + + // Represents the provisioned throughput settings for the specified global secondary + // index. + ProvisionedThroughput *ProvisionedThroughput `type:"structure"` +} + +// String returns the string representation +func (s GlobalSecondaryIndexInfo) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GlobalSecondaryIndexInfo) GoString() string { + return s.String() +} + +// SetIndexName sets the IndexName field's value. +func (s *GlobalSecondaryIndexInfo) SetIndexName(v string) *GlobalSecondaryIndexInfo { + s.IndexName = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *GlobalSecondaryIndexInfo) SetKeySchema(v []*KeySchemaElement) *GlobalSecondaryIndexInfo { + s.KeySchema = v + return s +} + +// SetProjection sets the Projection field's value. +func (s *GlobalSecondaryIndexInfo) SetProjection(v *Projection) *GlobalSecondaryIndexInfo { + s.Projection = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *GlobalSecondaryIndexInfo) SetProvisionedThroughput(v *ProvisionedThroughput) *GlobalSecondaryIndexInfo { + s.ProvisionedThroughput = v + return s +} + +// Represents one of the following: +// +// * A new global secondary index to be added to an existing table. +// +// * New provisioned throughput parameters for an existing global secondary +// index. +// +// * An existing global secondary index to be removed from an existing table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GlobalSecondaryIndexUpdate +type GlobalSecondaryIndexUpdate struct { + _ struct{} `type:"structure"` + + // The parameters required for creating a global secondary index on an existing + // table: + // + // * IndexName + // + // * KeySchema + // + // * AttributeDefinitions + // + // * Projection + // + // * ProvisionedThroughput + Create *CreateGlobalSecondaryIndexAction `type:"structure"` + + // The name of an existing global secondary index to be removed. + Delete *DeleteGlobalSecondaryIndexAction `type:"structure"` + + // The name of an existing global secondary index, along with new provisioned + // throughput settings to be applied to that index. + Update *UpdateGlobalSecondaryIndexAction `type:"structure"` +} + +// String returns the string representation +func (s GlobalSecondaryIndexUpdate) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GlobalSecondaryIndexUpdate) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GlobalSecondaryIndexUpdate) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GlobalSecondaryIndexUpdate"} + if s.Create != nil { + if err := s.Create.Validate(); err != nil { + invalidParams.AddNested("Create", err.(request.ErrInvalidParams)) + } + } + if s.Delete != nil { + if err := s.Delete.Validate(); err != nil { + invalidParams.AddNested("Delete", err.(request.ErrInvalidParams)) + } + } + if s.Update != nil { + if err := s.Update.Validate(); err != nil { + invalidParams.AddNested("Update", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetCreate sets the Create field's value. +func (s *GlobalSecondaryIndexUpdate) SetCreate(v *CreateGlobalSecondaryIndexAction) *GlobalSecondaryIndexUpdate { + s.Create = v + return s +} + +// SetDelete sets the Delete field's value. +func (s *GlobalSecondaryIndexUpdate) SetDelete(v *DeleteGlobalSecondaryIndexAction) *GlobalSecondaryIndexUpdate { + s.Delete = v + return s +} + +// SetUpdate sets the Update field's value. +func (s *GlobalSecondaryIndexUpdate) SetUpdate(v *UpdateGlobalSecondaryIndexAction) *GlobalSecondaryIndexUpdate { + s.Update = v + return s +} + +// Represents the properties of a global table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GlobalTable +type GlobalTable struct { + _ struct{} `type:"structure"` + + // The global table name. + GlobalTableName *string `min:"3" type:"string"` + + // The regions where the global table has replicas. + ReplicationGroup []*Replica `type:"list"` +} + +// String returns the string representation +func (s GlobalTable) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GlobalTable) GoString() string { + return s.String() +} + +// SetGlobalTableName sets the GlobalTableName field's value. +func (s *GlobalTable) SetGlobalTableName(v string) *GlobalTable { + s.GlobalTableName = &v + return s +} + +// SetReplicationGroup sets the ReplicationGroup field's value. +func (s *GlobalTable) SetReplicationGroup(v []*Replica) *GlobalTable { + s.ReplicationGroup = v + return s +} + +// Contains details about the global table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/GlobalTableDescription +type GlobalTableDescription struct { + _ struct{} `type:"structure"` + + // The creation time of the global table. + CreationDateTime *time.Time `type:"timestamp" timestampFormat:"unix"` + + // The unique identifier of the global table. + GlobalTableArn *string `type:"string"` + + // The global table name. + GlobalTableName *string `min:"3" type:"string"` + + // The current state of the global table: + // + // * CREATING - The global table is being created. + // + // * UPDATING - The global table is being updated. + // + // * DELETING - The global table is being deleted. + // + // * ACTIVE - The global table is ready for use. + GlobalTableStatus *string `type:"string" enum:"GlobalTableStatus"` + + // The regions where the global table has replicas. + ReplicationGroup []*ReplicaDescription `type:"list"` +} + +// String returns the string representation +func (s GlobalTableDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GlobalTableDescription) GoString() string { + return s.String() +} + +// SetCreationDateTime sets the CreationDateTime field's value. +func (s *GlobalTableDescription) SetCreationDateTime(v time.Time) *GlobalTableDescription { + s.CreationDateTime = &v + return s +} + +// SetGlobalTableArn sets the GlobalTableArn field's value. +func (s *GlobalTableDescription) SetGlobalTableArn(v string) *GlobalTableDescription { + s.GlobalTableArn = &v + return s +} + +// SetGlobalTableName sets the GlobalTableName field's value. +func (s *GlobalTableDescription) SetGlobalTableName(v string) *GlobalTableDescription { + s.GlobalTableName = &v + return s +} + +// SetGlobalTableStatus sets the GlobalTableStatus field's value. +func (s *GlobalTableDescription) SetGlobalTableStatus(v string) *GlobalTableDescription { + s.GlobalTableStatus = &v + return s +} + +// SetReplicationGroup sets the ReplicationGroup field's value. +func (s *GlobalTableDescription) SetReplicationGroup(v []*ReplicaDescription) *GlobalTableDescription { + s.ReplicationGroup = v + return s +} + +// Information about item collections, if any, that were affected by the operation. +// ItemCollectionMetrics is only returned if the request asked for it. If the +// table does not have any local secondary indexes, this information is not +// returned in the response. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ItemCollectionMetrics +type ItemCollectionMetrics struct { + _ struct{} `type:"structure"` + + // The partition key value of the item collection. This value is the same as + // the partition key value of the item. + ItemCollectionKey map[string]*AttributeValue `type:"map"` + + // An estimate of item collection size, in gigabytes. This value is a two-element + // array containing a lower bound and an upper bound for the estimate. The estimate + // includes the size of all the items in the table, plus the size of all attributes + // projected into all of the local secondary indexes on that table. Use this + // estimate to measure whether a local secondary index is approaching its size + // limit. + // + // The estimate is subject to change over time; therefore, do not rely on the + // precision or accuracy of the estimate. + SizeEstimateRangeGB []*float64 `type:"list"` +} + +// String returns the string representation +func (s ItemCollectionMetrics) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ItemCollectionMetrics) GoString() string { + return s.String() +} + +// SetItemCollectionKey sets the ItemCollectionKey field's value. +func (s *ItemCollectionMetrics) SetItemCollectionKey(v map[string]*AttributeValue) *ItemCollectionMetrics { + s.ItemCollectionKey = v + return s +} + +// SetSizeEstimateRangeGB sets the SizeEstimateRangeGB field's value. +func (s *ItemCollectionMetrics) SetSizeEstimateRangeGB(v []*float64) *ItemCollectionMetrics { + s.SizeEstimateRangeGB = v + return s +} + +// Represents a single element of a key schema. A key schema specifies the attributes +// that make up the primary key of a table, or the key attributes of an index. +// +// A KeySchemaElement represents exactly one attribute of the primary key. For +// example, a simple primary key would be represented by one KeySchemaElement +// (for the partition key). A composite primary key would require one KeySchemaElement +// for the partition key, and another KeySchemaElement for the sort key. +// +// A KeySchemaElement must be a scalar, top-level attribute (not a nested attribute). +// The data type must be one of String, Number, or Binary. The attribute cannot +// be nested within a List or a Map. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/KeySchemaElement +type KeySchemaElement struct { + _ struct{} `type:"structure"` + + // The name of a key attribute. + // + // AttributeName is a required field + AttributeName *string `min:"1" type:"string" required:"true"` + + // The role that this key attribute will assume: + // + // * HASH - partition key + // + // * RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + // + // KeyType is a required field + KeyType *string `type:"string" required:"true" enum:"KeyType"` +} + +// String returns the string representation +func (s KeySchemaElement) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s KeySchemaElement) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *KeySchemaElement) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "KeySchemaElement"} + if s.AttributeName == nil { + invalidParams.Add(request.NewErrParamRequired("AttributeName")) + } + if s.AttributeName != nil && len(*s.AttributeName) < 1 { + invalidParams.Add(request.NewErrParamMinLen("AttributeName", 1)) + } + if s.KeyType == nil { + invalidParams.Add(request.NewErrParamRequired("KeyType")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributeName sets the AttributeName field's value. +func (s *KeySchemaElement) SetAttributeName(v string) *KeySchemaElement { + s.AttributeName = &v + return s +} + +// SetKeyType sets the KeyType field's value. +func (s *KeySchemaElement) SetKeyType(v string) *KeySchemaElement { + s.KeyType = &v + return s +} + +// Represents a set of primary keys and, for each key, the attributes to retrieve +// from the table. +// +// For each primary key, you must provide all of the key attributes. For example, +// with a simple primary key, you only need to provide the partition key. For +// a composite primary key, you must provide both the partition key and the +// sort key. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/KeysAndAttributes +type KeysAndAttributes struct { + _ struct{} `type:"structure"` + + // This is a legacy parameter. Use ProjectionExpression instead. For more information, + // see Legacy Conditional Parameters (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.html) + // in the Amazon DynamoDB Developer Guide. + AttributesToGet []*string `min:"1" type:"list"` + + // The consistency of a read operation. If set to true, then a strongly consistent + // read is used; otherwise, an eventually consistent read is used. + ConsistentRead *bool `type:"boolean"` + + // One or more substitution tokens for attribute names in an expression. The + // following are some use cases for using ExpressionAttributeNames: + // + // * To access an attribute whose name conflicts with a DynamoDB reserved + // word. + // + // * To create a placeholder for repeating occurrences of an attribute name + // in an expression. + // + // * To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // * Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could specify + // the following for ExpressionAttributeNames: + // + // * {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // * #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeNames map[string]*string `type:"map"` + + // The primary key attribute values that define the items and the attributes + // associated with the items. + // + // Keys is a required field + Keys []map[string]*AttributeValue `min:"1" type:"list" required:"true"` + + // A string that identifies one or more attributes to retrieve from the table. + // These attributes can include scalars, sets, or elements of a JSON document. + // The attributes in the ProjectionExpression must be separated by commas. + // + // If no attribute names are specified, then all attributes will be returned. + // If any of the requested attributes are not found, they will not appear in + // the result. + // + // For more information, see Accessing Item Attributes (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ProjectionExpression *string `type:"string"` +} + +// String returns the string representation +func (s KeysAndAttributes) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s KeysAndAttributes) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *KeysAndAttributes) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "KeysAndAttributes"} + if s.AttributesToGet != nil && len(s.AttributesToGet) < 1 { + invalidParams.Add(request.NewErrParamMinLen("AttributesToGet", 1)) + } + if s.Keys == nil { + invalidParams.Add(request.NewErrParamRequired("Keys")) + } + if s.Keys != nil && len(s.Keys) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Keys", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributesToGet sets the AttributesToGet field's value. +func (s *KeysAndAttributes) SetAttributesToGet(v []*string) *KeysAndAttributes { + s.AttributesToGet = v + return s +} + +// SetConsistentRead sets the ConsistentRead field's value. +func (s *KeysAndAttributes) SetConsistentRead(v bool) *KeysAndAttributes { + s.ConsistentRead = &v + return s +} + +// SetExpressionAttributeNames sets the ExpressionAttributeNames field's value. +func (s *KeysAndAttributes) SetExpressionAttributeNames(v map[string]*string) *KeysAndAttributes { + s.ExpressionAttributeNames = v + return s +} + +// SetKeys sets the Keys field's value. +func (s *KeysAndAttributes) SetKeys(v []map[string]*AttributeValue) *KeysAndAttributes { + s.Keys = v + return s +} + +// SetProjectionExpression sets the ProjectionExpression field's value. +func (s *KeysAndAttributes) SetProjectionExpression(v string) *KeysAndAttributes { + s.ProjectionExpression = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListBackupsInput +type ListBackupsInput struct { + _ struct{} `type:"structure"` + + // LastEvaluatedBackupARN returned by the previous ListBackups call. + ExclusiveStartBackupArn *string `min:"37" type:"string"` + + // Maximum number of backups to return at once. + Limit *int64 `min:"1" type:"integer"` + + // The backups from the table specified by TableName are listed. + TableName *string `min:"3" type:"string"` + + // Only backups created after this time are listed. TimeRangeLowerBound is inclusive. + TimeRangeLowerBound *time.Time `type:"timestamp" timestampFormat:"unix"` + + // Only backups created before this time are listed. TimeRangeUpperBound is + // exclusive. + TimeRangeUpperBound *time.Time `type:"timestamp" timestampFormat:"unix"` +} + +// String returns the string representation +func (s ListBackupsInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListBackupsInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *ListBackupsInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ListBackupsInput"} + if s.ExclusiveStartBackupArn != nil && len(*s.ExclusiveStartBackupArn) < 37 { + invalidParams.Add(request.NewErrParamMinLen("ExclusiveStartBackupArn", 37)) + } + if s.Limit != nil && *s.Limit < 1 { + invalidParams.Add(request.NewErrParamMinValue("Limit", 1)) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetExclusiveStartBackupArn sets the ExclusiveStartBackupArn field's value. +func (s *ListBackupsInput) SetExclusiveStartBackupArn(v string) *ListBackupsInput { + s.ExclusiveStartBackupArn = &v + return s +} + +// SetLimit sets the Limit field's value. +func (s *ListBackupsInput) SetLimit(v int64) *ListBackupsInput { + s.Limit = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *ListBackupsInput) SetTableName(v string) *ListBackupsInput { + s.TableName = &v + return s +} + +// SetTimeRangeLowerBound sets the TimeRangeLowerBound field's value. +func (s *ListBackupsInput) SetTimeRangeLowerBound(v time.Time) *ListBackupsInput { + s.TimeRangeLowerBound = &v + return s +} + +// SetTimeRangeUpperBound sets the TimeRangeUpperBound field's value. +func (s *ListBackupsInput) SetTimeRangeUpperBound(v time.Time) *ListBackupsInput { + s.TimeRangeUpperBound = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListBackupsOutput +type ListBackupsOutput struct { + _ struct{} `type:"structure"` + + // List of BackupSummary objects. + BackupSummaries []*BackupSummary `type:"list"` + + // Last evaluated BackupARN. + LastEvaluatedBackupArn *string `min:"37" type:"string"` +} + +// String returns the string representation +func (s ListBackupsOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListBackupsOutput) GoString() string { + return s.String() +} + +// SetBackupSummaries sets the BackupSummaries field's value. +func (s *ListBackupsOutput) SetBackupSummaries(v []*BackupSummary) *ListBackupsOutput { + s.BackupSummaries = v + return s +} + +// SetLastEvaluatedBackupArn sets the LastEvaluatedBackupArn field's value. +func (s *ListBackupsOutput) SetLastEvaluatedBackupArn(v string) *ListBackupsOutput { + s.LastEvaluatedBackupArn = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListGlobalTablesInput +type ListGlobalTablesInput struct { + _ struct{} `type:"structure"` + + // The first global table name that this operation will evaluate. + ExclusiveStartGlobalTableName *string `min:"3" type:"string"` + + // The maximum number of table names to return. + Limit *int64 `min:"1" type:"integer"` + + // Lists the global tables in a specific region. + RegionName *string `type:"string"` +} + +// String returns the string representation +func (s ListGlobalTablesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListGlobalTablesInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *ListGlobalTablesInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ListGlobalTablesInput"} + if s.ExclusiveStartGlobalTableName != nil && len(*s.ExclusiveStartGlobalTableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("ExclusiveStartGlobalTableName", 3)) + } + if s.Limit != nil && *s.Limit < 1 { + invalidParams.Add(request.NewErrParamMinValue("Limit", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetExclusiveStartGlobalTableName sets the ExclusiveStartGlobalTableName field's value. +func (s *ListGlobalTablesInput) SetExclusiveStartGlobalTableName(v string) *ListGlobalTablesInput { + s.ExclusiveStartGlobalTableName = &v + return s +} + +// SetLimit sets the Limit field's value. +func (s *ListGlobalTablesInput) SetLimit(v int64) *ListGlobalTablesInput { + s.Limit = &v + return s +} + +// SetRegionName sets the RegionName field's value. +func (s *ListGlobalTablesInput) SetRegionName(v string) *ListGlobalTablesInput { + s.RegionName = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListGlobalTablesOutput +type ListGlobalTablesOutput struct { + _ struct{} `type:"structure"` + + // List of global table names. + GlobalTables []*GlobalTable `type:"list"` + + // Last evaluated global table name. + LastEvaluatedGlobalTableName *string `min:"3" type:"string"` +} + +// String returns the string representation +func (s ListGlobalTablesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListGlobalTablesOutput) GoString() string { + return s.String() +} + +// SetGlobalTables sets the GlobalTables field's value. +func (s *ListGlobalTablesOutput) SetGlobalTables(v []*GlobalTable) *ListGlobalTablesOutput { + s.GlobalTables = v + return s +} + +// SetLastEvaluatedGlobalTableName sets the LastEvaluatedGlobalTableName field's value. +func (s *ListGlobalTablesOutput) SetLastEvaluatedGlobalTableName(v string) *ListGlobalTablesOutput { + s.LastEvaluatedGlobalTableName = &v + return s +} + +// Represents the input of a ListTables operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTablesInput +type ListTablesInput struct { + _ struct{} `type:"structure"` + + // The first table name that this operation will evaluate. Use the value that + // was returned for LastEvaluatedTableName in a previous operation, so that + // you can obtain the next page of results. + ExclusiveStartTableName *string `min:"3" type:"string"` + + // A maximum number of table names to return. If this parameter is not specified, + // the limit is 100. + Limit *int64 `min:"1" type:"integer"` +} + +// String returns the string representation +func (s ListTablesInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListTablesInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *ListTablesInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ListTablesInput"} + if s.ExclusiveStartTableName != nil && len(*s.ExclusiveStartTableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("ExclusiveStartTableName", 3)) + } + if s.Limit != nil && *s.Limit < 1 { + invalidParams.Add(request.NewErrParamMinValue("Limit", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetExclusiveStartTableName sets the ExclusiveStartTableName field's value. +func (s *ListTablesInput) SetExclusiveStartTableName(v string) *ListTablesInput { + s.ExclusiveStartTableName = &v + return s +} + +// SetLimit sets the Limit field's value. +func (s *ListTablesInput) SetLimit(v int64) *ListTablesInput { + s.Limit = &v + return s +} + +// Represents the output of a ListTables operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTablesOutput +type ListTablesOutput struct { + _ struct{} `type:"structure"` + + // The name of the last table in the current page of results. Use this value + // as the ExclusiveStartTableName in a new request to obtain the next page of + // results, until all the table names are returned. + // + // If you do not receive a LastEvaluatedTableName value in the response, this + // means that there are no more table names to be retrieved. + LastEvaluatedTableName *string `min:"3" type:"string"` + + // The names of the tables associated with the current account at the current + // endpoint. The maximum size of this array is 100. + // + // If LastEvaluatedTableName also appears in the output, you can use this value + // as the ExclusiveStartTableName parameter in a subsequent ListTables request + // and obtain the next page of results. + TableNames []*string `type:"list"` +} + +// String returns the string representation +func (s ListTablesOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListTablesOutput) GoString() string { + return s.String() +} + +// SetLastEvaluatedTableName sets the LastEvaluatedTableName field's value. +func (s *ListTablesOutput) SetLastEvaluatedTableName(v string) *ListTablesOutput { + s.LastEvaluatedTableName = &v + return s +} + +// SetTableNames sets the TableNames field's value. +func (s *ListTablesOutput) SetTableNames(v []*string) *ListTablesOutput { + s.TableNames = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTagsOfResourceInput +type ListTagsOfResourceInput struct { + _ struct{} `type:"structure"` + + // An optional string that, if supplied, must be copied from the output of a + // previous call to ListTagOfResource. When provided in this manner, this API + // fetches the next page of results. + NextToken *string `type:"string"` + + // The Amazon DynamoDB resource with tags to be listed. This value is an Amazon + // Resource Name (ARN). + // + // ResourceArn is a required field + ResourceArn *string `min:"1" type:"string" required:"true"` +} + +// String returns the string representation +func (s ListTagsOfResourceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListTagsOfResourceInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *ListTagsOfResourceInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ListTagsOfResourceInput"} + if s.ResourceArn == nil { + invalidParams.Add(request.NewErrParamRequired("ResourceArn")) + } + if s.ResourceArn != nil && len(*s.ResourceArn) < 1 { + invalidParams.Add(request.NewErrParamMinLen("ResourceArn", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetNextToken sets the NextToken field's value. +func (s *ListTagsOfResourceInput) SetNextToken(v string) *ListTagsOfResourceInput { + s.NextToken = &v + return s +} + +// SetResourceArn sets the ResourceArn field's value. +func (s *ListTagsOfResourceInput) SetResourceArn(v string) *ListTagsOfResourceInput { + s.ResourceArn = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ListTagsOfResourceOutput +type ListTagsOfResourceOutput struct { + _ struct{} `type:"structure"` + + // If this value is returned, there are additional results to be displayed. + // To retrieve them, call ListTagsOfResource again, with NextToken set to this + // value. + NextToken *string `type:"string"` + + // The tags currently associated with the Amazon DynamoDB resource. + Tags []*Tag `type:"list"` +} + +// String returns the string representation +func (s ListTagsOfResourceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ListTagsOfResourceOutput) GoString() string { + return s.String() +} + +// SetNextToken sets the NextToken field's value. +func (s *ListTagsOfResourceOutput) SetNextToken(v string) *ListTagsOfResourceOutput { + s.NextToken = &v + return s +} + +// SetTags sets the Tags field's value. +func (s *ListTagsOfResourceOutput) SetTags(v []*Tag) *ListTagsOfResourceOutput { + s.Tags = v + return s +} + +// Represents the properties of a local secondary index. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/LocalSecondaryIndex +type LocalSecondaryIndex struct { + _ struct{} `type:"structure"` + + // The name of the local secondary index. The name must be unique among all + // other indexes on this table. + // + // IndexName is a required field + IndexName *string `min:"3" type:"string" required:"true"` + + // The complete key schema for the local secondary index, consisting of one + // or more pairs of attribute names and key types: + // + // * HASH - partition key + // + // * RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + // + // KeySchema is a required field + KeySchema []*KeySchemaElement `min:"1" type:"list" required:"true"` + + // Represents attributes that are copied (projected) from the table into the + // local secondary index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. + // + // Projection is a required field + Projection *Projection `type:"structure" required:"true"` +} + +// String returns the string representation +func (s LocalSecondaryIndex) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s LocalSecondaryIndex) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *LocalSecondaryIndex) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "LocalSecondaryIndex"} + if s.IndexName == nil { + invalidParams.Add(request.NewErrParamRequired("IndexName")) + } + if s.IndexName != nil && len(*s.IndexName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("IndexName", 3)) + } + if s.KeySchema == nil { + invalidParams.Add(request.NewErrParamRequired("KeySchema")) + } + if s.KeySchema != nil && len(s.KeySchema) < 1 { + invalidParams.Add(request.NewErrParamMinLen("KeySchema", 1)) + } + if s.Projection == nil { + invalidParams.Add(request.NewErrParamRequired("Projection")) + } + if s.KeySchema != nil { + for i, v := range s.KeySchema { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "KeySchema", i), err.(request.ErrInvalidParams)) + } + } + } + if s.Projection != nil { + if err := s.Projection.Validate(); err != nil { + invalidParams.AddNested("Projection", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetIndexName sets the IndexName field's value. +func (s *LocalSecondaryIndex) SetIndexName(v string) *LocalSecondaryIndex { + s.IndexName = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *LocalSecondaryIndex) SetKeySchema(v []*KeySchemaElement) *LocalSecondaryIndex { + s.KeySchema = v + return s +} + +// SetProjection sets the Projection field's value. +func (s *LocalSecondaryIndex) SetProjection(v *Projection) *LocalSecondaryIndex { + s.Projection = v + return s +} + +// Represents the properties of a local secondary index. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/LocalSecondaryIndexDescription +type LocalSecondaryIndexDescription struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN) that uniquely identifies the index. + IndexArn *string `type:"string"` + + // Represents the name of the local secondary index. + IndexName *string `min:"3" type:"string"` + + // The total size of the specified index, in bytes. DynamoDB updates this value + // approximately every six hours. Recent changes might not be reflected in this + // value. + IndexSizeBytes *int64 `type:"long"` + + // The number of items in the specified index. DynamoDB updates this value approximately + // every six hours. Recent changes might not be reflected in this value. + ItemCount *int64 `type:"long"` + + // The complete key schema for the local secondary index, consisting of one + // or more pairs of attribute names and key types: + // + // * HASH - partition key + // + // * RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + KeySchema []*KeySchemaElement `min:"1" type:"list"` + + // Represents attributes that are copied (projected) from the table into the + // global secondary index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. + Projection *Projection `type:"structure"` +} + +// String returns the string representation +func (s LocalSecondaryIndexDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s LocalSecondaryIndexDescription) GoString() string { + return s.String() +} + +// SetIndexArn sets the IndexArn field's value. +func (s *LocalSecondaryIndexDescription) SetIndexArn(v string) *LocalSecondaryIndexDescription { + s.IndexArn = &v + return s +} + +// SetIndexName sets the IndexName field's value. +func (s *LocalSecondaryIndexDescription) SetIndexName(v string) *LocalSecondaryIndexDescription { + s.IndexName = &v + return s +} + +// SetIndexSizeBytes sets the IndexSizeBytes field's value. +func (s *LocalSecondaryIndexDescription) SetIndexSizeBytes(v int64) *LocalSecondaryIndexDescription { + s.IndexSizeBytes = &v + return s +} + +// SetItemCount sets the ItemCount field's value. +func (s *LocalSecondaryIndexDescription) SetItemCount(v int64) *LocalSecondaryIndexDescription { + s.ItemCount = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *LocalSecondaryIndexDescription) SetKeySchema(v []*KeySchemaElement) *LocalSecondaryIndexDescription { + s.KeySchema = v + return s +} + +// SetProjection sets the Projection field's value. +func (s *LocalSecondaryIndexDescription) SetProjection(v *Projection) *LocalSecondaryIndexDescription { + s.Projection = v + return s +} + +// Represents the properties of a local secondary index for the table when the +// backup was created. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/LocalSecondaryIndexInfo +type LocalSecondaryIndexInfo struct { + _ struct{} `type:"structure"` + + // Represents the name of the local secondary index. + IndexName *string `min:"3" type:"string"` + + // The complete key schema for a local secondary index, which consists of one + // or more pairs of attribute names and key types: + // + // * HASH - partition key + // + // * RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + KeySchema []*KeySchemaElement `min:"1" type:"list"` + + // Represents attributes that are copied (projected) from the table into the + // global secondary index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. + Projection *Projection `type:"structure"` +} + +// String returns the string representation +func (s LocalSecondaryIndexInfo) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s LocalSecondaryIndexInfo) GoString() string { + return s.String() +} + +// SetIndexName sets the IndexName field's value. +func (s *LocalSecondaryIndexInfo) SetIndexName(v string) *LocalSecondaryIndexInfo { + s.IndexName = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *LocalSecondaryIndexInfo) SetKeySchema(v []*KeySchemaElement) *LocalSecondaryIndexInfo { + s.KeySchema = v + return s +} + +// SetProjection sets the Projection field's value. +func (s *LocalSecondaryIndexInfo) SetProjection(v *Projection) *LocalSecondaryIndexInfo { + s.Projection = v + return s +} + +// Represents attributes that are copied (projected) from the table into an +// index. These are in addition to the primary key attributes and index key +// attributes, which are automatically projected. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Projection +type Projection struct { + _ struct{} `type:"structure"` + + // Represents the non-key attribute names which will be projected into the index. + // + // For local secondary indexes, the total count of NonKeyAttributes summed across + // all of the local secondary indexes, must not exceed 20. If you project the + // same attribute into two different indexes, this counts as two distinct attributes + // when determining the total. + NonKeyAttributes []*string `min:"1" type:"list"` + + // The set of attributes that are projected into the index: + // + // * KEYS_ONLY - Only the index and primary keys are projected into the index. + // + // * INCLUDE - Only the specified table attributes are projected into the + // index. The list of projected attributes are in NonKeyAttributes. + // + // * ALL - All of the table attributes are projected into the index. + ProjectionType *string `type:"string" enum:"ProjectionType"` +} + +// String returns the string representation +func (s Projection) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Projection) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *Projection) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "Projection"} + if s.NonKeyAttributes != nil && len(s.NonKeyAttributes) < 1 { + invalidParams.Add(request.NewErrParamMinLen("NonKeyAttributes", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetNonKeyAttributes sets the NonKeyAttributes field's value. +func (s *Projection) SetNonKeyAttributes(v []*string) *Projection { + s.NonKeyAttributes = v + return s +} + +// SetProjectionType sets the ProjectionType field's value. +func (s *Projection) SetProjectionType(v string) *Projection { + s.ProjectionType = &v + return s +} + +// Represents the provisioned throughput settings for a specified table or index. +// The settings can be modified using the UpdateTable operation. +// +// For current minimum and maximum provisioned throughput values, see Limits +// (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) +// in the Amazon DynamoDB Developer Guide. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ProvisionedThroughput +type ProvisionedThroughput struct { + _ struct{} `type:"structure"` + + // The maximum number of strongly consistent reads consumed per second before + // DynamoDB returns a ThrottlingException. For more information, see Specifying + // Read and Write Requirements (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html#ProvisionedThroughput) + // in the Amazon DynamoDB Developer Guide. + // + // ReadCapacityUnits is a required field + ReadCapacityUnits *int64 `min:"1" type:"long" required:"true"` + + // The maximum number of writes consumed per second before DynamoDB returns + // a ThrottlingException. For more information, see Specifying Read and Write + // Requirements (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html#ProvisionedThroughput) + // in the Amazon DynamoDB Developer Guide. + // + // WriteCapacityUnits is a required field + WriteCapacityUnits *int64 `min:"1" type:"long" required:"true"` +} + +// String returns the string representation +func (s ProvisionedThroughput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ProvisionedThroughput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *ProvisionedThroughput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ProvisionedThroughput"} + if s.ReadCapacityUnits == nil { + invalidParams.Add(request.NewErrParamRequired("ReadCapacityUnits")) + } + if s.ReadCapacityUnits != nil && *s.ReadCapacityUnits < 1 { + invalidParams.Add(request.NewErrParamMinValue("ReadCapacityUnits", 1)) + } + if s.WriteCapacityUnits == nil { + invalidParams.Add(request.NewErrParamRequired("WriteCapacityUnits")) + } + if s.WriteCapacityUnits != nil && *s.WriteCapacityUnits < 1 { + invalidParams.Add(request.NewErrParamMinValue("WriteCapacityUnits", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetReadCapacityUnits sets the ReadCapacityUnits field's value. +func (s *ProvisionedThroughput) SetReadCapacityUnits(v int64) *ProvisionedThroughput { + s.ReadCapacityUnits = &v + return s +} + +// SetWriteCapacityUnits sets the WriteCapacityUnits field's value. +func (s *ProvisionedThroughput) SetWriteCapacityUnits(v int64) *ProvisionedThroughput { + s.WriteCapacityUnits = &v + return s +} + +// Represents the provisioned throughput settings for the table, consisting +// of read and write capacity units, along with data about increases and decreases. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ProvisionedThroughputDescription +type ProvisionedThroughputDescription struct { + _ struct{} `type:"structure"` + + // The date and time of the last provisioned throughput decrease for this table. + LastDecreaseDateTime *time.Time `type:"timestamp" timestampFormat:"unix"` + + // The date and time of the last provisioned throughput increase for this table. + LastIncreaseDateTime *time.Time `type:"timestamp" timestampFormat:"unix"` + + // The number of provisioned throughput decreases for this table during this + // UTC calendar day. For current maximums on provisioned throughput decreases, + // see Limits (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) + // in the Amazon DynamoDB Developer Guide. + NumberOfDecreasesToday *int64 `min:"1" type:"long"` + + // The maximum number of strongly consistent reads consumed per second before + // DynamoDB returns a ThrottlingException. Eventually consistent reads require + // less effort than strongly consistent reads, so a setting of 50 ReadCapacityUnits + // per second provides 100 eventually consistent ReadCapacityUnits per second. + ReadCapacityUnits *int64 `min:"1" type:"long"` + + // The maximum number of writes consumed per second before DynamoDB returns + // a ThrottlingException. + WriteCapacityUnits *int64 `min:"1" type:"long"` +} + +// String returns the string representation +func (s ProvisionedThroughputDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ProvisionedThroughputDescription) GoString() string { + return s.String() +} + +// SetLastDecreaseDateTime sets the LastDecreaseDateTime field's value. +func (s *ProvisionedThroughputDescription) SetLastDecreaseDateTime(v time.Time) *ProvisionedThroughputDescription { + s.LastDecreaseDateTime = &v + return s +} + +// SetLastIncreaseDateTime sets the LastIncreaseDateTime field's value. +func (s *ProvisionedThroughputDescription) SetLastIncreaseDateTime(v time.Time) *ProvisionedThroughputDescription { + s.LastIncreaseDateTime = &v + return s +} + +// SetNumberOfDecreasesToday sets the NumberOfDecreasesToday field's value. +func (s *ProvisionedThroughputDescription) SetNumberOfDecreasesToday(v int64) *ProvisionedThroughputDescription { + s.NumberOfDecreasesToday = &v + return s +} + +// SetReadCapacityUnits sets the ReadCapacityUnits field's value. +func (s *ProvisionedThroughputDescription) SetReadCapacityUnits(v int64) *ProvisionedThroughputDescription { + s.ReadCapacityUnits = &v + return s +} + +// SetWriteCapacityUnits sets the WriteCapacityUnits field's value. +func (s *ProvisionedThroughputDescription) SetWriteCapacityUnits(v int64) *ProvisionedThroughputDescription { + s.WriteCapacityUnits = &v + return s +} + +// Represents the input of a PutItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/PutItemInput +type PutItemInput struct { + _ struct{} `type:"structure"` + + // A condition that must be satisfied in order for a conditional PutItem operation + // to succeed. + // + // An expression can contain any of the following: + // + // * Functions: attribute_exists | attribute_not_exists | attribute_type + // | contains | begins_with | size + // + // These function names are case-sensitive. + // + // * Comparison operators: = | <> | < | > | <= | >= | BETWEEN | IN + // + // * Logical operators: AND | OR | NOT + // + // For more information on condition expressions, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ConditionExpression *string `type:"string"` + + // This is a legacy parameter. Use ConditionExpression instead. For more information, + // see ConditionalOperator (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ConditionalOperator.html) + // in the Amazon DynamoDB Developer Guide. + ConditionalOperator *string `type:"string" enum:"ConditionalOperator"` + + // This is a legacy parameter. Use ConditionExpression instead. For more information, + // see Expected (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.Expected.html) + // in the Amazon DynamoDB Developer Guide. + Expected map[string]*ExpectedAttributeValue `type:"map"` + + // One or more substitution tokens for attribute names in an expression. The + // following are some use cases for using ExpressionAttributeNames: + // + // * To access an attribute whose name conflicts with a DynamoDB reserved + // word. + // + // * To create a placeholder for repeating occurrences of an attribute name + // in an expression. + // + // * To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // * Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could specify + // the following for ExpressionAttributeNames: + // + // * {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // * #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeNames map[string]*string `type:"map"` + + // One or more values that can be substituted in an expression. + // + // Use the : (colon) character in an expression to dereference an attribute + // value. For example, suppose that you wanted to check whether the value of + // the ProductStatus attribute was one of the following: + // + // Available | Backordered | Discontinued + // + // You would first need to specify ExpressionAttributeValues as follows: + // + // { ":avail":{"S":"Available"}, ":back":{"S":"Backordered"}, ":disc":{"S":"Discontinued"} + // } + // + // You could then use these values in an expression, such as this: + // + // ProductStatus IN (:avail, :back, :disc) + // + // For more information on expression attribute values, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeValues map[string]*AttributeValue `type:"map"` + + // A map of attribute name/value pairs, one for each attribute. Only the primary + // key attributes are required; you can optionally provide other attribute name-value + // pairs for the item. + // + // You must provide all of the attributes for the primary key. For example, + // with a simple primary key, you only need to provide a value for the partition + // key. For a composite primary key, you must provide both values for both the + // partition key and the sort key. + // + // If you specify any attributes that are part of an index key, then the data + // types for those attributes must match those of the schema in the table's + // attribute definition. + // + // For more information about primary keys, see Primary Key (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataModel.html#DataModelPrimaryKey) + // in the Amazon DynamoDB Developer Guide. + // + // Each element in the Item map is an AttributeValue object. + // + // Item is a required field + Item map[string]*AttributeValue `type:"map" required:"true"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` + + // Determines whether item collection metrics are returned. If set to SIZE, + // the response includes statistics about item collections, if any, that were + // modified during the operation are returned in the response. If set to NONE + // (the default), no statistics are returned. + ReturnItemCollectionMetrics *string `type:"string" enum:"ReturnItemCollectionMetrics"` + + // Use ReturnValues if you want to get the item attributes as they appeared + // before they were updated with the PutItem request. For PutItem, the valid + // values are: + // + // * NONE - If ReturnValues is not specified, or if its value is NONE, then + // nothing is returned. (This setting is the default for ReturnValues.) + // + // * ALL_OLD - If PutItem overwrote an attribute name-value pair, then the + // content of the old item is returned. + // + // The ReturnValues parameter is used by several DynamoDB operations; however, + // PutItem does not recognize any values other than NONE or ALL_OLD. + ReturnValues *string `type:"string" enum:"ReturnValue"` + + // The name of the table to contain the item. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s PutItemInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PutItemInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *PutItemInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "PutItemInput"} + if s.Item == nil { + invalidParams.Add(request.NewErrParamRequired("Item")) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetConditionExpression sets the ConditionExpression field's value. +func (s *PutItemInput) SetConditionExpression(v string) *PutItemInput { + s.ConditionExpression = &v + return s +} + +// SetConditionalOperator sets the ConditionalOperator field's value. +func (s *PutItemInput) SetConditionalOperator(v string) *PutItemInput { + s.ConditionalOperator = &v + return s +} + +// SetExpected sets the Expected field's value. +func (s *PutItemInput) SetExpected(v map[string]*ExpectedAttributeValue) *PutItemInput { + s.Expected = v + return s +} + +// SetExpressionAttributeNames sets the ExpressionAttributeNames field's value. +func (s *PutItemInput) SetExpressionAttributeNames(v map[string]*string) *PutItemInput { + s.ExpressionAttributeNames = v + return s +} + +// SetExpressionAttributeValues sets the ExpressionAttributeValues field's value. +func (s *PutItemInput) SetExpressionAttributeValues(v map[string]*AttributeValue) *PutItemInput { + s.ExpressionAttributeValues = v + return s +} + +// SetItem sets the Item field's value. +func (s *PutItemInput) SetItem(v map[string]*AttributeValue) *PutItemInput { + s.Item = v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *PutItemInput) SetReturnConsumedCapacity(v string) *PutItemInput { + s.ReturnConsumedCapacity = &v + return s +} + +// SetReturnItemCollectionMetrics sets the ReturnItemCollectionMetrics field's value. +func (s *PutItemInput) SetReturnItemCollectionMetrics(v string) *PutItemInput { + s.ReturnItemCollectionMetrics = &v + return s +} + +// SetReturnValues sets the ReturnValues field's value. +func (s *PutItemInput) SetReturnValues(v string) *PutItemInput { + s.ReturnValues = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *PutItemInput) SetTableName(v string) *PutItemInput { + s.TableName = &v + return s +} + +// Represents the output of a PutItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/PutItemOutput +type PutItemOutput struct { + _ struct{} `type:"structure"` + + // The attribute values as they appeared before the PutItem operation, but only + // if ReturnValues is specified as ALL_OLD in the request. Each element consists + // of an attribute name and an attribute value. + Attributes map[string]*AttributeValue `type:"map"` + + // The capacity units consumed by the PutItem operation. The data returned includes + // the total provisioned throughput consumed, along with statistics for the + // table and any indexes involved in the operation. ConsumedCapacity is only + // returned if the ReturnConsumedCapacity parameter was specified. For more + // information, see Provisioned Throughput (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) + // in the Amazon DynamoDB Developer Guide. + ConsumedCapacity *ConsumedCapacity `type:"structure"` + + // Information about item collections, if any, that were affected by the PutItem + // operation. ItemCollectionMetrics is only returned if the ReturnItemCollectionMetrics + // parameter was specified. If the table does not have any local secondary indexes, + // this information is not returned in the response. + // + // Each ItemCollectionMetrics element consists of: + // + // * ItemCollectionKey - The partition key value of the item collection. + // This is the same as the partition key value of the item itself. + // + // * SizeEstimateRangeGB - An estimate of item collection size, in gigabytes. + // This value is a two-element array containing a lower bound and an upper + // bound for the estimate. The estimate includes the size of all the items + // in the table, plus the size of all attributes projected into all of the + // local secondary indexes on that table. Use this estimate to measure whether + // a local secondary index is approaching its size limit. + // + // The estimate is subject to change over time; therefore, do not rely on the + // precision or accuracy of the estimate. + ItemCollectionMetrics *ItemCollectionMetrics `type:"structure"` +} + +// String returns the string representation +func (s PutItemOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PutItemOutput) GoString() string { + return s.String() +} + +// SetAttributes sets the Attributes field's value. +func (s *PutItemOutput) SetAttributes(v map[string]*AttributeValue) *PutItemOutput { + s.Attributes = v + return s +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *PutItemOutput) SetConsumedCapacity(v *ConsumedCapacity) *PutItemOutput { + s.ConsumedCapacity = v + return s +} + +// SetItemCollectionMetrics sets the ItemCollectionMetrics field's value. +func (s *PutItemOutput) SetItemCollectionMetrics(v *ItemCollectionMetrics) *PutItemOutput { + s.ItemCollectionMetrics = v + return s +} + +// Represents a request to perform a PutItem operation on an item. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/PutRequest +type PutRequest struct { + _ struct{} `type:"structure"` + + // A map of attribute name to attribute values, representing the primary key + // of an item to be processed by PutItem. All of the table's primary key attributes + // must be specified, and their data types must match those of the table's key + // schema. If any attributes are present in the item which are part of an index + // key schema for the table, their types must match the index key schema. + // + // Item is a required field + Item map[string]*AttributeValue `type:"map" required:"true"` +} + +// String returns the string representation +func (s PutRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s PutRequest) GoString() string { + return s.String() +} + +// SetItem sets the Item field's value. +func (s *PutRequest) SetItem(v map[string]*AttributeValue) *PutRequest { + s.Item = v + return s +} + +// Represents the input of a Query operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/QueryInput +type QueryInput struct { + _ struct{} `type:"structure"` + + // This is a legacy parameter. Use ProjectionExpression instead. For more information, + // see AttributesToGet (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributesToGet.html) + // in the Amazon DynamoDB Developer Guide. + AttributesToGet []*string `min:"1" type:"list"` + + // This is a legacy parameter. Use FilterExpression instead. For more information, + // see ConditionalOperator (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ConditionalOperator.html) + // in the Amazon DynamoDB Developer Guide. + ConditionalOperator *string `type:"string" enum:"ConditionalOperator"` + + // Determines the read consistency model: If set to true, then the operation + // uses strongly consistent reads; otherwise, the operation uses eventually + // consistent reads. + // + // Strongly consistent reads are not supported on global secondary indexes. + // If you query a global secondary index with ConsistentRead set to true, you + // will receive a ValidationException. + ConsistentRead *bool `type:"boolean"` + + // The primary key of the first item that this operation will evaluate. Use + // the value that was returned for LastEvaluatedKey in the previous operation. + // + // The data type for ExclusiveStartKey must be String, Number or Binary. No + // set data types are allowed. + ExclusiveStartKey map[string]*AttributeValue `type:"map"` + + // One or more substitution tokens for attribute names in an expression. The + // following are some use cases for using ExpressionAttributeNames: + // + // * To access an attribute whose name conflicts with a DynamoDB reserved + // word. + // + // * To create a placeholder for repeating occurrences of an attribute name + // in an expression. + // + // * To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // * Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could specify + // the following for ExpressionAttributeNames: + // + // * {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // * #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeNames map[string]*string `type:"map"` + + // One or more values that can be substituted in an expression. + // + // Use the : (colon) character in an expression to dereference an attribute + // value. For example, suppose that you wanted to check whether the value of + // the ProductStatus attribute was one of the following: + // + // Available | Backordered | Discontinued + // + // You would first need to specify ExpressionAttributeValues as follows: + // + // { ":avail":{"S":"Available"}, ":back":{"S":"Backordered"}, ":disc":{"S":"Discontinued"} + // } + // + // You could then use these values in an expression, such as this: + // + // ProductStatus IN (:avail, :back, :disc) + // + // For more information on expression attribute values, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeValues map[string]*AttributeValue `type:"map"` + + // A string that contains conditions that DynamoDB applies after the Query operation, + // but before the data is returned to you. Items that do not satisfy the FilterExpression + // criteria are not returned. + // + // A FilterExpression does not allow key attributes. You cannot define a filter + // expression based on a partition key or a sort key. + // + // A FilterExpression is applied after the items have already been read; the + // process of filtering does not consume any additional read capacity units. + // + // For more information, see Filter Expressions (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html#FilteringResults) + // in the Amazon DynamoDB Developer Guide. + FilterExpression *string `type:"string"` + + // The name of an index to query. This index can be any local secondary index + // or global secondary index on the table. Note that if you use the IndexName + // parameter, you must also provide TableName. + IndexName *string `min:"3" type:"string"` + + // The condition that specifies the key value(s) for items to be retrieved by + // the Query action. + // + // The condition must perform an equality test on a single partition key value. + // The condition can also perform one of several comparison tests on a single + // sort key value. Query can use KeyConditionExpression to retrieve one item + // with a given partition key value and sort key value, or several items that + // have the same partition key value but different sort key values. + // + // The partition key equality test is required, and must be specified in the + // following format: + // + // partitionKeyName=:partitionkeyval + // + // If you also want to provide a condition for the sort key, it must be combined + // using AND with the condition for the sort key. Following is an example, using + // the = comparison operator for the sort key: + // + // partitionKeyName=:partitionkeyvalANDsortKeyName=:sortkeyval + // + // Valid comparisons for the sort key condition are as follows: + // + // * sortKeyName=:sortkeyval - true if the sort key value is equal to :sortkeyval. + // + // * sortKeyName<:sortkeyval - true if the sort key value is less than :sortkeyval. + // + // * sortKeyName<=:sortkeyval - true if the sort key value is less than or + // equal to :sortkeyval. + // + // * sortKeyName>:sortkeyval - true if the sort key value is greater than + // :sortkeyval. + // + // * sortKeyName>= :sortkeyval - true if the sort key value is greater than + // or equal to :sortkeyval. + // + // * sortKeyNameBETWEEN:sortkeyval1AND:sortkeyval2 - true if the sort key + // value is greater than or equal to :sortkeyval1, and less than or equal + // to :sortkeyval2. + // + // * begins_with (sortKeyName, :sortkeyval) - true if the sort key value + // begins with a particular operand. (You cannot use this function with a + // sort key that is of type Number.) Note that the function name begins_with + // is case-sensitive. + // + // Use the ExpressionAttributeValues parameter to replace tokens such as :partitionval + // and :sortval with actual values at runtime. + // + // You can optionally use the ExpressionAttributeNames parameter to replace + // the names of the partition key and sort key with placeholder tokens. This + // option might be necessary if an attribute name conflicts with a DynamoDB + // reserved word. For example, the following KeyConditionExpression parameter + // causes an error because Size is a reserved word: + // + // * Size = :myval + // + // To work around this, define a placeholder (such a #S) to represent the attribute + // name Size. KeyConditionExpression then is as follows: + // + // * #S = :myval + // + // For a list of reserved words, see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide. + // + // For more information on ExpressionAttributeNames and ExpressionAttributeValues, + // see Using Placeholders for Attribute Names and Values (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ExpressionPlaceholders.html) + // in the Amazon DynamoDB Developer Guide. + KeyConditionExpression *string `type:"string"` + + // This is a legacy parameter. Use KeyConditionExpression instead. For more + // information, see KeyConditions (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.KeyConditions.html) + // in the Amazon DynamoDB Developer Guide. + KeyConditions map[string]*Condition `type:"map"` + + // The maximum number of items to evaluate (not necessarily the number of matching + // items). If DynamoDB processes the number of items up to the limit while processing + // the results, it stops the operation and returns the matching values up to + // that point, and a key in LastEvaluatedKey to apply in a subsequent operation, + // so that you can pick up where you left off. Also, if the processed data set + // size exceeds 1 MB before DynamoDB reaches this limit, it stops the operation + // and returns the matching values up to the limit, and a key in LastEvaluatedKey + // to apply in a subsequent operation to continue the operation. For more information, + // see Query and Scan (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html) + // in the Amazon DynamoDB Developer Guide. + Limit *int64 `min:"1" type:"integer"` + + // A string that identifies one or more attributes to retrieve from the table. + // These attributes can include scalars, sets, or elements of a JSON document. + // The attributes in the expression must be separated by commas. + // + // If no attribute names are specified, then all attributes will be returned. + // If any of the requested attributes are not found, they will not appear in + // the result. + // + // For more information, see Accessing Item Attributes (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ProjectionExpression *string `type:"string"` + + // This is a legacy parameter. Use FilterExpression instead. For more information, + // see QueryFilter (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.QueryFilter.html) + // in the Amazon DynamoDB Developer Guide. + QueryFilter map[string]*Condition `type:"map"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` + + // Specifies the order for index traversal: If true (default), the traversal + // is performed in ascending order; if false, the traversal is performed in + // descending order. + // + // Items with the same partition key value are stored in sorted order by sort + // key. If the sort key data type is Number, the results are stored in numeric + // order. For type String, the results are stored in order of ASCII character + // code values. For type Binary, DynamoDB treats each byte of the binary data + // as unsigned. + // + // If ScanIndexForward is true, DynamoDB returns the results in the order in + // which they are stored (by sort key value). This is the default behavior. + // If ScanIndexForward is false, DynamoDB reads the results in reverse order + // by sort key value, and then returns the results to the client. + ScanIndexForward *bool `type:"boolean"` + + // The attributes to be returned in the result. You can retrieve all item attributes, + // specific item attributes, the count of matching items, or in the case of + // an index, some or all of the attributes projected into the index. + // + // * ALL_ATTRIBUTES - Returns all of the item attributes from the specified + // table or index. If you query a local secondary index, then for each matching + // item in the index DynamoDB will fetch the entire item from the parent + // table. If the index is configured to project all item attributes, then + // all of the data can be obtained from the local secondary index, and no + // fetching is required. + // + // * ALL_PROJECTED_ATTRIBUTES - Allowed only when querying an index. Retrieves + // all attributes that have been projected into the index. If the index is + // configured to project all attributes, this return value is equivalent + // to specifying ALL_ATTRIBUTES. + // + // * COUNT - Returns the number of matching items, rather than the matching + // items themselves. + // + // * SPECIFIC_ATTRIBUTES - Returns only the attributes listed in AttributesToGet. + // This return value is equivalent to specifying AttributesToGet without + // specifying any value for Select. + // + // If you query or scan a local secondary index and request only attributes + // that are projected into that index, the operation will read only the index + // and not the table. If any of the requested attributes are not projected + // into the local secondary index, DynamoDB will fetch each of these attributes + // from the parent table. This extra fetching incurs additional throughput + // cost and latency. + // + // If you query or scan a global secondary index, you can only request attributes + // that are projected into the index. Global secondary index queries cannot + // fetch attributes from the parent table. + // + // If neither Select nor AttributesToGet are specified, DynamoDB defaults to + // ALL_ATTRIBUTES when accessing a table, and ALL_PROJECTED_ATTRIBUTES when + // accessing an index. You cannot use both Select and AttributesToGet together + // in a single request, unless the value for Select is SPECIFIC_ATTRIBUTES. + // (This usage is equivalent to specifying AttributesToGet without any value + // for Select.) + // + // If you use the ProjectionExpression parameter, then the value for Select + // can only be SPECIFIC_ATTRIBUTES. Any other value for Select will return an + // error. + Select *string `type:"string" enum:"Select"` + + // The name of the table containing the requested items. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s QueryInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s QueryInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *QueryInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "QueryInput"} + if s.AttributesToGet != nil && len(s.AttributesToGet) < 1 { + invalidParams.Add(request.NewErrParamMinLen("AttributesToGet", 1)) + } + if s.IndexName != nil && len(*s.IndexName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("IndexName", 3)) + } + if s.Limit != nil && *s.Limit < 1 { + invalidParams.Add(request.NewErrParamMinValue("Limit", 1)) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + if s.KeyConditions != nil { + for i, v := range s.KeyConditions { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "KeyConditions", i), err.(request.ErrInvalidParams)) + } + } + } + if s.QueryFilter != nil { + for i, v := range s.QueryFilter { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "QueryFilter", i), err.(request.ErrInvalidParams)) + } + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributesToGet sets the AttributesToGet field's value. +func (s *QueryInput) SetAttributesToGet(v []*string) *QueryInput { + s.AttributesToGet = v + return s +} + +// SetConditionalOperator sets the ConditionalOperator field's value. +func (s *QueryInput) SetConditionalOperator(v string) *QueryInput { + s.ConditionalOperator = &v + return s +} + +// SetConsistentRead sets the ConsistentRead field's value. +func (s *QueryInput) SetConsistentRead(v bool) *QueryInput { + s.ConsistentRead = &v + return s +} + +// SetExclusiveStartKey sets the ExclusiveStartKey field's value. +func (s *QueryInput) SetExclusiveStartKey(v map[string]*AttributeValue) *QueryInput { + s.ExclusiveStartKey = v + return s +} + +// SetExpressionAttributeNames sets the ExpressionAttributeNames field's value. +func (s *QueryInput) SetExpressionAttributeNames(v map[string]*string) *QueryInput { + s.ExpressionAttributeNames = v + return s +} + +// SetExpressionAttributeValues sets the ExpressionAttributeValues field's value. +func (s *QueryInput) SetExpressionAttributeValues(v map[string]*AttributeValue) *QueryInput { + s.ExpressionAttributeValues = v + return s +} + +// SetFilterExpression sets the FilterExpression field's value. +func (s *QueryInput) SetFilterExpression(v string) *QueryInput { + s.FilterExpression = &v + return s +} + +// SetIndexName sets the IndexName field's value. +func (s *QueryInput) SetIndexName(v string) *QueryInput { + s.IndexName = &v + return s +} + +// SetKeyConditionExpression sets the KeyConditionExpression field's value. +func (s *QueryInput) SetKeyConditionExpression(v string) *QueryInput { + s.KeyConditionExpression = &v + return s +} + +// SetKeyConditions sets the KeyConditions field's value. +func (s *QueryInput) SetKeyConditions(v map[string]*Condition) *QueryInput { + s.KeyConditions = v + return s +} + +// SetLimit sets the Limit field's value. +func (s *QueryInput) SetLimit(v int64) *QueryInput { + s.Limit = &v + return s +} + +// SetProjectionExpression sets the ProjectionExpression field's value. +func (s *QueryInput) SetProjectionExpression(v string) *QueryInput { + s.ProjectionExpression = &v + return s +} + +// SetQueryFilter sets the QueryFilter field's value. +func (s *QueryInput) SetQueryFilter(v map[string]*Condition) *QueryInput { + s.QueryFilter = v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *QueryInput) SetReturnConsumedCapacity(v string) *QueryInput { + s.ReturnConsumedCapacity = &v + return s +} + +// SetScanIndexForward sets the ScanIndexForward field's value. +func (s *QueryInput) SetScanIndexForward(v bool) *QueryInput { + s.ScanIndexForward = &v + return s +} + +// SetSelect sets the Select field's value. +func (s *QueryInput) SetSelect(v string) *QueryInput { + s.Select = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *QueryInput) SetTableName(v string) *QueryInput { + s.TableName = &v + return s +} + +// Represents the output of a Query operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/QueryOutput +type QueryOutput struct { + _ struct{} `type:"structure"` + + // The capacity units consumed by the Query operation. The data returned includes + // the total provisioned throughput consumed, along with statistics for the + // table and any indexes involved in the operation. ConsumedCapacity is only + // returned if the ReturnConsumedCapacity parameter was specified For more information, + // see Provisioned Throughput (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) + // in the Amazon DynamoDB Developer Guide. + ConsumedCapacity *ConsumedCapacity `type:"structure"` + + // The number of items in the response. + // + // If you used a QueryFilter in the request, then Count is the number of items + // returned after the filter was applied, and ScannedCount is the number of + // matching items before the filter was applied. + // + // If you did not use a filter in the request, then Count and ScannedCount are + // the same. + Count *int64 `type:"integer"` + + // An array of item attributes that match the query criteria. Each element in + // this array consists of an attribute name and the value for that attribute. + Items []map[string]*AttributeValue `type:"list"` + + // The primary key of the item where the operation stopped, inclusive of the + // previous result set. Use this value to start a new operation, excluding this + // value in the new request. + // + // If LastEvaluatedKey is empty, then the "last page" of results has been processed + // and there is no more data to be retrieved. + // + // If LastEvaluatedKey is not empty, it does not necessarily mean that there + // is more data in the result set. The only way to know when you have reached + // the end of the result set is when LastEvaluatedKey is empty. + LastEvaluatedKey map[string]*AttributeValue `type:"map"` + + // The number of items evaluated, before any QueryFilter is applied. A high + // ScannedCount value with few, or no, Count results indicates an inefficient + // Query operation. For more information, see Count and ScannedCount (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html#Count) + // in the Amazon DynamoDB Developer Guide. + // + // If you did not use a filter in the request, then ScannedCount is the same + // as Count. + ScannedCount *int64 `type:"integer"` +} + +// String returns the string representation +func (s QueryOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s QueryOutput) GoString() string { + return s.String() +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *QueryOutput) SetConsumedCapacity(v *ConsumedCapacity) *QueryOutput { + s.ConsumedCapacity = v + return s +} + +// SetCount sets the Count field's value. +func (s *QueryOutput) SetCount(v int64) *QueryOutput { + s.Count = &v + return s +} + +// SetItems sets the Items field's value. +func (s *QueryOutput) SetItems(v []map[string]*AttributeValue) *QueryOutput { + s.Items = v + return s +} + +// SetLastEvaluatedKey sets the LastEvaluatedKey field's value. +func (s *QueryOutput) SetLastEvaluatedKey(v map[string]*AttributeValue) *QueryOutput { + s.LastEvaluatedKey = v + return s +} + +// SetScannedCount sets the ScannedCount field's value. +func (s *QueryOutput) SetScannedCount(v int64) *QueryOutput { + s.ScannedCount = &v + return s +} + +// Represents the properties of a replica. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Replica +type Replica struct { + _ struct{} `type:"structure"` + + // The region where the replica needs to be created. + RegionName *string `type:"string"` +} + +// String returns the string representation +func (s Replica) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Replica) GoString() string { + return s.String() +} + +// SetRegionName sets the RegionName field's value. +func (s *Replica) SetRegionName(v string) *Replica { + s.RegionName = &v + return s +} + +// Contains the details of the replica. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ReplicaDescription +type ReplicaDescription struct { + _ struct{} `type:"structure"` + + // The name of the region. + RegionName *string `type:"string"` +} + +// String returns the string representation +func (s ReplicaDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplicaDescription) GoString() string { + return s.String() +} + +// SetRegionName sets the RegionName field's value. +func (s *ReplicaDescription) SetRegionName(v string) *ReplicaDescription { + s.RegionName = &v + return s +} + +// Represents one of the following: +// +// * A new replica to be added to an existing global table. +// +// * New parameters for an existing replica. +// +// * An existing replica to be removed from an existing global table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ReplicaUpdate +type ReplicaUpdate struct { + _ struct{} `type:"structure"` + + // The parameters required for creating a replica on an existing global table. + Create *CreateReplicaAction `type:"structure"` + + // The name of the existing replica to be removed. + Delete *DeleteReplicaAction `type:"structure"` +} + +// String returns the string representation +func (s ReplicaUpdate) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ReplicaUpdate) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *ReplicaUpdate) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ReplicaUpdate"} + if s.Create != nil { + if err := s.Create.Validate(); err != nil { + invalidParams.AddNested("Create", err.(request.ErrInvalidParams)) + } + } + if s.Delete != nil { + if err := s.Delete.Validate(); err != nil { + invalidParams.AddNested("Delete", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetCreate sets the Create field's value. +func (s *ReplicaUpdate) SetCreate(v *CreateReplicaAction) *ReplicaUpdate { + s.Create = v + return s +} + +// SetDelete sets the Delete field's value. +func (s *ReplicaUpdate) SetDelete(v *DeleteReplicaAction) *ReplicaUpdate { + s.Delete = v + return s +} + +// Contains details for the restore. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/RestoreSummary +type RestoreSummary struct { + _ struct{} `type:"structure"` + + // Point in time or source backup time. + // + // RestoreDateTime is a required field + RestoreDateTime *time.Time `type:"timestamp" timestampFormat:"unix" required:"true"` + + // Indicates if a restore is in progress or not. + // + // RestoreInProgress is a required field + RestoreInProgress *bool `type:"boolean" required:"true"` + + // ARN of the backup from which the table was restored. + SourceBackupArn *string `min:"37" type:"string"` + + // ARN of the source table of the backup that is being restored. + SourceTableArn *string `type:"string"` +} + +// String returns the string representation +func (s RestoreSummary) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RestoreSummary) GoString() string { + return s.String() +} + +// SetRestoreDateTime sets the RestoreDateTime field's value. +func (s *RestoreSummary) SetRestoreDateTime(v time.Time) *RestoreSummary { + s.RestoreDateTime = &v + return s +} + +// SetRestoreInProgress sets the RestoreInProgress field's value. +func (s *RestoreSummary) SetRestoreInProgress(v bool) *RestoreSummary { + s.RestoreInProgress = &v + return s +} + +// SetSourceBackupArn sets the SourceBackupArn field's value. +func (s *RestoreSummary) SetSourceBackupArn(v string) *RestoreSummary { + s.SourceBackupArn = &v + return s +} + +// SetSourceTableArn sets the SourceTableArn field's value. +func (s *RestoreSummary) SetSourceTableArn(v string) *RestoreSummary { + s.SourceTableArn = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/RestoreTableFromBackupInput +type RestoreTableFromBackupInput struct { + _ struct{} `type:"structure"` + + // The ARN associated with the backup. + // + // BackupArn is a required field + BackupArn *string `min:"37" type:"string" required:"true"` + + // The name of the new table to which the backup must be restored. + // + // TargetTableName is a required field + TargetTableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s RestoreTableFromBackupInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RestoreTableFromBackupInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *RestoreTableFromBackupInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "RestoreTableFromBackupInput"} + if s.BackupArn == nil { + invalidParams.Add(request.NewErrParamRequired("BackupArn")) + } + if s.BackupArn != nil && len(*s.BackupArn) < 37 { + invalidParams.Add(request.NewErrParamMinLen("BackupArn", 37)) + } + if s.TargetTableName == nil { + invalidParams.Add(request.NewErrParamRequired("TargetTableName")) + } + if s.TargetTableName != nil && len(*s.TargetTableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TargetTableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetBackupArn sets the BackupArn field's value. +func (s *RestoreTableFromBackupInput) SetBackupArn(v string) *RestoreTableFromBackupInput { + s.BackupArn = &v + return s +} + +// SetTargetTableName sets the TargetTableName field's value. +func (s *RestoreTableFromBackupInput) SetTargetTableName(v string) *RestoreTableFromBackupInput { + s.TargetTableName = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/RestoreTableFromBackupOutput +type RestoreTableFromBackupOutput struct { + _ struct{} `type:"structure"` + + // The description of the table created from an existing backup. + TableDescription *TableDescription `type:"structure"` +} + +// String returns the string representation +func (s RestoreTableFromBackupOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s RestoreTableFromBackupOutput) GoString() string { + return s.String() +} + +// SetTableDescription sets the TableDescription field's value. +func (s *RestoreTableFromBackupOutput) SetTableDescription(v *TableDescription) *RestoreTableFromBackupOutput { + s.TableDescription = v + return s +} + +// Represents the input of a Scan operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ScanInput +type ScanInput struct { + _ struct{} `type:"structure"` + + // This is a legacy parameter. Use ProjectionExpression instead. For more information, + // see AttributesToGet (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributesToGet.html) + // in the Amazon DynamoDB Developer Guide. + AttributesToGet []*string `min:"1" type:"list"` + + // This is a legacy parameter. Use FilterExpression instead. For more information, + // see ConditionalOperator (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ConditionalOperator.html) + // in the Amazon DynamoDB Developer Guide. + ConditionalOperator *string `type:"string" enum:"ConditionalOperator"` + + // A Boolean value that determines the read consistency model during the scan: + // + // * If ConsistentRead is false, then the data returned from Scan might not + // contain the results from other recently completed write operations (PutItem, + // UpdateItem or DeleteItem). + // + // * If ConsistentRead is true, then all of the write operations that completed + // before the Scan began are guaranteed to be contained in the Scan response. + // + // The default setting for ConsistentRead is false. + // + // The ConsistentRead parameter is not supported on global secondary indexes. + // If you scan a global secondary index with ConsistentRead set to true, you + // will receive a ValidationException. + ConsistentRead *bool `type:"boolean"` + + // The primary key of the first item that this operation will evaluate. Use + // the value that was returned for LastEvaluatedKey in the previous operation. + // + // The data type for ExclusiveStartKey must be String, Number or Binary. No + // set data types are allowed. + // + // In a parallel scan, a Scan request that includes ExclusiveStartKey must specify + // the same segment whose previous Scan returned the corresponding value of + // LastEvaluatedKey. + ExclusiveStartKey map[string]*AttributeValue `type:"map"` + + // One or more substitution tokens for attribute names in an expression. The + // following are some use cases for using ExpressionAttributeNames: + // + // * To access an attribute whose name conflicts with a DynamoDB reserved + // word. + // + // * To create a placeholder for repeating occurrences of an attribute name + // in an expression. + // + // * To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // * Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could specify + // the following for ExpressionAttributeNames: + // + // * {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // * #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeNames map[string]*string `type:"map"` + + // One or more values that can be substituted in an expression. + // + // Use the : (colon) character in an expression to dereference an attribute + // value. For example, suppose that you wanted to check whether the value of + // the ProductStatus attribute was one of the following: + // + // Available | Backordered | Discontinued + // + // You would first need to specify ExpressionAttributeValues as follows: + // + // { ":avail":{"S":"Available"}, ":back":{"S":"Backordered"}, ":disc":{"S":"Discontinued"} + // } + // + // You could then use these values in an expression, such as this: + // + // ProductStatus IN (:avail, :back, :disc) + // + // For more information on expression attribute values, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeValues map[string]*AttributeValue `type:"map"` + + // A string that contains conditions that DynamoDB applies after the Scan operation, + // but before the data is returned to you. Items that do not satisfy the FilterExpression + // criteria are not returned. + // + // A FilterExpression is applied after the items have already been read; the + // process of filtering does not consume any additional read capacity units. + // + // For more information, see Filter Expressions (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html#FilteringResults) + // in the Amazon DynamoDB Developer Guide. + FilterExpression *string `type:"string"` + + // The name of a secondary index to scan. This index can be any local secondary + // index or global secondary index. Note that if you use the IndexName parameter, + // you must also provide TableName. + IndexName *string `min:"3" type:"string"` + + // The maximum number of items to evaluate (not necessarily the number of matching + // items). If DynamoDB processes the number of items up to the limit while processing + // the results, it stops the operation and returns the matching values up to + // that point, and a key in LastEvaluatedKey to apply in a subsequent operation, + // so that you can pick up where you left off. Also, if the processed data set + // size exceeds 1 MB before DynamoDB reaches this limit, it stops the operation + // and returns the matching values up to the limit, and a key in LastEvaluatedKey + // to apply in a subsequent operation to continue the operation. For more information, + // see Query and Scan (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html) + // in the Amazon DynamoDB Developer Guide. + Limit *int64 `min:"1" type:"integer"` + + // A string that identifies one or more attributes to retrieve from the specified + // table or index. These attributes can include scalars, sets, or elements of + // a JSON document. The attributes in the expression must be separated by commas. + // + // If no attribute names are specified, then all attributes will be returned. + // If any of the requested attributes are not found, they will not appear in + // the result. + // + // For more information, see Accessing Item Attributes (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ProjectionExpression *string `type:"string"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` + + // This is a legacy parameter. Use FilterExpression instead. For more information, + // see ScanFilter (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ScanFilter.html) + // in the Amazon DynamoDB Developer Guide. + ScanFilter map[string]*Condition `type:"map"` + + // For a parallel Scan request, Segment identifies an individual segment to + // be scanned by an application worker. + // + // Segment IDs are zero-based, so the first segment is always 0. For example, + // if you want to use four application threads to scan a table or an index, + // then the first thread specifies a Segment value of 0, the second thread specifies + // 1, and so on. + // + // The value of LastEvaluatedKey returned from a parallel Scan request must + // be used as ExclusiveStartKey with the same segment ID in a subsequent Scan + // operation. + // + // The value for Segment must be greater than or equal to 0, and less than the + // value provided for TotalSegments. + // + // If you provide Segment, you must also provide TotalSegments. + Segment *int64 `type:"integer"` + + // The attributes to be returned in the result. You can retrieve all item attributes, + // specific item attributes, the count of matching items, or in the case of + // an index, some or all of the attributes projected into the index. + // + // * ALL_ATTRIBUTES - Returns all of the item attributes from the specified + // table or index. If you query a local secondary index, then for each matching + // item in the index DynamoDB will fetch the entire item from the parent + // table. If the index is configured to project all item attributes, then + // all of the data can be obtained from the local secondary index, and no + // fetching is required. + // + // * ALL_PROJECTED_ATTRIBUTES - Allowed only when querying an index. Retrieves + // all attributes that have been projected into the index. If the index is + // configured to project all attributes, this return value is equivalent + // to specifying ALL_ATTRIBUTES. + // + // * COUNT - Returns the number of matching items, rather than the matching + // items themselves. + // + // * SPECIFIC_ATTRIBUTES - Returns only the attributes listed in AttributesToGet. + // This return value is equivalent to specifying AttributesToGet without + // specifying any value for Select. + // + // If you query or scan a local secondary index and request only attributes + // that are projected into that index, the operation will read only the index + // and not the table. If any of the requested attributes are not projected + // into the local secondary index, DynamoDB will fetch each of these attributes + // from the parent table. This extra fetching incurs additional throughput + // cost and latency. + // + // If you query or scan a global secondary index, you can only request attributes + // that are projected into the index. Global secondary index queries cannot + // fetch attributes from the parent table. + // + // If neither Select nor AttributesToGet are specified, DynamoDB defaults to + // ALL_ATTRIBUTES when accessing a table, and ALL_PROJECTED_ATTRIBUTES when + // accessing an index. You cannot use both Select and AttributesToGet together + // in a single request, unless the value for Select is SPECIFIC_ATTRIBUTES. + // (This usage is equivalent to specifying AttributesToGet without any value + // for Select.) + // + // If you use the ProjectionExpression parameter, then the value for Select + // can only be SPECIFIC_ATTRIBUTES. Any other value for Select will return an + // error. + Select *string `type:"string" enum:"Select"` + + // The name of the table containing the requested items; or, if you provide + // IndexName, the name of the table to which that index belongs. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` + + // For a parallel Scan request, TotalSegments represents the total number of + // segments into which the Scan operation will be divided. The value of TotalSegments + // corresponds to the number of application workers that will perform the parallel + // scan. For example, if you want to use four application threads to scan a + // table or an index, specify a TotalSegments value of 4. + // + // The value for TotalSegments must be greater than or equal to 1, and less + // than or equal to 1000000. If you specify a TotalSegments value of 1, the + // Scan operation will be sequential rather than parallel. + // + // If you specify TotalSegments, you must also specify Segment. + TotalSegments *int64 `min:"1" type:"integer"` +} + +// String returns the string representation +func (s ScanInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScanInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *ScanInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "ScanInput"} + if s.AttributesToGet != nil && len(s.AttributesToGet) < 1 { + invalidParams.Add(request.NewErrParamMinLen("AttributesToGet", 1)) + } + if s.IndexName != nil && len(*s.IndexName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("IndexName", 3)) + } + if s.Limit != nil && *s.Limit < 1 { + invalidParams.Add(request.NewErrParamMinValue("Limit", 1)) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + if s.TotalSegments != nil && *s.TotalSegments < 1 { + invalidParams.Add(request.NewErrParamMinValue("TotalSegments", 1)) + } + if s.ScanFilter != nil { + for i, v := range s.ScanFilter { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "ScanFilter", i), err.(request.ErrInvalidParams)) + } + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributesToGet sets the AttributesToGet field's value. +func (s *ScanInput) SetAttributesToGet(v []*string) *ScanInput { + s.AttributesToGet = v + return s +} + +// SetConditionalOperator sets the ConditionalOperator field's value. +func (s *ScanInput) SetConditionalOperator(v string) *ScanInput { + s.ConditionalOperator = &v + return s +} + +// SetConsistentRead sets the ConsistentRead field's value. +func (s *ScanInput) SetConsistentRead(v bool) *ScanInput { + s.ConsistentRead = &v + return s +} + +// SetExclusiveStartKey sets the ExclusiveStartKey field's value. +func (s *ScanInput) SetExclusiveStartKey(v map[string]*AttributeValue) *ScanInput { + s.ExclusiveStartKey = v + return s +} + +// SetExpressionAttributeNames sets the ExpressionAttributeNames field's value. +func (s *ScanInput) SetExpressionAttributeNames(v map[string]*string) *ScanInput { + s.ExpressionAttributeNames = v + return s +} + +// SetExpressionAttributeValues sets the ExpressionAttributeValues field's value. +func (s *ScanInput) SetExpressionAttributeValues(v map[string]*AttributeValue) *ScanInput { + s.ExpressionAttributeValues = v + return s +} + +// SetFilterExpression sets the FilterExpression field's value. +func (s *ScanInput) SetFilterExpression(v string) *ScanInput { + s.FilterExpression = &v + return s +} + +// SetIndexName sets the IndexName field's value. +func (s *ScanInput) SetIndexName(v string) *ScanInput { + s.IndexName = &v + return s +} + +// SetLimit sets the Limit field's value. +func (s *ScanInput) SetLimit(v int64) *ScanInput { + s.Limit = &v + return s +} + +// SetProjectionExpression sets the ProjectionExpression field's value. +func (s *ScanInput) SetProjectionExpression(v string) *ScanInput { + s.ProjectionExpression = &v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *ScanInput) SetReturnConsumedCapacity(v string) *ScanInput { + s.ReturnConsumedCapacity = &v + return s +} + +// SetScanFilter sets the ScanFilter field's value. +func (s *ScanInput) SetScanFilter(v map[string]*Condition) *ScanInput { + s.ScanFilter = v + return s +} + +// SetSegment sets the Segment field's value. +func (s *ScanInput) SetSegment(v int64) *ScanInput { + s.Segment = &v + return s +} + +// SetSelect sets the Select field's value. +func (s *ScanInput) SetSelect(v string) *ScanInput { + s.Select = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *ScanInput) SetTableName(v string) *ScanInput { + s.TableName = &v + return s +} + +// SetTotalSegments sets the TotalSegments field's value. +func (s *ScanInput) SetTotalSegments(v int64) *ScanInput { + s.TotalSegments = &v + return s +} + +// Represents the output of a Scan operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/ScanOutput +type ScanOutput struct { + _ struct{} `type:"structure"` + + // The capacity units consumed by the Scan operation. The data returned includes + // the total provisioned throughput consumed, along with statistics for the + // table and any indexes involved in the operation. ConsumedCapacity is only + // returned if the ReturnConsumedCapacity parameter was specified. For more + // information, see Provisioned Throughput (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) + // in the Amazon DynamoDB Developer Guide. + ConsumedCapacity *ConsumedCapacity `type:"structure"` + + // The number of items in the response. + // + // If you set ScanFilter in the request, then Count is the number of items returned + // after the filter was applied, and ScannedCount is the number of matching + // items before the filter was applied. + // + // If you did not use a filter in the request, then Count is the same as ScannedCount. + Count *int64 `type:"integer"` + + // An array of item attributes that match the scan criteria. Each element in + // this array consists of an attribute name and the value for that attribute. + Items []map[string]*AttributeValue `type:"list"` + + // The primary key of the item where the operation stopped, inclusive of the + // previous result set. Use this value to start a new operation, excluding this + // value in the new request. + // + // If LastEvaluatedKey is empty, then the "last page" of results has been processed + // and there is no more data to be retrieved. + // + // If LastEvaluatedKey is not empty, it does not necessarily mean that there + // is more data in the result set. The only way to know when you have reached + // the end of the result set is when LastEvaluatedKey is empty. + LastEvaluatedKey map[string]*AttributeValue `type:"map"` + + // The number of items evaluated, before any ScanFilter is applied. A high ScannedCount + // value with few, or no, Count results indicates an inefficient Scan operation. + // For more information, see Count and ScannedCount (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html#Count) + // in the Amazon DynamoDB Developer Guide. + // + // If you did not use a filter in the request, then ScannedCount is the same + // as Count. + ScannedCount *int64 `type:"integer"` +} + +// String returns the string representation +func (s ScanOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s ScanOutput) GoString() string { + return s.String() +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *ScanOutput) SetConsumedCapacity(v *ConsumedCapacity) *ScanOutput { + s.ConsumedCapacity = v + return s +} + +// SetCount sets the Count field's value. +func (s *ScanOutput) SetCount(v int64) *ScanOutput { + s.Count = &v + return s +} + +// SetItems sets the Items field's value. +func (s *ScanOutput) SetItems(v []map[string]*AttributeValue) *ScanOutput { + s.Items = v + return s +} + +// SetLastEvaluatedKey sets the LastEvaluatedKey field's value. +func (s *ScanOutput) SetLastEvaluatedKey(v map[string]*AttributeValue) *ScanOutput { + s.LastEvaluatedKey = v + return s +} + +// SetScannedCount sets the ScannedCount field's value. +func (s *ScanOutput) SetScannedCount(v int64) *ScanOutput { + s.ScannedCount = &v + return s +} + +// Contains the details of the table when the backup was created. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/SourceTableDetails +type SourceTableDetails struct { + _ struct{} `type:"structure"` + + // Number of items in the table. Please note this is an approximate value. + ItemCount *int64 `type:"long"` + + // Schema of the table. + // + // KeySchema is a required field + KeySchema []*KeySchemaElement `min:"1" type:"list" required:"true"` + + // Read IOPs and Write IOPS on the table when the backup was created. + // + // ProvisionedThroughput is a required field + ProvisionedThroughput *ProvisionedThroughput `type:"structure" required:"true"` + + // ARN of the table for which backup was created. + TableArn *string `type:"string"` + + // Time when the source table was created. + // + // TableCreationDateTime is a required field + TableCreationDateTime *time.Time `type:"timestamp" timestampFormat:"unix" required:"true"` + + // Unique identifier for the table for which the backup was created. + // + // TableId is a required field + TableId *string `type:"string" required:"true"` + + // The name of the table for which the backup was created. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` + + // Size of the table in bytes. Please note this is an approximate value. + TableSizeBytes *int64 `type:"long"` +} + +// String returns the string representation +func (s SourceTableDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SourceTableDetails) GoString() string { + return s.String() +} + +// SetItemCount sets the ItemCount field's value. +func (s *SourceTableDetails) SetItemCount(v int64) *SourceTableDetails { + s.ItemCount = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *SourceTableDetails) SetKeySchema(v []*KeySchemaElement) *SourceTableDetails { + s.KeySchema = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *SourceTableDetails) SetProvisionedThroughput(v *ProvisionedThroughput) *SourceTableDetails { + s.ProvisionedThroughput = v + return s +} + +// SetTableArn sets the TableArn field's value. +func (s *SourceTableDetails) SetTableArn(v string) *SourceTableDetails { + s.TableArn = &v + return s +} + +// SetTableCreationDateTime sets the TableCreationDateTime field's value. +func (s *SourceTableDetails) SetTableCreationDateTime(v time.Time) *SourceTableDetails { + s.TableCreationDateTime = &v + return s +} + +// SetTableId sets the TableId field's value. +func (s *SourceTableDetails) SetTableId(v string) *SourceTableDetails { + s.TableId = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *SourceTableDetails) SetTableName(v string) *SourceTableDetails { + s.TableName = &v + return s +} + +// SetTableSizeBytes sets the TableSizeBytes field's value. +func (s *SourceTableDetails) SetTableSizeBytes(v int64) *SourceTableDetails { + s.TableSizeBytes = &v + return s +} + +// Contains the details of the features enabled on the table when the backup +// was created. For example, LSIs, GSIs, streams, TTL. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/SourceTableFeatureDetails +type SourceTableFeatureDetails struct { + _ struct{} `type:"structure"` + + // Represents the GSI properties for the table when the backup was created. + // It includes the IndexName, KeySchema, Projection and ProvisionedThroughput + // for the GSIs on the table at the time of backup. + GlobalSecondaryIndexes []*GlobalSecondaryIndexInfo `type:"list"` + + // Represents the LSI properties for the table when the backup was created. + // It includes the IndexName, KeySchema and Projection for the LSIs on the table + // at the time of backup. + LocalSecondaryIndexes []*LocalSecondaryIndexInfo `type:"list"` + + // Stream settings on the table when the backup was created. + StreamDescription *StreamSpecification `type:"structure"` + + // Time to Live settings on the table when the backup was created. + TimeToLiveDescription *TimeToLiveDescription `type:"structure"` +} + +// String returns the string representation +func (s SourceTableFeatureDetails) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s SourceTableFeatureDetails) GoString() string { + return s.String() +} + +// SetGlobalSecondaryIndexes sets the GlobalSecondaryIndexes field's value. +func (s *SourceTableFeatureDetails) SetGlobalSecondaryIndexes(v []*GlobalSecondaryIndexInfo) *SourceTableFeatureDetails { + s.GlobalSecondaryIndexes = v + return s +} + +// SetLocalSecondaryIndexes sets the LocalSecondaryIndexes field's value. +func (s *SourceTableFeatureDetails) SetLocalSecondaryIndexes(v []*LocalSecondaryIndexInfo) *SourceTableFeatureDetails { + s.LocalSecondaryIndexes = v + return s +} + +// SetStreamDescription sets the StreamDescription field's value. +func (s *SourceTableFeatureDetails) SetStreamDescription(v *StreamSpecification) *SourceTableFeatureDetails { + s.StreamDescription = v + return s +} + +// SetTimeToLiveDescription sets the TimeToLiveDescription field's value. +func (s *SourceTableFeatureDetails) SetTimeToLiveDescription(v *TimeToLiveDescription) *SourceTableFeatureDetails { + s.TimeToLiveDescription = v + return s +} + +// Represents the DynamoDB Streams configuration for a table in DynamoDB. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/StreamSpecification +type StreamSpecification struct { + _ struct{} `type:"structure"` + + // Indicates whether DynamoDB Streams is enabled (true) or disabled (false) + // on the table. + StreamEnabled *bool `type:"boolean"` + + // When an item in the table is modified, StreamViewType determines what information + // is written to the stream for this table. Valid values for StreamViewType + // are: + // + // * KEYS_ONLY - Only the key attributes of the modified item are written + // to the stream. + // + // * NEW_IMAGE - The entire item, as it appears after it was modified, is + // written to the stream. + // + // * OLD_IMAGE - The entire item, as it appeared before it was modified, + // is written to the stream. + // + // * NEW_AND_OLD_IMAGES - Both the new and the old item images of the item + // are written to the stream. + StreamViewType *string `type:"string" enum:"StreamViewType"` +} + +// String returns the string representation +func (s StreamSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s StreamSpecification) GoString() string { + return s.String() +} + +// SetStreamEnabled sets the StreamEnabled field's value. +func (s *StreamSpecification) SetStreamEnabled(v bool) *StreamSpecification { + s.StreamEnabled = &v + return s +} + +// SetStreamViewType sets the StreamViewType field's value. +func (s *StreamSpecification) SetStreamViewType(v string) *StreamSpecification { + s.StreamViewType = &v + return s +} + +// Represents the properties of a table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/TableDescription +type TableDescription struct { + _ struct{} `type:"structure"` + + // An array of AttributeDefinition objects. Each of these objects describes + // one attribute in the table and index key schema. + // + // Each AttributeDefinition object in this array is composed of: + // + // * AttributeName - The name of the attribute. + // + // * AttributeType - The data type for the attribute. + AttributeDefinitions []*AttributeDefinition `type:"list"` + + // The date and time when the table was created, in UNIX epoch time (http://www.epochconverter.com/) + // format. + CreationDateTime *time.Time `type:"timestamp" timestampFormat:"unix"` + + // The global secondary indexes, if any, on the table. Each index is scoped + // to a given partition key value. Each element is composed of: + // + // * Backfilling - If true, then the index is currently in the backfilling + // phase. Backfilling occurs only when a new global secondary index is added + // to the table; it is the process by which DynamoDB populates the new index + // with data from the table. (This attribute does not appear for indexes + // that were created during a CreateTable operation.) + // + // * IndexName - The name of the global secondary index. + // + // * IndexSizeBytes - The total size of the global secondary index, in bytes. + // DynamoDB updates this value approximately every six hours. Recent changes + // might not be reflected in this value. + // + // * IndexStatus - The current status of the global secondary index: + // + // CREATING - The index is being created. + // + // UPDATING - The index is being updated. + // + // DELETING - The index is being deleted. + // + // ACTIVE - The index is ready for use. + // + // * ItemCount - The number of items in the global secondary index. DynamoDB + // updates this value approximately every six hours. Recent changes might + // not be reflected in this value. + // + // * KeySchema - Specifies the complete index key schema. The attribute names + // in the key schema must be between 1 and 255 characters (inclusive). The + // key schema must begin with the same partition key as the table. + // + // * Projection - Specifies attributes that are copied (projected) from the + // table into the index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. Each attribute + // specification is composed of: + // + // ProjectionType - One of the following: + // + // KEYS_ONLY - Only the index and primary keys are projected into the index. + // + // INCLUDE - Only the specified table attributes are projected into the index. + // The list of projected attributes are in NonKeyAttributes. + // + // ALL - All of the table attributes are projected into the index. + // + // NonKeyAttributes - A list of one or more non-key attribute names that are + // projected into the secondary index. The total count of attributes provided + // in NonKeyAttributes, summed across all of the secondary indexes, must + // not exceed 20. If you project the same attribute into two different indexes, + // this counts as two distinct attributes when determining the total. + // + // * ProvisionedThroughput - The provisioned throughput settings for the + // global secondary index, consisting of read and write capacity units, along + // with data about increases and decreases. + // + // If the table is in the DELETING state, no information about indexes will + // be returned. + GlobalSecondaryIndexes []*GlobalSecondaryIndexDescription `type:"list"` + + // The number of items in the specified table. DynamoDB updates this value approximately + // every six hours. Recent changes might not be reflected in this value. + ItemCount *int64 `type:"long"` + + // The primary key structure for the table. Each KeySchemaElement consists of: + // + // * AttributeName - The name of the attribute. + // + // * KeyType - The role of the attribute: + // + // HASH - partition key + // + // RANGE - sort key + // + // The partition key of an item is also known as its hash attribute. The term + // "hash attribute" derives from DynamoDB' usage of an internal hash function + // to evenly distribute data items across partitions, based on their partition + // key values. + // + // The sort key of an item is also known as its range attribute. The term "range + // attribute" derives from the way DynamoDB stores items with the same partition + // key physically close together, in sorted order by the sort key value. + // + // For more information about primary keys, see Primary Key (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataModel.html#DataModelPrimaryKey) + // in the Amazon DynamoDB Developer Guide. + KeySchema []*KeySchemaElement `min:"1" type:"list"` + + // The Amazon Resource Name (ARN) that uniquely identifies the latest stream + // for this table. + LatestStreamArn *string `min:"37" type:"string"` + + // A timestamp, in ISO 8601 format, for this stream. + // + // Note that LatestStreamLabel is not a unique identifier for the stream, because + // it is possible that a stream from another table might have the same timestamp. + // However, the combination of the following three elements is guaranteed to + // be unique: + // + // * the AWS customer ID. + // + // * the table name. + // + // * the StreamLabel. + LatestStreamLabel *string `type:"string"` + + // Represents one or more local secondary indexes on the table. Each index is + // scoped to a given partition key value. Tables with one or more local secondary + // indexes are subject to an item collection size limit, where the amount of + // data within a given item collection cannot exceed 10 GB. Each element is + // composed of: + // + // * IndexName - The name of the local secondary index. + // + // * KeySchema - Specifies the complete index key schema. The attribute names + // in the key schema must be between 1 and 255 characters (inclusive). The + // key schema must begin with the same partition key as the table. + // + // * Projection - Specifies attributes that are copied (projected) from the + // table into the index. These are in addition to the primary key attributes + // and index key attributes, which are automatically projected. Each attribute + // specification is composed of: + // + // ProjectionType - One of the following: + // + // KEYS_ONLY - Only the index and primary keys are projected into the index. + // + // INCLUDE - Only the specified table attributes are projected into the index. + // The list of projected attributes are in NonKeyAttributes. + // + // ALL - All of the table attributes are projected into the index. + // + // NonKeyAttributes - A list of one or more non-key attribute names that are + // projected into the secondary index. The total count of attributes provided + // in NonKeyAttributes, summed across all of the secondary indexes, must + // not exceed 20. If you project the same attribute into two different indexes, + // this counts as two distinct attributes when determining the total. + // + // * IndexSizeBytes - Represents the total size of the index, in bytes. DynamoDB + // updates this value approximately every six hours. Recent changes might + // not be reflected in this value. + // + // * ItemCount - Represents the number of items in the index. DynamoDB updates + // this value approximately every six hours. Recent changes might not be + // reflected in this value. + // + // If the table is in the DELETING state, no information about indexes will + // be returned. + LocalSecondaryIndexes []*LocalSecondaryIndexDescription `type:"list"` + + // The provisioned throughput settings for the table, consisting of read and + // write capacity units, along with data about increases and decreases. + ProvisionedThroughput *ProvisionedThroughputDescription `type:"structure"` + + // Contains details for the restore. + RestoreSummary *RestoreSummary `type:"structure"` + + // The current DynamoDB Streams configuration for the table. + StreamSpecification *StreamSpecification `type:"structure"` + + // The Amazon Resource Name (ARN) that uniquely identifies the table. + TableArn *string `type:"string"` + + // Unique identifier for the table for which the backup was created. + TableId *string `type:"string"` + + // The name of the table. + TableName *string `min:"3" type:"string"` + + // The total size of the specified table, in bytes. DynamoDB updates this value + // approximately every six hours. Recent changes might not be reflected in this + // value. + TableSizeBytes *int64 `type:"long"` + + // The current state of the table: + // + // * CREATING - The table is being created. + // + // * UPDATING - The table is being updated. + // + // * DELETING - The table is being deleted. + // + // * ACTIVE - The table is ready for use. + TableStatus *string `type:"string" enum:"TableStatus"` +} + +// String returns the string representation +func (s TableDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TableDescription) GoString() string { + return s.String() +} + +// SetAttributeDefinitions sets the AttributeDefinitions field's value. +func (s *TableDescription) SetAttributeDefinitions(v []*AttributeDefinition) *TableDescription { + s.AttributeDefinitions = v + return s +} + +// SetCreationDateTime sets the CreationDateTime field's value. +func (s *TableDescription) SetCreationDateTime(v time.Time) *TableDescription { + s.CreationDateTime = &v + return s +} + +// SetGlobalSecondaryIndexes sets the GlobalSecondaryIndexes field's value. +func (s *TableDescription) SetGlobalSecondaryIndexes(v []*GlobalSecondaryIndexDescription) *TableDescription { + s.GlobalSecondaryIndexes = v + return s +} + +// SetItemCount sets the ItemCount field's value. +func (s *TableDescription) SetItemCount(v int64) *TableDescription { + s.ItemCount = &v + return s +} + +// SetKeySchema sets the KeySchema field's value. +func (s *TableDescription) SetKeySchema(v []*KeySchemaElement) *TableDescription { + s.KeySchema = v + return s +} + +// SetLatestStreamArn sets the LatestStreamArn field's value. +func (s *TableDescription) SetLatestStreamArn(v string) *TableDescription { + s.LatestStreamArn = &v + return s +} + +// SetLatestStreamLabel sets the LatestStreamLabel field's value. +func (s *TableDescription) SetLatestStreamLabel(v string) *TableDescription { + s.LatestStreamLabel = &v + return s +} + +// SetLocalSecondaryIndexes sets the LocalSecondaryIndexes field's value. +func (s *TableDescription) SetLocalSecondaryIndexes(v []*LocalSecondaryIndexDescription) *TableDescription { + s.LocalSecondaryIndexes = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *TableDescription) SetProvisionedThroughput(v *ProvisionedThroughputDescription) *TableDescription { + s.ProvisionedThroughput = v + return s +} + +// SetRestoreSummary sets the RestoreSummary field's value. +func (s *TableDescription) SetRestoreSummary(v *RestoreSummary) *TableDescription { + s.RestoreSummary = v + return s +} + +// SetStreamSpecification sets the StreamSpecification field's value. +func (s *TableDescription) SetStreamSpecification(v *StreamSpecification) *TableDescription { + s.StreamSpecification = v + return s +} + +// SetTableArn sets the TableArn field's value. +func (s *TableDescription) SetTableArn(v string) *TableDescription { + s.TableArn = &v + return s +} + +// SetTableId sets the TableId field's value. +func (s *TableDescription) SetTableId(v string) *TableDescription { + s.TableId = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *TableDescription) SetTableName(v string) *TableDescription { + s.TableName = &v + return s +} + +// SetTableSizeBytes sets the TableSizeBytes field's value. +func (s *TableDescription) SetTableSizeBytes(v int64) *TableDescription { + s.TableSizeBytes = &v + return s +} + +// SetTableStatus sets the TableStatus field's value. +func (s *TableDescription) SetTableStatus(v string) *TableDescription { + s.TableStatus = &v + return s +} + +// Describes a tag. A tag is a key-value pair. You can add up to 50 tags to +// a single DynamoDB table. +// +// AWS-assigned tag names and values are automatically assigned the aws: prefix, +// which the user cannot assign. AWS-assigned tag names do not count towards +// the tag limit of 50. User-assigned tag names have the prefix user: in the +// Cost Allocation Report. You cannot backdate the application of a tag. +// +// For an overview on tagging DynamoDB resources, see Tagging for DynamoDB (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tagging.html) +// in the Amazon DynamoDB Developer Guide. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/Tag +type Tag struct { + _ struct{} `type:"structure"` + + // The key of the tag.Tag keys are case sensitive. Each DynamoDB table can only + // have up to one tag with the same key. If you try to add an existing tag (same + // key), the existing tag value will be updated to the new value. + // + // Key is a required field + Key *string `min:"1" type:"string" required:"true"` + + // The value of the tag. Tag values are case-sensitive and can be null. + // + // Value is a required field + Value *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s Tag) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Tag) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *Tag) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "Tag"} + if s.Key == nil { + invalidParams.Add(request.NewErrParamRequired("Key")) + } + if s.Key != nil && len(*s.Key) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Key", 1)) + } + if s.Value == nil { + invalidParams.Add(request.NewErrParamRequired("Value")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetKey sets the Key field's value. +func (s *Tag) SetKey(v string) *Tag { + s.Key = &v + return s +} + +// SetValue sets the Value field's value. +func (s *Tag) SetValue(v string) *Tag { + s.Value = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/TagResourceInput +type TagResourceInput struct { + _ struct{} `type:"structure"` + + // Identifies the Amazon DynamoDB resource to which tags should be added. This + // value is an Amazon Resource Name (ARN). + // + // ResourceArn is a required field + ResourceArn *string `min:"1" type:"string" required:"true"` + + // The tags to be assigned to the Amazon DynamoDB resource. + // + // Tags is a required field + Tags []*Tag `type:"list" required:"true"` +} + +// String returns the string representation +func (s TagResourceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TagResourceInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *TagResourceInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "TagResourceInput"} + if s.ResourceArn == nil { + invalidParams.Add(request.NewErrParamRequired("ResourceArn")) + } + if s.ResourceArn != nil && len(*s.ResourceArn) < 1 { + invalidParams.Add(request.NewErrParamMinLen("ResourceArn", 1)) + } + if s.Tags == nil { + invalidParams.Add(request.NewErrParamRequired("Tags")) + } + if s.Tags != nil { + for i, v := range s.Tags { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "Tags", i), err.(request.ErrInvalidParams)) + } + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetResourceArn sets the ResourceArn field's value. +func (s *TagResourceInput) SetResourceArn(v string) *TagResourceInput { + s.ResourceArn = &v + return s +} + +// SetTags sets the Tags field's value. +func (s *TagResourceInput) SetTags(v []*Tag) *TagResourceInput { + s.Tags = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/TagResourceOutput +type TagResourceOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s TagResourceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TagResourceOutput) GoString() string { + return s.String() +} + +// The description of the Time to Live (TTL) status on the specified table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/TimeToLiveDescription +type TimeToLiveDescription struct { + _ struct{} `type:"structure"` + + // The name of the Time to Live attribute for items in the table. + AttributeName *string `min:"1" type:"string"` + + // The Time to Live status for the table. + TimeToLiveStatus *string `type:"string" enum:"TimeToLiveStatus"` +} + +// String returns the string representation +func (s TimeToLiveDescription) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TimeToLiveDescription) GoString() string { + return s.String() +} + +// SetAttributeName sets the AttributeName field's value. +func (s *TimeToLiveDescription) SetAttributeName(v string) *TimeToLiveDescription { + s.AttributeName = &v + return s +} + +// SetTimeToLiveStatus sets the TimeToLiveStatus field's value. +func (s *TimeToLiveDescription) SetTimeToLiveStatus(v string) *TimeToLiveDescription { + s.TimeToLiveStatus = &v + return s +} + +// Represents the settings used to enable or disable Time to Live for the specified +// table. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/TimeToLiveSpecification +type TimeToLiveSpecification struct { + _ struct{} `type:"structure"` + + // The name of the Time to Live attribute used to store the expiration time + // for items in the table. + // + // AttributeName is a required field + AttributeName *string `min:"1" type:"string" required:"true"` + + // Indicates whether Time To Live is to be enabled (true) or disabled (false) + // on the table. + // + // Enabled is a required field + Enabled *bool `type:"boolean" required:"true"` +} + +// String returns the string representation +func (s TimeToLiveSpecification) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s TimeToLiveSpecification) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *TimeToLiveSpecification) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "TimeToLiveSpecification"} + if s.AttributeName == nil { + invalidParams.Add(request.NewErrParamRequired("AttributeName")) + } + if s.AttributeName != nil && len(*s.AttributeName) < 1 { + invalidParams.Add(request.NewErrParamMinLen("AttributeName", 1)) + } + if s.Enabled == nil { + invalidParams.Add(request.NewErrParamRequired("Enabled")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributeName sets the AttributeName field's value. +func (s *TimeToLiveSpecification) SetAttributeName(v string) *TimeToLiveSpecification { + s.AttributeName = &v + return s +} + +// SetEnabled sets the Enabled field's value. +func (s *TimeToLiveSpecification) SetEnabled(v bool) *TimeToLiveSpecification { + s.Enabled = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UntagResourceInput +type UntagResourceInput struct { + _ struct{} `type:"structure"` + + // The Amazon DyanamoDB resource the tags will be removed from. This value is + // an Amazon Resource Name (ARN). + // + // ResourceArn is a required field + ResourceArn *string `min:"1" type:"string" required:"true"` + + // A list of tag keys. Existing tags of the resource whose keys are members + // of this list will be removed from the Amazon DynamoDB resource. + // + // TagKeys is a required field + TagKeys []*string `type:"list" required:"true"` +} + +// String returns the string representation +func (s UntagResourceInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UntagResourceInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UntagResourceInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UntagResourceInput"} + if s.ResourceArn == nil { + invalidParams.Add(request.NewErrParamRequired("ResourceArn")) + } + if s.ResourceArn != nil && len(*s.ResourceArn) < 1 { + invalidParams.Add(request.NewErrParamMinLen("ResourceArn", 1)) + } + if s.TagKeys == nil { + invalidParams.Add(request.NewErrParamRequired("TagKeys")) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetResourceArn sets the ResourceArn field's value. +func (s *UntagResourceInput) SetResourceArn(v string) *UntagResourceInput { + s.ResourceArn = &v + return s +} + +// SetTagKeys sets the TagKeys field's value. +func (s *UntagResourceInput) SetTagKeys(v []*string) *UntagResourceInput { + s.TagKeys = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UntagResourceOutput +type UntagResourceOutput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s UntagResourceOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UntagResourceOutput) GoString() string { + return s.String() +} + +// Represents the new provisioned throughput settings to be applied to a global +// secondary index. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateGlobalSecondaryIndexAction +type UpdateGlobalSecondaryIndexAction struct { + _ struct{} `type:"structure"` + + // The name of the global secondary index to be updated. + // + // IndexName is a required field + IndexName *string `min:"3" type:"string" required:"true"` + + // Represents the provisioned throughput settings for the specified global secondary + // index. + // + // For current minimum and maximum provisioned throughput values, see Limits + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html) + // in the Amazon DynamoDB Developer Guide. + // + // ProvisionedThroughput is a required field + ProvisionedThroughput *ProvisionedThroughput `type:"structure" required:"true"` +} + +// String returns the string representation +func (s UpdateGlobalSecondaryIndexAction) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateGlobalSecondaryIndexAction) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UpdateGlobalSecondaryIndexAction) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UpdateGlobalSecondaryIndexAction"} + if s.IndexName == nil { + invalidParams.Add(request.NewErrParamRequired("IndexName")) + } + if s.IndexName != nil && len(*s.IndexName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("IndexName", 3)) + } + if s.ProvisionedThroughput == nil { + invalidParams.Add(request.NewErrParamRequired("ProvisionedThroughput")) + } + if s.ProvisionedThroughput != nil { + if err := s.ProvisionedThroughput.Validate(); err != nil { + invalidParams.AddNested("ProvisionedThroughput", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetIndexName sets the IndexName field's value. +func (s *UpdateGlobalSecondaryIndexAction) SetIndexName(v string) *UpdateGlobalSecondaryIndexAction { + s.IndexName = &v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *UpdateGlobalSecondaryIndexAction) SetProvisionedThroughput(v *ProvisionedThroughput) *UpdateGlobalSecondaryIndexAction { + s.ProvisionedThroughput = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateGlobalTableInput +type UpdateGlobalTableInput struct { + _ struct{} `type:"structure"` + + // The global table name. + // + // GlobalTableName is a required field + GlobalTableName *string `min:"3" type:"string" required:"true"` + + // A list of regions that should be added or removed from the global table. + // + // ReplicaUpdates is a required field + ReplicaUpdates []*ReplicaUpdate `type:"list" required:"true"` +} + +// String returns the string representation +func (s UpdateGlobalTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateGlobalTableInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UpdateGlobalTableInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UpdateGlobalTableInput"} + if s.GlobalTableName == nil { + invalidParams.Add(request.NewErrParamRequired("GlobalTableName")) + } + if s.GlobalTableName != nil && len(*s.GlobalTableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("GlobalTableName", 3)) + } + if s.ReplicaUpdates == nil { + invalidParams.Add(request.NewErrParamRequired("ReplicaUpdates")) + } + if s.ReplicaUpdates != nil { + for i, v := range s.ReplicaUpdates { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "ReplicaUpdates", i), err.(request.ErrInvalidParams)) + } + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetGlobalTableName sets the GlobalTableName field's value. +func (s *UpdateGlobalTableInput) SetGlobalTableName(v string) *UpdateGlobalTableInput { + s.GlobalTableName = &v + return s +} + +// SetReplicaUpdates sets the ReplicaUpdates field's value. +func (s *UpdateGlobalTableInput) SetReplicaUpdates(v []*ReplicaUpdate) *UpdateGlobalTableInput { + s.ReplicaUpdates = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateGlobalTableOutput +type UpdateGlobalTableOutput struct { + _ struct{} `type:"structure"` + + // Contains the details of the global table. + GlobalTableDescription *GlobalTableDescription `type:"structure"` +} + +// String returns the string representation +func (s UpdateGlobalTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateGlobalTableOutput) GoString() string { + return s.String() +} + +// SetGlobalTableDescription sets the GlobalTableDescription field's value. +func (s *UpdateGlobalTableOutput) SetGlobalTableDescription(v *GlobalTableDescription) *UpdateGlobalTableOutput { + s.GlobalTableDescription = v + return s +} + +// Represents the input of an UpdateItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateItemInput +type UpdateItemInput struct { + _ struct{} `type:"structure"` + + // This is a legacy parameter. Use UpdateExpression instead. For more information, + // see AttributeUpdates (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.AttributeUpdates.html) + // in the Amazon DynamoDB Developer Guide. + AttributeUpdates map[string]*AttributeValueUpdate `type:"map"` + + // A condition that must be satisfied in order for a conditional update to succeed. + // + // An expression can contain any of the following: + // + // * Functions: attribute_exists | attribute_not_exists | attribute_type + // | contains | begins_with | size + // + // These function names are case-sensitive. + // + // * Comparison operators: = | <> | < | > | <= | >= | BETWEEN | IN + // + // * Logical operators: AND | OR | NOT + // + // For more information on condition expressions, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ConditionExpression *string `type:"string"` + + // This is a legacy parameter. Use ConditionExpression instead. For more information, + // see ConditionalOperator (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ConditionalOperator.html) + // in the Amazon DynamoDB Developer Guide. + ConditionalOperator *string `type:"string" enum:"ConditionalOperator"` + + // This is a legacy parameter. Use ConditionExpression instead. For more information, + // see Expected (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.Expected.html) + // in the Amazon DynamoDB Developer Guide. + Expected map[string]*ExpectedAttributeValue `type:"map"` + + // One or more substitution tokens for attribute names in an expression. The + // following are some use cases for using ExpressionAttributeNames: + // + // * To access an attribute whose name conflicts with a DynamoDB reserved + // word. + // + // * To create a placeholder for repeating occurrences of an attribute name + // in an expression. + // + // * To prevent special characters in an attribute name from being misinterpreted + // in an expression. + // + // Use the # character in an expression to dereference an attribute name. For + // example, consider the following attribute name: + // + // * Percentile + // + // The name of this attribute conflicts with a reserved word, so it cannot be + // used directly in an expression. (For the complete list of reserved words, + // see Reserved Words (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + // in the Amazon DynamoDB Developer Guide). To work around this, you could specify + // the following for ExpressionAttributeNames: + // + // * {"#P":"Percentile"} + // + // You could then use this substitution in an expression, as in this example: + // + // * #P = :val + // + // Tokens that begin with the : character are expression attribute values, which + // are placeholders for the actual value at runtime. + // + // For more information on expression attribute names, see Accessing Item Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeNames map[string]*string `type:"map"` + + // One or more values that can be substituted in an expression. + // + // Use the : (colon) character in an expression to dereference an attribute + // value. For example, suppose that you wanted to check whether the value of + // the ProductStatus attribute was one of the following: + // + // Available | Backordered | Discontinued + // + // You would first need to specify ExpressionAttributeValues as follows: + // + // { ":avail":{"S":"Available"}, ":back":{"S":"Backordered"}, ":disc":{"S":"Discontinued"} + // } + // + // You could then use these values in an expression, such as this: + // + // ProductStatus IN (:avail, :back, :disc) + // + // For more information on expression attribute values, see Specifying Conditions + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) + // in the Amazon DynamoDB Developer Guide. + ExpressionAttributeValues map[string]*AttributeValue `type:"map"` + + // The primary key of the item to be updated. Each element consists of an attribute + // name and a value for that attribute. + // + // For the primary key, you must provide all of the attributes. For example, + // with a simple primary key, you only need to provide a value for the partition + // key. For a composite primary key, you must provide values for both the partition + // key and the sort key. + // + // Key is a required field + Key map[string]*AttributeValue `type:"map" required:"true"` + + // Determines the level of detail about provisioned throughput consumption that + // is returned in the response: + // + // * INDEXES - The response includes the aggregate ConsumedCapacity for the + // operation, together with ConsumedCapacity for each table and secondary + // index that was accessed. + // + // Note that some operations, such as GetItem and BatchGetItem, do not access + // any indexes at all. In these cases, specifying INDEXES will only return + // ConsumedCapacity information for table(s). + // + // * TOTAL - The response includes only the aggregate ConsumedCapacity for + // the operation. + // + // * NONE - No ConsumedCapacity details are included in the response. + ReturnConsumedCapacity *string `type:"string" enum:"ReturnConsumedCapacity"` + + // Determines whether item collection metrics are returned. If set to SIZE, + // the response includes statistics about item collections, if any, that were + // modified during the operation are returned in the response. If set to NONE + // (the default), no statistics are returned. + ReturnItemCollectionMetrics *string `type:"string" enum:"ReturnItemCollectionMetrics"` + + // Use ReturnValues if you want to get the item attributes as they appear before + // or after they are updated. For UpdateItem, the valid values are: + // + // * NONE - If ReturnValues is not specified, or if its value is NONE, then + // nothing is returned. (This setting is the default for ReturnValues.) + // + // * ALL_OLD - Returns all of the attributes of the item, as they appeared + // before the UpdateItem operation. + // + // * UPDATED_OLD - Returns only the updated attributes, as they appeared + // before the UpdateItem operation. + // + // * ALL_NEW - Returns all of the attributes of the item, as they appear + // after the UpdateItem operation. + // + // * UPDATED_NEW - Returns only the updated attributes, as they appear after + // the UpdateItem operation. + // + // There is no additional cost associated with requesting a return value aside + // from the small network and processing overhead of receiving a larger response. + // No read capacity units are consumed. + // + // The values returned are strongly consistent. + ReturnValues *string `type:"string" enum:"ReturnValue"` + + // The name of the table containing the item to update. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` + + // An expression that defines one or more attributes to be updated, the action + // to be performed on them, and new value(s) for them. + // + // The following action values are available for UpdateExpression. + // + // * SET - Adds one or more attributes and values to an item. If any of these + // attribute already exist, they are replaced by the new values. You can + // also use SET to add or subtract from an attribute that is of type Number. + // For example: SET myNum = myNum + :val + // + // SET supports the following functions: + // + // if_not_exists (path, operand) - if the item does not contain an attribute + // at the specified path, then if_not_exists evaluates to operand; otherwise, + // it evaluates to path. You can use this function to avoid overwriting an + // attribute that may already be present in the item. + // + // list_append (operand, operand) - evaluates to a list with a new element added + // to it. You can append the new element to the start or the end of the list + // by reversing the order of the operands. + // + // These function names are case-sensitive. + // + // * REMOVE - Removes one or more attributes from an item. + // + // * ADD - Adds the specified value to the item, if the attribute does not + // already exist. If the attribute does exist, then the behavior of ADD depends + // on the data type of the attribute: + // + // If the existing attribute is a number, and if Value is also a number, then + // Value is mathematically added to the existing attribute. If Value is a + // negative number, then it is subtracted from the existing attribute. + // + // If you use ADD to increment or decrement a number value for an item that + // doesn't exist before the update, DynamoDB uses 0 as the initial value. + // + // Similarly, if you use ADD for an existing item to increment or decrement + // an attribute value that doesn't exist before the update, DynamoDB uses + // 0 as the initial value. For example, suppose that the item you want to + // update doesn't have an attribute named itemcount, but you decide to ADD + // the number 3 to this attribute anyway. DynamoDB will create the itemcount + // attribute, set its initial value to 0, and finally add 3 to it. The result + // will be a new itemcount attribute in the item, with a value of 3. + // + // If the existing data type is a set and if Value is also a set, then Value + // is added to the existing set. For example, if the attribute value is the + // set [1,2], and the ADD action specified [3], then the final attribute + // value is [1,2,3]. An error occurs if an ADD action is specified for a + // set attribute and the attribute type specified does not match the existing + // set type. + // + // Both sets must have the same primitive data type. For example, if the existing + // data type is a set of strings, the Value must also be a set of strings. + // + // The ADD action only supports Number and set data types. In addition, ADD + // can only be used on top-level attributes, not nested attributes. + // + // * DELETE - Deletes an element from a set. + // + // If a set of values is specified, then those values are subtracted from the + // old set. For example, if the attribute value was the set [a,b,c] and the + // DELETE action specifies [a,c], then the final attribute value is [b]. + // Specifying an empty set is an error. + // + // The DELETE action only supports set data types. In addition, DELETE can only + // be used on top-level attributes, not nested attributes. + // + // You can have many actions in a single expression, such as the following: + // SET a=:value1, b=:value2 DELETE :value3, :value4, :value5 + // + // For more information on update expressions, see Modifying Items and Attributes + // (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Modifying.html) + // in the Amazon DynamoDB Developer Guide. + UpdateExpression *string `type:"string"` +} + +// String returns the string representation +func (s UpdateItemInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateItemInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UpdateItemInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UpdateItemInput"} + if s.Key == nil { + invalidParams.Add(request.NewErrParamRequired("Key")) + } + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributeUpdates sets the AttributeUpdates field's value. +func (s *UpdateItemInput) SetAttributeUpdates(v map[string]*AttributeValueUpdate) *UpdateItemInput { + s.AttributeUpdates = v + return s +} + +// SetConditionExpression sets the ConditionExpression field's value. +func (s *UpdateItemInput) SetConditionExpression(v string) *UpdateItemInput { + s.ConditionExpression = &v + return s +} + +// SetConditionalOperator sets the ConditionalOperator field's value. +func (s *UpdateItemInput) SetConditionalOperator(v string) *UpdateItemInput { + s.ConditionalOperator = &v + return s +} + +// SetExpected sets the Expected field's value. +func (s *UpdateItemInput) SetExpected(v map[string]*ExpectedAttributeValue) *UpdateItemInput { + s.Expected = v + return s +} + +// SetExpressionAttributeNames sets the ExpressionAttributeNames field's value. +func (s *UpdateItemInput) SetExpressionAttributeNames(v map[string]*string) *UpdateItemInput { + s.ExpressionAttributeNames = v + return s +} + +// SetExpressionAttributeValues sets the ExpressionAttributeValues field's value. +func (s *UpdateItemInput) SetExpressionAttributeValues(v map[string]*AttributeValue) *UpdateItemInput { + s.ExpressionAttributeValues = v + return s +} + +// SetKey sets the Key field's value. +func (s *UpdateItemInput) SetKey(v map[string]*AttributeValue) *UpdateItemInput { + s.Key = v + return s +} + +// SetReturnConsumedCapacity sets the ReturnConsumedCapacity field's value. +func (s *UpdateItemInput) SetReturnConsumedCapacity(v string) *UpdateItemInput { + s.ReturnConsumedCapacity = &v + return s +} + +// SetReturnItemCollectionMetrics sets the ReturnItemCollectionMetrics field's value. +func (s *UpdateItemInput) SetReturnItemCollectionMetrics(v string) *UpdateItemInput { + s.ReturnItemCollectionMetrics = &v + return s +} + +// SetReturnValues sets the ReturnValues field's value. +func (s *UpdateItemInput) SetReturnValues(v string) *UpdateItemInput { + s.ReturnValues = &v + return s +} + +// SetTableName sets the TableName field's value. +func (s *UpdateItemInput) SetTableName(v string) *UpdateItemInput { + s.TableName = &v + return s +} + +// SetUpdateExpression sets the UpdateExpression field's value. +func (s *UpdateItemInput) SetUpdateExpression(v string) *UpdateItemInput { + s.UpdateExpression = &v + return s +} + +// Represents the output of an UpdateItem operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateItemOutput +type UpdateItemOutput struct { + _ struct{} `type:"structure"` + + // A map of attribute values as they appear before or after the UpdateItem operation, + // as determined by the ReturnValues parameter. + // + // The Attributes map is only present if ReturnValues was specified as something + // other than NONE in the request. Each element represents one attribute. + Attributes map[string]*AttributeValue `type:"map"` + + // The capacity units consumed by the UpdateItem operation. The data returned + // includes the total provisioned throughput consumed, along with statistics + // for the table and any indexes involved in the operation. ConsumedCapacity + // is only returned if the ReturnConsumedCapacity parameter was specified. For + // more information, see Provisioned Throughput (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughputIntro.html) + // in the Amazon DynamoDB Developer Guide. + ConsumedCapacity *ConsumedCapacity `type:"structure"` + + // Information about item collections, if any, that were affected by the UpdateItem + // operation. ItemCollectionMetrics is only returned if the ReturnItemCollectionMetrics + // parameter was specified. If the table does not have any local secondary indexes, + // this information is not returned in the response. + // + // Each ItemCollectionMetrics element consists of: + // + // * ItemCollectionKey - The partition key value of the item collection. + // This is the same as the partition key value of the item itself. + // + // * SizeEstimateRangeGB - An estimate of item collection size, in gigabytes. + // This value is a two-element array containing a lower bound and an upper + // bound for the estimate. The estimate includes the size of all the items + // in the table, plus the size of all attributes projected into all of the + // local secondary indexes on that table. Use this estimate to measure whether + // a local secondary index is approaching its size limit. + // + // The estimate is subject to change over time; therefore, do not rely on the + // precision or accuracy of the estimate. + ItemCollectionMetrics *ItemCollectionMetrics `type:"structure"` +} + +// String returns the string representation +func (s UpdateItemOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateItemOutput) GoString() string { + return s.String() +} + +// SetAttributes sets the Attributes field's value. +func (s *UpdateItemOutput) SetAttributes(v map[string]*AttributeValue) *UpdateItemOutput { + s.Attributes = v + return s +} + +// SetConsumedCapacity sets the ConsumedCapacity field's value. +func (s *UpdateItemOutput) SetConsumedCapacity(v *ConsumedCapacity) *UpdateItemOutput { + s.ConsumedCapacity = v + return s +} + +// SetItemCollectionMetrics sets the ItemCollectionMetrics field's value. +func (s *UpdateItemOutput) SetItemCollectionMetrics(v *ItemCollectionMetrics) *UpdateItemOutput { + s.ItemCollectionMetrics = v + return s +} + +// Represents the input of an UpdateTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTableInput +type UpdateTableInput struct { + _ struct{} `type:"structure"` + + // An array of attributes that describe the key schema for the table and indexes. + // If you are adding a new global secondary index to the table, AttributeDefinitions + // must include the key element(s) of the new index. + AttributeDefinitions []*AttributeDefinition `type:"list"` + + // An array of one or more global secondary indexes for the table. For each + // index in the array, you can request one action: + // + // * Create - add a new global secondary index to the table. + // + // * Update - modify the provisioned throughput settings of an existing global + // secondary index. + // + // * Delete - remove a global secondary index from the table. + // + // For more information, see Managing Global Secondary Indexes (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.OnlineOps.html) + // in the Amazon DynamoDB Developer Guide. + GlobalSecondaryIndexUpdates []*GlobalSecondaryIndexUpdate `type:"list"` + + // The new provisioned throughput settings for the specified table or index. + ProvisionedThroughput *ProvisionedThroughput `type:"structure"` + + // Represents the DynamoDB Streams configuration for the table. + // + // You will receive a ResourceInUseException if you attempt to enable a stream + // on a table that already has a stream, or if you attempt to disable a stream + // on a table which does not have a stream. + StreamSpecification *StreamSpecification `type:"structure"` + + // The name of the table to be updated. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` +} + +// String returns the string representation +func (s UpdateTableInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateTableInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UpdateTableInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UpdateTableInput"} + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + if s.AttributeDefinitions != nil { + for i, v := range s.AttributeDefinitions { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "AttributeDefinitions", i), err.(request.ErrInvalidParams)) + } + } + } + if s.GlobalSecondaryIndexUpdates != nil { + for i, v := range s.GlobalSecondaryIndexUpdates { + if v == nil { + continue + } + if err := v.Validate(); err != nil { + invalidParams.AddNested(fmt.Sprintf("%s[%v]", "GlobalSecondaryIndexUpdates", i), err.(request.ErrInvalidParams)) + } + } + } + if s.ProvisionedThroughput != nil { + if err := s.ProvisionedThroughput.Validate(); err != nil { + invalidParams.AddNested("ProvisionedThroughput", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetAttributeDefinitions sets the AttributeDefinitions field's value. +func (s *UpdateTableInput) SetAttributeDefinitions(v []*AttributeDefinition) *UpdateTableInput { + s.AttributeDefinitions = v + return s +} + +// SetGlobalSecondaryIndexUpdates sets the GlobalSecondaryIndexUpdates field's value. +func (s *UpdateTableInput) SetGlobalSecondaryIndexUpdates(v []*GlobalSecondaryIndexUpdate) *UpdateTableInput { + s.GlobalSecondaryIndexUpdates = v + return s +} + +// SetProvisionedThroughput sets the ProvisionedThroughput field's value. +func (s *UpdateTableInput) SetProvisionedThroughput(v *ProvisionedThroughput) *UpdateTableInput { + s.ProvisionedThroughput = v + return s +} + +// SetStreamSpecification sets the StreamSpecification field's value. +func (s *UpdateTableInput) SetStreamSpecification(v *StreamSpecification) *UpdateTableInput { + s.StreamSpecification = v + return s +} + +// SetTableName sets the TableName field's value. +func (s *UpdateTableInput) SetTableName(v string) *UpdateTableInput { + s.TableName = &v + return s +} + +// Represents the output of an UpdateTable operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTableOutput +type UpdateTableOutput struct { + _ struct{} `type:"structure"` + + // Represents the properties of the table. + TableDescription *TableDescription `type:"structure"` +} + +// String returns the string representation +func (s UpdateTableOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateTableOutput) GoString() string { + return s.String() +} + +// SetTableDescription sets the TableDescription field's value. +func (s *UpdateTableOutput) SetTableDescription(v *TableDescription) *UpdateTableOutput { + s.TableDescription = v + return s +} + +// Represents the input of an UpdateTimeToLive operation. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTimeToLiveInput +type UpdateTimeToLiveInput struct { + _ struct{} `type:"structure"` + + // The name of the table to be configured. + // + // TableName is a required field + TableName *string `min:"3" type:"string" required:"true"` + + // Represents the settings used to enable or disable Time to Live for the specified + // table. + // + // TimeToLiveSpecification is a required field + TimeToLiveSpecification *TimeToLiveSpecification `type:"structure" required:"true"` +} + +// String returns the string representation +func (s UpdateTimeToLiveInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateTimeToLiveInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *UpdateTimeToLiveInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "UpdateTimeToLiveInput"} + if s.TableName == nil { + invalidParams.Add(request.NewErrParamRequired("TableName")) + } + if s.TableName != nil && len(*s.TableName) < 3 { + invalidParams.Add(request.NewErrParamMinLen("TableName", 3)) + } + if s.TimeToLiveSpecification == nil { + invalidParams.Add(request.NewErrParamRequired("TimeToLiveSpecification")) + } + if s.TimeToLiveSpecification != nil { + if err := s.TimeToLiveSpecification.Validate(); err != nil { + invalidParams.AddNested("TimeToLiveSpecification", err.(request.ErrInvalidParams)) + } + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetTableName sets the TableName field's value. +func (s *UpdateTimeToLiveInput) SetTableName(v string) *UpdateTimeToLiveInput { + s.TableName = &v + return s +} + +// SetTimeToLiveSpecification sets the TimeToLiveSpecification field's value. +func (s *UpdateTimeToLiveInput) SetTimeToLiveSpecification(v *TimeToLiveSpecification) *UpdateTimeToLiveInput { + s.TimeToLiveSpecification = v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/UpdateTimeToLiveOutput +type UpdateTimeToLiveOutput struct { + _ struct{} `type:"structure"` + + // Represents the output of an UpdateTimeToLive operation. + TimeToLiveSpecification *TimeToLiveSpecification `type:"structure"` +} + +// String returns the string representation +func (s UpdateTimeToLiveOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s UpdateTimeToLiveOutput) GoString() string { + return s.String() +} + +// SetTimeToLiveSpecification sets the TimeToLiveSpecification field's value. +func (s *UpdateTimeToLiveOutput) SetTimeToLiveSpecification(v *TimeToLiveSpecification) *UpdateTimeToLiveOutput { + s.TimeToLiveSpecification = v + return s +} + +// Represents an operation to perform - either DeleteItem or PutItem. You can +// only request one of these operations, not both, in a single WriteRequest. +// If you do need to perform both of these operations, you will need to provide +// two separate WriteRequest objects. +// See also, https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10/WriteRequest +type WriteRequest struct { + _ struct{} `type:"structure"` + + // A request to perform a DeleteItem operation. + DeleteRequest *DeleteRequest `type:"structure"` + + // A request to perform a PutItem operation. + PutRequest *PutRequest `type:"structure"` +} + +// String returns the string representation +func (s WriteRequest) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s WriteRequest) GoString() string { + return s.String() +} + +// SetDeleteRequest sets the DeleteRequest field's value. +func (s *WriteRequest) SetDeleteRequest(v *DeleteRequest) *WriteRequest { + s.DeleteRequest = v + return s +} + +// SetPutRequest sets the PutRequest field's value. +func (s *WriteRequest) SetPutRequest(v *PutRequest) *WriteRequest { + s.PutRequest = v + return s +} + +const ( + // AttributeActionAdd is a AttributeAction enum value + AttributeActionAdd = "ADD" + + // AttributeActionPut is a AttributeAction enum value + AttributeActionPut = "PUT" + + // AttributeActionDelete is a AttributeAction enum value + AttributeActionDelete = "DELETE" +) + +const ( + // BackupStatusCreating is a BackupStatus enum value + BackupStatusCreating = "CREATING" + + // BackupStatusDeleted is a BackupStatus enum value + BackupStatusDeleted = "DELETED" + + // BackupStatusAvailable is a BackupStatus enum value + BackupStatusAvailable = "AVAILABLE" +) + +const ( + // ComparisonOperatorEq is a ComparisonOperator enum value + ComparisonOperatorEq = "EQ" + + // ComparisonOperatorNe is a ComparisonOperator enum value + ComparisonOperatorNe = "NE" + + // ComparisonOperatorIn is a ComparisonOperator enum value + ComparisonOperatorIn = "IN" + + // ComparisonOperatorLe is a ComparisonOperator enum value + ComparisonOperatorLe = "LE" + + // ComparisonOperatorLt is a ComparisonOperator enum value + ComparisonOperatorLt = "LT" + + // ComparisonOperatorGe is a ComparisonOperator enum value + ComparisonOperatorGe = "GE" + + // ComparisonOperatorGt is a ComparisonOperator enum value + ComparisonOperatorGt = "GT" + + // ComparisonOperatorBetween is a ComparisonOperator enum value + ComparisonOperatorBetween = "BETWEEN" + + // ComparisonOperatorNotNull is a ComparisonOperator enum value + ComparisonOperatorNotNull = "NOT_NULL" + + // ComparisonOperatorNull is a ComparisonOperator enum value + ComparisonOperatorNull = "NULL" + + // ComparisonOperatorContains is a ComparisonOperator enum value + ComparisonOperatorContains = "CONTAINS" + + // ComparisonOperatorNotContains is a ComparisonOperator enum value + ComparisonOperatorNotContains = "NOT_CONTAINS" + + // ComparisonOperatorBeginsWith is a ComparisonOperator enum value + ComparisonOperatorBeginsWith = "BEGINS_WITH" +) + +const ( + // ConditionalOperatorAnd is a ConditionalOperator enum value + ConditionalOperatorAnd = "AND" + + // ConditionalOperatorOr is a ConditionalOperator enum value + ConditionalOperatorOr = "OR" +) + +const ( + // ContinuousBackupsStatusEnabled is a ContinuousBackupsStatus enum value + ContinuousBackupsStatusEnabled = "ENABLED" + + // ContinuousBackupsStatusDisabled is a ContinuousBackupsStatus enum value + ContinuousBackupsStatusDisabled = "DISABLED" +) + +const ( + // GlobalTableStatusCreating is a GlobalTableStatus enum value + GlobalTableStatusCreating = "CREATING" + + // GlobalTableStatusActive is a GlobalTableStatus enum value + GlobalTableStatusActive = "ACTIVE" + + // GlobalTableStatusDeleting is a GlobalTableStatus enum value + GlobalTableStatusDeleting = "DELETING" + + // GlobalTableStatusUpdating is a GlobalTableStatus enum value + GlobalTableStatusUpdating = "UPDATING" +) + +const ( + // IndexStatusCreating is a IndexStatus enum value + IndexStatusCreating = "CREATING" + + // IndexStatusUpdating is a IndexStatus enum value + IndexStatusUpdating = "UPDATING" + + // IndexStatusDeleting is a IndexStatus enum value + IndexStatusDeleting = "DELETING" + + // IndexStatusActive is a IndexStatus enum value + IndexStatusActive = "ACTIVE" +) + +const ( + // KeyTypeHash is a KeyType enum value + KeyTypeHash = "HASH" + + // KeyTypeRange is a KeyType enum value + KeyTypeRange = "RANGE" +) + +const ( + // ProjectionTypeAll is a ProjectionType enum value + ProjectionTypeAll = "ALL" + + // ProjectionTypeKeysOnly is a ProjectionType enum value + ProjectionTypeKeysOnly = "KEYS_ONLY" + + // ProjectionTypeInclude is a ProjectionType enum value + ProjectionTypeInclude = "INCLUDE" +) + +// Determines the level of detail about provisioned throughput consumption that +// is returned in the response: +// +// * INDEXES - The response includes the aggregate ConsumedCapacity for the +// operation, together with ConsumedCapacity for each table and secondary +// index that was accessed. +// +// Note that some operations, such as GetItem and BatchGetItem, do not access +// any indexes at all. In these cases, specifying INDEXES will only return +// ConsumedCapacity information for table(s). +// +// * TOTAL - The response includes only the aggregate ConsumedCapacity for +// the operation. +// +// * NONE - No ConsumedCapacity details are included in the response. +const ( + // ReturnConsumedCapacityIndexes is a ReturnConsumedCapacity enum value + ReturnConsumedCapacityIndexes = "INDEXES" + + // ReturnConsumedCapacityTotal is a ReturnConsumedCapacity enum value + ReturnConsumedCapacityTotal = "TOTAL" + + // ReturnConsumedCapacityNone is a ReturnConsumedCapacity enum value + ReturnConsumedCapacityNone = "NONE" +) + +const ( + // ReturnItemCollectionMetricsSize is a ReturnItemCollectionMetrics enum value + ReturnItemCollectionMetricsSize = "SIZE" + + // ReturnItemCollectionMetricsNone is a ReturnItemCollectionMetrics enum value + ReturnItemCollectionMetricsNone = "NONE" +) + +const ( + // ReturnValueNone is a ReturnValue enum value + ReturnValueNone = "NONE" + + // ReturnValueAllOld is a ReturnValue enum value + ReturnValueAllOld = "ALL_OLD" + + // ReturnValueUpdatedOld is a ReturnValue enum value + ReturnValueUpdatedOld = "UPDATED_OLD" + + // ReturnValueAllNew is a ReturnValue enum value + ReturnValueAllNew = "ALL_NEW" + + // ReturnValueUpdatedNew is a ReturnValue enum value + ReturnValueUpdatedNew = "UPDATED_NEW" +) + +const ( + // ScalarAttributeTypeS is a ScalarAttributeType enum value + ScalarAttributeTypeS = "S" + + // ScalarAttributeTypeN is a ScalarAttributeType enum value + ScalarAttributeTypeN = "N" + + // ScalarAttributeTypeB is a ScalarAttributeType enum value + ScalarAttributeTypeB = "B" +) + +const ( + // SelectAllAttributes is a Select enum value + SelectAllAttributes = "ALL_ATTRIBUTES" + + // SelectAllProjectedAttributes is a Select enum value + SelectAllProjectedAttributes = "ALL_PROJECTED_ATTRIBUTES" + + // SelectSpecificAttributes is a Select enum value + SelectSpecificAttributes = "SPECIFIC_ATTRIBUTES" + + // SelectCount is a Select enum value + SelectCount = "COUNT" +) + +const ( + // StreamViewTypeNewImage is a StreamViewType enum value + StreamViewTypeNewImage = "NEW_IMAGE" + + // StreamViewTypeOldImage is a StreamViewType enum value + StreamViewTypeOldImage = "OLD_IMAGE" + + // StreamViewTypeNewAndOldImages is a StreamViewType enum value + StreamViewTypeNewAndOldImages = "NEW_AND_OLD_IMAGES" + + // StreamViewTypeKeysOnly is a StreamViewType enum value + StreamViewTypeKeysOnly = "KEYS_ONLY" +) + +const ( + // TableStatusCreating is a TableStatus enum value + TableStatusCreating = "CREATING" + + // TableStatusUpdating is a TableStatus enum value + TableStatusUpdating = "UPDATING" + + // TableStatusDeleting is a TableStatus enum value + TableStatusDeleting = "DELETING" + + // TableStatusActive is a TableStatus enum value + TableStatusActive = "ACTIVE" +) + +const ( + // TimeToLiveStatusEnabling is a TimeToLiveStatus enum value + TimeToLiveStatusEnabling = "ENABLING" + + // TimeToLiveStatusDisabling is a TimeToLiveStatus enum value + TimeToLiveStatusDisabling = "DISABLING" + + // TimeToLiveStatusEnabled is a TimeToLiveStatus enum value + TimeToLiveStatusEnabled = "ENABLED" + + // TimeToLiveStatusDisabled is a TimeToLiveStatus enum value + TimeToLiveStatusDisabled = "DISABLED" +) diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations.go new file mode 100644 index 0000000..333e61b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations.go @@ -0,0 +1,109 @@ +package dynamodb + +import ( + "bytes" + "hash/crc32" + "io" + "io/ioutil" + "math" + "strconv" + "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/request" +) + +type retryer struct { + client.DefaultRetryer +} + +func (d retryer) RetryRules(r *request.Request) time.Duration { + delay := time.Duration(math.Pow(2, float64(r.RetryCount))) * 50 + return delay * time.Millisecond +} + +func init() { + initClient = func(c *client.Client) { + if c.Config.Retryer == nil { + // Only override the retryer with a custom one if the config + // does not already contain a retryer + setCustomRetryer(c) + } + + c.Handlers.Build.PushBack(disableCompression) + c.Handlers.Unmarshal.PushFront(validateCRC32) + } +} + +func setCustomRetryer(c *client.Client) { + maxRetries := aws.IntValue(c.Config.MaxRetries) + if c.Config.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries { + maxRetries = 10 + } + + c.Retryer = retryer{ + DefaultRetryer: client.DefaultRetryer{ + NumMaxRetries: maxRetries, + }, + } +} + +func drainBody(b io.ReadCloser, length int64) (out *bytes.Buffer, err error) { + if length < 0 { + length = 0 + } + buf := bytes.NewBuffer(make([]byte, 0, length)) + + if _, err = buf.ReadFrom(b); err != nil { + return nil, err + } + if err = b.Close(); err != nil { + return nil, err + } + return buf, nil +} + +func disableCompression(r *request.Request) { + r.HTTPRequest.Header.Set("Accept-Encoding", "identity") +} + +func validateCRC32(r *request.Request) { + if r.Error != nil { + return // already have an error, no need to verify CRC + } + + // Checksum validation is off, skip + if aws.BoolValue(r.Config.DisableComputeChecksums) { + return + } + + // Try to get CRC from response + header := r.HTTPResponse.Header.Get("X-Amz-Crc32") + if header == "" { + return // No header, skip + } + + expected, err := strconv.ParseUint(header, 10, 32) + if err != nil { + return // Could not determine CRC value, skip + } + + buf, err := drainBody(r.HTTPResponse.Body, r.HTTPResponse.ContentLength) + if err != nil { // failed to read the response body, skip + return + } + + // Reset body for subsequent reads + r.HTTPResponse.Body = ioutil.NopCloser(bytes.NewReader(buf.Bytes())) + + // Compute the CRC checksum + crc := crc32.ChecksumIEEE(buf.Bytes()) + + if crc != uint32(expected) { + // CRC does not match, set a retryable error + r.Retryable = aws.Bool(true) + r.Error = awserr.New("CRC32CheckFailed", "CRC32 integrity check failed", nil) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations_test.go new file mode 100644 index 0000000..0247d56 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/customizations_test.go @@ -0,0 +1,153 @@ +package dynamodb_test + +import ( + "bytes" + "io/ioutil" + "net/http" + "os" + "testing" + + "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/request" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +var db *dynamodb.DynamoDB + +func TestMain(m *testing.M) { + db = dynamodb.New(unit.Session, &aws.Config{ + MaxRetries: aws.Int(2), + }) + db.Handlers.Send.Clear() // mock sending + + os.Exit(m.Run()) +} + +func mockCRCResponse(svc *dynamodb.DynamoDB, status int, body, crc string) (req *request.Request) { + header := http.Header{} + header.Set("x-amz-crc32", crc) + + req, _ = svc.ListTablesRequest(nil) + req.Handlers.Send.PushBack(func(*request.Request) { + req.HTTPResponse = &http.Response{ + ContentLength: int64(len(body)), + StatusCode: status, + Body: ioutil.NopCloser(bytes.NewReader([]byte(body))), + Header: header, + } + }) + req.Send() + return +} + +func TestDefaultRetryRules(t *testing.T) { + d := dynamodb.New(unit.Session, &aws.Config{MaxRetries: aws.Int(-1)}) + if e, a := 10, d.MaxRetries(); e != a { + t.Errorf("expect %d max retries, got %d", e, a) + } +} + +func TestCustomRetryRules(t *testing.T) { + d := dynamodb.New(unit.Session, &aws.Config{MaxRetries: aws.Int(2)}) + if e, a := 2, d.MaxRetries(); e != a { + t.Errorf("expect %d max retries, got %d", e, a) + } +} + +type testCustomRetryer struct { + client.DefaultRetryer +} + +func TestCustomRetry_FromConfig(t *testing.T) { + d := dynamodb.New(unit.Session, &aws.Config{ + Retryer: testCustomRetryer{client.DefaultRetryer{NumMaxRetries: 9}}, + }) + + if _, ok := d.Retryer.(testCustomRetryer); !ok { + t.Errorf("expect retryer to be testCustomRetryer, but got %T", d.Retryer) + } + + if e, a := 9, d.MaxRetries(); e != a { + t.Errorf("expect %d max retries from custom retryer, got %d", e, a) + } +} + +func TestValidateCRC32NoHeaderSkip(t *testing.T) { + req := mockCRCResponse(db, 200, "{}", "") + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } +} + +func TestValidateCRC32InvalidHeaderSkip(t *testing.T) { + req := mockCRCResponse(db, 200, "{}", "ABC") + if req.Error != nil { + t.Errorf("expect no error, got %v", req.Error) + } +} + +func TestValidateCRC32AlreadyErrorSkip(t *testing.T) { + req := mockCRCResponse(db, 400, "{}", "1234") + if req.Error == nil { + t.Fatalf("expect error, but got none") + } + + aerr := req.Error.(awserr.Error) + if aerr.Code() == "CRC32CheckFailed" { + t.Errorf("expect error code not to be CRC32CheckFailed") + } +} + +func TestValidateCRC32IsValid(t *testing.T) { + req := mockCRCResponse(db, 200, `{"TableNames":["A"]}`, "3090163698") + if req.Error != nil { + t.Fatalf("expect no error, got %v", req.Error) + } + + // CRC check does not affect output parsing + out := req.Data.(*dynamodb.ListTablesOutput) + if e, a := "A", *out.TableNames[0]; e != a { + t.Errorf("expect %q table name, got %q", e, a) + } +} + +func TestValidateCRC32DoesNotMatch(t *testing.T) { + req := mockCRCResponse(db, 200, "{}", "1234") + if req.Error == nil { + t.Fatalf("expect error, but got none") + } + + aerr := req.Error.(awserr.Error) + if e, a := "CRC32CheckFailed", aerr.Code(); e != a { + t.Errorf("expect %s error code, got %s", e, a) + } + if e, a := 2, req.RetryCount; e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } +} + +func TestValidateCRC32DoesNotMatchNoComputeChecksum(t *testing.T) { + svc := dynamodb.New(unit.Session, &aws.Config{ + MaxRetries: aws.Int(2), + DisableComputeChecksums: aws.Bool(true), + }) + svc.Handlers.Send.Clear() // mock sending + + req := mockCRCResponse(svc, 200, `{"TableNames":["A"]}`, "1234") + if req.Error != nil { + t.Fatalf("expect no error, got %v", req.Error) + } + + if e, a := 0, req.RetryCount; e != a { + t.Errorf("expect %d retry count, got %d", e, a) + } + + // CRC check disabled. Does not affect output parsing + out := req.Data.(*dynamodb.ListTablesOutput) + if e, a := "A", *out.TableNames[0]; e != a { + t.Errorf("expect %q table name, got %q", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc.go new file mode 100644 index 0000000..f244a73 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc.go @@ -0,0 +1,45 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +// Package dynamodb provides the client and types for making API +// requests to Amazon DynamoDB. +// +// Amazon DynamoDB is a fully managed NoSQL database service that provides fast +// and predictable performance with seamless scalability. DynamoDB lets you +// offload the administrative burdens of operating and scaling a distributed +// database, so that you don't have to worry about hardware provisioning, setup +// and configuration, replication, software patching, or cluster scaling. +// +// With DynamoDB, you can create database tables that can store and retrieve +// any amount of data, and serve any level of request traffic. You can scale +// up or scale down your tables' throughput capacity without downtime or performance +// degradation, and use the AWS Management Console to monitor resource utilization +// and performance metrics. +// +// DynamoDB automatically spreads the data and traffic for your tables over +// a sufficient number of servers to handle your throughput and storage requirements, +// while maintaining consistent and fast performance. All of your data is stored +// on solid state disks (SSDs) and automatically replicated across multiple +// Availability Zones in an AWS region, providing built-in high availability +// and data durability. +// +// See https://docs.aws.amazon.com/goto/WebAPI/dynamodb-2012-08-10 for more information on this service. +// +// See dynamodb package documentation for more information. +// https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/ +// +// Using the Client +// +// To contact Amazon DynamoDB with the SDK use the New function to create +// a new service client. With that client you can make API requests to the service. +// These clients are safe to use concurrently. +// +// See the SDK's documentation for more information on how to use the SDK. +// https://docs.aws.amazon.com/sdk-for-go/api/ +// +// See aws.Config documentation for more information on configuring SDK clients. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config +// +// See the Amazon DynamoDB client DynamoDB for more +// information on creating client for this service. +// https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/#New +package dynamodb diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc_custom.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc_custom.go new file mode 100644 index 0000000..5ebc580 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/doc_custom.go @@ -0,0 +1,27 @@ +/* +AttributeValue Marshaling and Unmarshaling Helpers + +Utility helpers to marshal and unmarshal AttributeValue to and +from Go types can be found in the dynamodbattribute sub package. This package +provides has specialized functions for the common ways of working with +AttributeValues. Such as map[string]*AttributeValue, []*AttributeValue, and +directly with *AttributeValue. This is helpful for marshaling Go types for API +operations such as PutItem, and unmarshaling Query and Scan APIs' responses. + +See the dynamodbattribute package documentation for more information. +https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/ + +Expression Builders + +The expression package provides utility types and functions to build DynamoDB +expression for type safe construction of API ExpressionAttributeNames, and +ExpressionAttribute Values. + +The package represents the various DynamoDB Expressions as structs named +accordingly. For example, ConditionBuilder represents a DynamoDB Condition +Expression, an UpdateBuilder represents a DynamoDB Update Expression, and so on. + +See the expression package documentation for more information. +https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/expression/ +*/ +package dynamodb diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter.go new file mode 100644 index 0000000..e38e41d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter.go @@ -0,0 +1,443 @@ +package dynamodbattribute + +import ( + "bytes" + "encoding/json" + "fmt" + "reflect" + "runtime" + "strconv" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +// ConvertToMap accepts a map[string]interface{} or struct and converts it to a +// map[string]*dynamodb.AttributeValue. +// +// If in contains any structs, it is first JSON encoded/decoded it to convert it +// to a map[string]interface{}, so `json` struct tags are respected. +// +// Deprecated: Use MarshalMap instead +func ConvertToMap(in interface{}) (item map[string]*dynamodb.AttributeValue, err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(runtime.Error); ok { + err = e + } else if s, ok := r.(string); ok { + err = fmt.Errorf(s) + } else { + err = r.(error) + } + item = nil + } + }() + + if in == nil { + return nil, awserr.New("SerializationError", + "in must be a map[string]interface{} or struct, got ", nil) + } + + v := reflect.ValueOf(in) + if v.Kind() != reflect.Struct && !(v.Kind() == reflect.Map && v.Type().Key().Kind() == reflect.String) { + return nil, awserr.New("SerializationError", + fmt.Sprintf("in must be a map[string]interface{} or struct, got %s", + v.Type().String()), + nil) + } + + if isTyped(reflect.TypeOf(in)) { + var out map[string]interface{} + in = convertToUntyped(in, out) + } + + item = make(map[string]*dynamodb.AttributeValue) + for k, v := range in.(map[string]interface{}) { + item[k] = convertTo(v) + } + + return item, nil +} + +// ConvertFromMap accepts a map[string]*dynamodb.AttributeValue and converts it to a +// map[string]interface{} or struct. +// +// If v points to a struct, the result is first converted it to a +// map[string]interface{}, then JSON encoded/decoded it to convert to a struct, +// so `json` struct tags are respected. +// +// Deprecated: Use UnmarshalMap instead +func ConvertFromMap(item map[string]*dynamodb.AttributeValue, v interface{}) (err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(runtime.Error); ok { + err = e + } else if s, ok := r.(string); ok { + err = fmt.Errorf(s) + } else { + err = r.(error) + } + item = nil + } + }() + + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return awserr.New("SerializationError", + fmt.Sprintf("v must be a non-nil pointer to a map[string]interface{} or struct, got %s", + rv.Type()), + nil) + } + if rv.Elem().Kind() != reflect.Struct && !(rv.Elem().Kind() == reflect.Map && rv.Elem().Type().Key().Kind() == reflect.String) { + return awserr.New("SerializationError", + fmt.Sprintf("v must be a non-nil pointer to a map[string]interface{} or struct, got %s", + rv.Type()), + nil) + } + + m := make(map[string]interface{}) + for k, v := range item { + m[k] = convertFrom(v) + } + + if isTyped(reflect.TypeOf(v)) { + err = convertToTyped(m, v) + } else { + rv.Elem().Set(reflect.ValueOf(m)) + } + + return err +} + +// ConvertToList accepts an array or slice and converts it to a +// []*dynamodb.AttributeValue. +// +// Converting []byte fields to dynamodb.AttributeValue are only currently supported +// if the input is a map[string]interface{} type. []byte within typed structs are not +// converted correctly and are converted into base64 strings. This is a known bug, +// and will be fixed in a later release. +// +// If in contains any structs, it is first JSON encoded/decoded it to convert it +// to a []interface{}, so `json` struct tags are respected. +// +// Deprecated: Use MarshalList instead +func ConvertToList(in interface{}) (item []*dynamodb.AttributeValue, err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(runtime.Error); ok { + err = e + } else if s, ok := r.(string); ok { + err = fmt.Errorf(s) + } else { + err = r.(error) + } + item = nil + } + }() + + if in == nil { + return nil, awserr.New("SerializationError", + "in must be an array or slice, got ", + nil) + } + + v := reflect.ValueOf(in) + if v.Kind() != reflect.Array && v.Kind() != reflect.Slice { + return nil, awserr.New("SerializationError", + fmt.Sprintf("in must be an array or slice, got %s", + v.Type().String()), + nil) + } + + if isTyped(reflect.TypeOf(in)) { + var out []interface{} + in = convertToUntyped(in, out) + } + + item = make([]*dynamodb.AttributeValue, 0, len(in.([]interface{}))) + for _, v := range in.([]interface{}) { + item = append(item, convertTo(v)) + } + + return item, nil +} + +// ConvertFromList accepts a []*dynamodb.AttributeValue and converts it to an array or +// slice. +// +// If v contains any structs, the result is first converted it to a +// []interface{}, then JSON encoded/decoded it to convert to a typed array or +// slice, so `json` struct tags are respected. +// +// Deprecated: Use UnmarshalList instead +func ConvertFromList(item []*dynamodb.AttributeValue, v interface{}) (err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(runtime.Error); ok { + err = e + } else if s, ok := r.(string); ok { + err = fmt.Errorf(s) + } else { + err = r.(error) + } + item = nil + } + }() + + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return awserr.New("SerializationError", + fmt.Sprintf("v must be a non-nil pointer to an array or slice, got %s", + rv.Type()), + nil) + } + if rv.Elem().Kind() != reflect.Array && rv.Elem().Kind() != reflect.Slice { + return awserr.New("SerializationError", + fmt.Sprintf("v must be a non-nil pointer to an array or slice, got %s", + rv.Type()), + nil) + } + + l := make([]interface{}, 0, len(item)) + for _, v := range item { + l = append(l, convertFrom(v)) + } + + if isTyped(reflect.TypeOf(v)) { + err = convertToTyped(l, v) + } else { + rv.Elem().Set(reflect.ValueOf(l)) + } + + return err +} + +// ConvertTo accepts any interface{} and converts it to a *dynamodb.AttributeValue. +// +// If in contains any structs, it is first JSON encoded/decoded it to convert it +// to a interface{}, so `json` struct tags are respected. +// +// Deprecated: Use Marshal instead +func ConvertTo(in interface{}) (item *dynamodb.AttributeValue, err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(runtime.Error); ok { + err = e + } else if s, ok := r.(string); ok { + err = fmt.Errorf(s) + } else { + err = r.(error) + } + item = nil + } + }() + + if in != nil && isTyped(reflect.TypeOf(in)) { + var out interface{} + in = convertToUntyped(in, out) + } + + item = convertTo(in) + return item, nil +} + +// ConvertFrom accepts a *dynamodb.AttributeValue and converts it to any interface{}. +// +// If v contains any structs, the result is first converted it to a interface{}, +// then JSON encoded/decoded it to convert to a struct, so `json` struct tags +// are respected. +// +// Deprecated: Use Unmarshal instead +func ConvertFrom(item *dynamodb.AttributeValue, v interface{}) (err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(runtime.Error); ok { + err = e + } else if s, ok := r.(string); ok { + err = fmt.Errorf(s) + } else { + err = r.(error) + } + item = nil + } + }() + + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return awserr.New("SerializationError", + fmt.Sprintf("v must be a non-nil pointer to an interface{} or struct, got %s", + rv.Type()), + nil) + } + if rv.Elem().Kind() != reflect.Interface && rv.Elem().Kind() != reflect.Struct { + return awserr.New("SerializationError", + fmt.Sprintf("v must be a non-nil pointer to an interface{} or struct, got %s", + rv.Type()), + nil) + } + + res := convertFrom(item) + + if isTyped(reflect.TypeOf(v)) { + err = convertToTyped(res, v) + } else if res != nil { + rv.Elem().Set(reflect.ValueOf(res)) + } + + return err +} + +func isTyped(v reflect.Type) bool { + switch v.Kind() { + case reflect.Struct: + return true + case reflect.Array, reflect.Slice: + if isTyped(v.Elem()) { + return true + } + case reflect.Map: + if isTyped(v.Key()) { + return true + } + if isTyped(v.Elem()) { + return true + } + case reflect.Ptr: + return isTyped(v.Elem()) + } + return false +} + +func convertToUntyped(in, out interface{}) interface{} { + b, err := json.Marshal(in) + if err != nil { + panic(err) + } + + decoder := json.NewDecoder(bytes.NewReader(b)) + decoder.UseNumber() + err = decoder.Decode(&out) + if err != nil { + panic(err) + } + + return out +} + +func convertToTyped(in, out interface{}) error { + b, err := json.Marshal(in) + if err != nil { + return err + } + + decoder := json.NewDecoder(bytes.NewReader(b)) + return decoder.Decode(&out) +} + +func convertTo(in interface{}) *dynamodb.AttributeValue { + a := &dynamodb.AttributeValue{} + + if in == nil { + a.NULL = new(bool) + *a.NULL = true + return a + } + + if m, ok := in.(map[string]interface{}); ok { + a.M = make(map[string]*dynamodb.AttributeValue) + for k, v := range m { + a.M[k] = convertTo(v) + } + return a + } + + v := reflect.ValueOf(in) + switch v.Kind() { + case reflect.Bool: + a.BOOL = new(bool) + *a.BOOL = v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + a.N = new(string) + *a.N = strconv.FormatInt(v.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + a.N = new(string) + *a.N = strconv.FormatUint(v.Uint(), 10) + case reflect.Float32, reflect.Float64: + a.N = new(string) + *a.N = strconv.FormatFloat(v.Float(), 'f', -1, 64) + case reflect.String: + if n, ok := in.(json.Number); ok { + a.N = new(string) + *a.N = n.String() + } else { + a.S = new(string) + *a.S = v.String() + } + case reflect.Slice: + switch v.Type() { + case reflect.TypeOf(([]byte)(nil)): + a.B = v.Bytes() + default: + a.L = make([]*dynamodb.AttributeValue, v.Len()) + for i := 0; i < v.Len(); i++ { + a.L[i] = convertTo(v.Index(i).Interface()) + } + } + default: + panic(fmt.Sprintf("the type %s is not supported", v.Type().String())) + } + + return a +} + +func convertFrom(a *dynamodb.AttributeValue) interface{} { + if a.S != nil { + return *a.S + } + + if a.N != nil { + // Number is tricky b/c we don't know which numeric type to use. Here we + // simply try the different types from most to least restrictive. + if n, err := strconv.ParseInt(*a.N, 10, 64); err == nil { + return int(n) + } + if n, err := strconv.ParseUint(*a.N, 10, 64); err == nil { + return uint(n) + } + n, err := strconv.ParseFloat(*a.N, 64) + if err != nil { + panic(err) + } + return n + } + + if a.BOOL != nil { + return *a.BOOL + } + + if a.NULL != nil { + return nil + } + + if a.M != nil { + m := make(map[string]interface{}) + for k, v := range a.M { + m[k] = convertFrom(v) + } + return m + } + + if a.L != nil { + l := make([]interface{}, len(a.L)) + for index, v := range a.L { + l[index] = convertFrom(v) + } + return l + } + + if a.B != nil { + return a.B + } + + panic(fmt.Sprintf("%#v is not a supported dynamodb.AttributeValue", a)) +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_examples_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_examples_test.go new file mode 100644 index 0000000..67b65fa --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_examples_test.go @@ -0,0 +1,80 @@ +package dynamodbattribute_test + +import ( + "fmt" + "reflect" + + "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" +) + +func ExampleConvertTo() { + type Record struct { + MyField string + Letters []string + Numbers []int + } + + r := Record{ + MyField: "MyFieldValue", + Letters: []string{"a", "b", "c", "d"}, + Numbers: []int{1, 2, 3}, + } + av, err := dynamodbattribute.ConvertTo(r) + fmt.Println("err", err) + fmt.Println("MyField", av.M["MyField"]) + fmt.Println("Letters", av.M["Letters"]) + fmt.Println("Numbers", av.M["Numbers"]) + + // Output: + // err + // MyField { + // S: "MyFieldValue" + // } + // Letters { + // L: [ + // { + // S: "a" + // }, + // { + // S: "b" + // }, + // { + // S: "c" + // }, + // { + // S: "d" + // } + // ] + // } + // Numbers { + // L: [{ + // N: "1" + // },{ + // N: "2" + // },{ + // N: "3" + // }] + // } +} + +func ExampleConvertFrom() { + type Record struct { + MyField string + Letters []string + A2Num map[string]int + } + + r := Record{ + MyField: "MyFieldValue", + Letters: []string{"a", "b", "c", "d"}, + A2Num: map[string]int{"a": 1, "b": 2, "c": 3}, + } + av, err := dynamodbattribute.ConvertTo(r) + + r2 := Record{} + err = dynamodbattribute.ConvertFrom(av, &r2) + fmt.Println(err, reflect.DeepEqual(r, r2)) + + // Output: + // true +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_test.go new file mode 100644 index 0000000..a73cd22 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/converter_test.go @@ -0,0 +1,498 @@ +package dynamodbattribute + +import ( + "math" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +type mySimpleStruct struct { + String string + Int int + Uint uint + Float32 float32 + Float64 float64 + Bool bool + Null *interface{} +} + +type myComplexStruct struct { + Simple []mySimpleStruct +} + +type converterTestInput struct { + input interface{} + expected interface{} + err awserr.Error + inputType string // "enum" of types +} + +var trueValue = true +var falseValue = false + +var converterScalarInputs = []converterTestInput{ + { + input: nil, + expected: &dynamodb.AttributeValue{NULL: &trueValue}, + }, + { + input: "some string", + expected: &dynamodb.AttributeValue{S: aws.String("some string")}, + }, + { + input: true, + expected: &dynamodb.AttributeValue{BOOL: &trueValue}, + }, + { + input: false, + expected: &dynamodb.AttributeValue{BOOL: &falseValue}, + }, + { + input: 3.14, + expected: &dynamodb.AttributeValue{N: aws.String("3.14")}, + }, + { + input: math.MaxFloat32, + expected: &dynamodb.AttributeValue{N: aws.String("340282346638528860000000000000000000000")}, + }, + { + input: math.MaxFloat64, + expected: &dynamodb.AttributeValue{N: aws.String("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")}, + }, + { + input: 12, + expected: &dynamodb.AttributeValue{N: aws.String("12")}, + }, + { + input: mySimpleStruct{}, + expected: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {S: aws.String("")}, + "Uint": {N: aws.String("0")}, + }, + }, + inputType: "mySimpleStruct", + }, +} + +var converterMapTestInputs = []converterTestInput{ + // Scalar tests + { + input: nil, + err: awserr.New("SerializationError", "in must be a map[string]interface{} or struct, got ", nil), + }, + { + input: map[string]interface{}{"string": "some string"}, + expected: map[string]*dynamodb.AttributeValue{"string": {S: aws.String("some string")}}, + }, + { + input: map[string]interface{}{"bool": true}, + expected: map[string]*dynamodb.AttributeValue{"bool": {BOOL: &trueValue}}, + }, + { + input: map[string]interface{}{"bool": false}, + expected: map[string]*dynamodb.AttributeValue{"bool": {BOOL: &falseValue}}, + }, + { + input: map[string]interface{}{"null": nil}, + expected: map[string]*dynamodb.AttributeValue{"null": {NULL: &trueValue}}, + }, + { + input: map[string]interface{}{"float": 3.14}, + expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("3.14")}}, + }, + { + input: map[string]interface{}{"float": math.MaxFloat32}, + expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("340282346638528860000000000000000000000")}}, + }, + { + input: map[string]interface{}{"float": math.MaxFloat64}, + expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")}}, + }, + { + input: map[string]interface{}{"int": int(12)}, + expected: map[string]*dynamodb.AttributeValue{"int": {N: aws.String("12")}}, + }, + { + input: map[string]interface{}{"byte": []byte{48, 49}}, + expected: map[string]*dynamodb.AttributeValue{"byte": {B: []byte{48, 49}}}, + }, + // List + { + input: map[string]interface{}{"list": []interface{}{"a string", 12, 3.14, true, nil, false}}, + expected: map[string]*dynamodb.AttributeValue{ + "list": { + L: []*dynamodb.AttributeValue{ + {S: aws.String("a string")}, + {N: aws.String("12")}, + {N: aws.String("3.14")}, + {BOOL: &trueValue}, + {NULL: &trueValue}, + {BOOL: &falseValue}, + }, + }, + }, + }, + // Map + { + input: map[string]interface{}{"map": map[string]interface{}{"nestedint": 12}}, + expected: map[string]*dynamodb.AttributeValue{ + "map": { + M: map[string]*dynamodb.AttributeValue{ + "nestedint": { + N: aws.String("12"), + }, + }, + }, + }, + }, + // Structs + { + input: mySimpleStruct{}, + expected: map[string]*dynamodb.AttributeValue{ + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {S: aws.String("")}, + "Uint": {N: aws.String("0")}, + }, + inputType: "mySimpleStruct", + }, + { + input: myComplexStruct{}, + expected: map[string]*dynamodb.AttributeValue{ + "Simple": {NULL: &trueValue}, + }, + inputType: "myComplexStruct", + }, + { + input: myComplexStruct{Simple: []mySimpleStruct{{Int: -2}, {Uint: 5}}}, + expected: map[string]*dynamodb.AttributeValue{ + "Simple": { + L: []*dynamodb.AttributeValue{ + { + M: map[string]*dynamodb.AttributeValue{ + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("-2")}, + "Null": {NULL: &trueValue}, + "String": {S: aws.String("")}, + "Uint": {N: aws.String("0")}, + }, + }, + { + M: map[string]*dynamodb.AttributeValue{ + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {S: aws.String("")}, + "Uint": {N: aws.String("5")}, + }, + }, + }, + }, + }, + inputType: "myComplexStruct", + }, +} + +var converterListTestInputs = []converterTestInput{ + { + input: nil, + err: awserr.New("SerializationError", "in must be an array or slice, got ", nil), + }, + { + input: []interface{}{}, + expected: []*dynamodb.AttributeValue{}, + }, + { + input: []interface{}{"a string", 12, 3.14, true, nil, false}, + expected: []*dynamodb.AttributeValue{ + {S: aws.String("a string")}, + {N: aws.String("12")}, + {N: aws.String("3.14")}, + {BOOL: &trueValue}, + {NULL: &trueValue}, + {BOOL: &falseValue}, + }, + }, + { + input: []mySimpleStruct{{}}, + expected: []*dynamodb.AttributeValue{ + { + M: map[string]*dynamodb.AttributeValue{ + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {S: aws.String("")}, + "Uint": {N: aws.String("0")}, + }, + }, + }, + inputType: "mySimpleStruct", + }, +} + +func TestConvertTo(t *testing.T) { + for _, test := range converterScalarInputs { + testConvertTo(t, test) + } +} + +func testConvertTo(t *testing.T, test converterTestInput) { + actual, err := ConvertTo(test.input) + if test.err != nil { + if err == nil { + t.Errorf("ConvertTo with input %#v retured %#v, expected error `%s`", test.input, actual, test.err) + } else if err.Error() != test.err.Error() { + t.Errorf("ConvertTo with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err) + } + } else { + if err != nil { + t.Errorf("ConvertTo with input %#v retured error `%s`", test.input, err) + } + compareObjects(t, test.expected, actual) + } +} + +func TestConvertFrom(t *testing.T) { + // Using the same inputs from TestConvertTo, test the reverse mapping. + for _, test := range converterScalarInputs { + if test.expected != nil { + testConvertFrom(t, test) + } + } +} + +func testConvertFrom(t *testing.T, test converterTestInput) { + switch test.inputType { + case "mySimpleStruct": + var actual mySimpleStruct + if err := ConvertFrom(test.expected.(*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFrom with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + case "myComplexStruct": + var actual myComplexStruct + if err := ConvertFrom(test.expected.(*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFrom with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + default: + var actual interface{} + if err := ConvertFrom(test.expected.(*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFrom with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + } +} + +func TestConvertFromError(t *testing.T) { + // Test that we get an error using ConvertFrom to convert to a map. + var actual map[string]interface{} + expected := awserr.New("SerializationError", `v must be a non-nil pointer to an interface{} or struct, got *map[string]interface {}`, nil).Error() + if err := ConvertFrom(nil, &actual); err == nil { + t.Errorf("ConvertFrom with input %#v returned no error, expected error `%s`", nil, expected) + } else if err.Error() != expected { + t.Errorf("ConvertFrom with input %#v returned error `%s`, expected error `%s`", nil, err, expected) + } + + // Test that we get an error using ConvertFrom to convert to a list. + var actual2 []interface{} + expected = awserr.New("SerializationError", `v must be a non-nil pointer to an interface{} or struct, got *[]interface {}`, nil).Error() + if err := ConvertFrom(nil, &actual2); err == nil { + t.Errorf("ConvertFrom with input %#v returned no error, expected error `%s`", nil, expected) + } else if err.Error() != expected { + t.Errorf("ConvertFrom with input %#v returned error `%s`, expected error `%s`", nil, err, expected) + } +} + +func TestConvertToMap(t *testing.T) { + for _, test := range converterMapTestInputs { + testConvertToMap(t, test) + } +} + +func testConvertToMap(t *testing.T, test converterTestInput) { + actual, err := ConvertToMap(test.input) + if test.err != nil { + if err == nil { + t.Errorf("ConvertToMap with input %#v retured %#v, expected error `%s`", test.input, actual, test.err) + } else if err.Error() != test.err.Error() { + t.Errorf("ConvertToMap with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err) + } + } else { + if err != nil { + t.Errorf("ConvertToMap with input %#v retured error `%s`", test.input, err) + } + compareObjects(t, test.expected, actual) + } +} + +func TestConvertFromMap(t *testing.T) { + // Using the same inputs from TestConvertToMap, test the reverse mapping. + for _, test := range converterMapTestInputs { + if test.expected != nil { + testConvertFromMap(t, test) + } + } +} + +func testConvertFromMap(t *testing.T, test converterTestInput) { + switch test.inputType { + case "mySimpleStruct": + var actual mySimpleStruct + if err := ConvertFromMap(test.expected.(map[string]*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFromMap with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + case "myComplexStruct": + var actual myComplexStruct + if err := ConvertFromMap(test.expected.(map[string]*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFromMap with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + default: + var actual map[string]interface{} + if err := ConvertFromMap(test.expected.(map[string]*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFromMap with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + } +} + +func TestConvertFromMapError(t *testing.T) { + // Test that we get an error using ConvertFromMap to convert to an interface{}. + var actual interface{} + expected := awserr.New("SerializationError", `v must be a non-nil pointer to a map[string]interface{} or struct, got *interface {}`, nil).Error() + if err := ConvertFromMap(nil, &actual); err == nil { + t.Errorf("ConvertFromMap with input %#v returned no error, expected error `%s`", nil, expected) + } else if err.Error() != expected { + t.Errorf("ConvertFromMap with input %#v returned error `%s`, expected error `%s`", nil, err, expected) + } + + // Test that we get an error using ConvertFromMap to convert to a slice. + var actual2 []interface{} + expected = awserr.New("SerializationError", `v must be a non-nil pointer to a map[string]interface{} or struct, got *[]interface {}`, nil).Error() + if err := ConvertFromMap(nil, &actual2); err == nil { + t.Errorf("ConvertFromMap with input %#v returned no error, expected error `%s`", nil, expected) + } else if err.Error() != expected { + t.Errorf("ConvertFromMap with input %#v returned error `%s`, expected error `%s`", nil, err, expected) + } +} + +func TestConvertToList(t *testing.T) { + for _, test := range converterListTestInputs { + testConvertToList(t, test) + } +} + +func testConvertToList(t *testing.T, test converterTestInput) { + actual, err := ConvertToList(test.input) + if test.err != nil { + if err == nil { + t.Errorf("ConvertToList with input %#v retured %#v, expected error `%s`", test.input, actual, test.err) + } else if err.Error() != test.err.Error() { + t.Errorf("ConvertToList with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err) + } + } else { + if err != nil { + t.Errorf("ConvertToList with input %#v retured error `%s`", test.input, err) + } + compareObjects(t, test.expected, actual) + } +} + +func TestConvertFromList(t *testing.T) { + // Using the same inputs from TestConvertToList, test the reverse mapping. + for _, test := range converterListTestInputs { + if test.expected != nil { + testConvertFromList(t, test) + } + } +} + +func testConvertFromList(t *testing.T, test converterTestInput) { + switch test.inputType { + case "mySimpleStruct": + var actual []mySimpleStruct + if err := ConvertFromList(test.expected.([]*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFromList with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + case "myComplexStruct": + var actual []myComplexStruct + if err := ConvertFromList(test.expected.([]*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFromList with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + default: + var actual []interface{} + if err := ConvertFromList(test.expected.([]*dynamodb.AttributeValue), &actual); err != nil { + t.Errorf("ConvertFromList with input %#v retured error `%s`", test.expected, err) + } + compareObjects(t, test.input, actual) + } +} + +func TestConvertFromListError(t *testing.T) { + // Test that we get an error using ConvertFromList to convert to a map. + var actual map[string]interface{} + expected := awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *map[string]interface {}`, nil).Error() + if err := ConvertFromList(nil, &actual); err == nil { + t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected) + } else if err.Error() != expected { + t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected) + } + + // Test that we get an error using ConvertFromList to convert to a struct. + var actual2 myComplexStruct + expected = awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *dynamodbattribute.myComplexStruct`, nil).Error() + if err := ConvertFromList(nil, &actual2); err == nil { + t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected) + } else if err.Error() != expected { + t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected) + } + + // Test that we get an error using ConvertFromList to convert to an interface{}. + var actual3 interface{} + expected = awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *interface {}`, nil).Error() + if err := ConvertFromList(nil, &actual3); err == nil { + t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected) + } else if err.Error() != expected { + t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected) + } +} + +func BenchmarkConvertTo(b *testing.B) { + d := mySimpleStruct{ + String: "abc", + Int: 123, + Uint: 123, + Float32: 123.321, + Float64: 123.321, + Bool: true, + Null: nil, + } + for i := 0; i < b.N; i++ { + _, err := ConvertTo(d) + if err != nil { + b.Fatal("unexpected error", err) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode.go new file mode 100644 index 0000000..e024975 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode.go @@ -0,0 +1,761 @@ +package dynamodbattribute + +import ( + "fmt" + "reflect" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +// An Unmarshaler is an interface to provide custom unmarshaling of +// AttributeValues. Use this to provide custom logic determining +// how AttributeValues should be unmarshaled. +// type ExampleUnmarshaler struct { +// Value int +// } +// +// func (u *exampleUnmarshaler) UnmarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error { +// if av.N == nil { +// return nil +// } +// +// n, err := strconv.ParseInt(*av.N, 10, 0) +// if err != nil { +// return err +// } +// +// u.Value = n +// return nil +// } +type Unmarshaler interface { + UnmarshalDynamoDBAttributeValue(*dynamodb.AttributeValue) error +} + +// Unmarshal will unmarshal DynamoDB AttributeValues to Go value types. +// Both generic interface{} and concrete types are valid unmarshal +// destination types. +// +// Unmarshal will allocate maps, slices, and pointers as needed to +// unmarshal the AttributeValue into the provided type value. +// +// When unmarshaling AttributeValues into structs Unmarshal matches +// the field names of the struct to the AttributeValue Map keys. +// Initially it will look for exact field name matching, but will +// fall back to case insensitive if not exact match is found. +// +// With the exception of omitempty, omitemptyelem, binaryset, numberset +// and stringset all struct tags used by Marshal are also used by +// Unmarshal. +// +// When decoding AttributeValues to interfaces Unmarshal will use the +// following types. +// +// []byte, AV Binary (B) +// [][]byte, AV Binary Set (BS) +// bool, AV Boolean (BOOL) +// []interface{}, AV List (L) +// map[string]interface{}, AV Map (M) +// float64, AV Number (N) +// Number, AV Number (N) with UseNumber set +// []float64, AV Number Set (NS) +// []Number, AV Number Set (NS) with UseNumber set +// string, AV String (S) +// []string, AV String Set (SS) +// +// If the Decoder option, UseNumber is set numbers will be unmarshaled +// as Number values instead of float64. Use this to maintain the original +// string formating of the number as it was represented in the AttributeValue. +// In addition provides additional opportunities to parse the number +// string based on individual use cases. +// +// When unmarshaling any error that occurs will halt the unmarshal +// and return the error. +// +// The output value provided must be a non-nil pointer +func Unmarshal(av *dynamodb.AttributeValue, out interface{}) error { + return NewDecoder().Decode(av, out) +} + +// UnmarshalMap is an alias for Unmarshal which unmarshals from +// a map of AttributeValues. +// +// The output value provided must be a non-nil pointer +func UnmarshalMap(m map[string]*dynamodb.AttributeValue, out interface{}) error { + return NewDecoder().Decode(&dynamodb.AttributeValue{M: m}, out) +} + +// UnmarshalList is an alias for Unmarshal func which unmarshals +// a slice of AttributeValues. +// +// The output value provided must be a non-nil pointer +func UnmarshalList(l []*dynamodb.AttributeValue, out interface{}) error { + return NewDecoder().Decode(&dynamodb.AttributeValue{L: l}, out) +} + +// UnmarshalListOfMaps is an alias for Unmarshal func which unmarshals a +// slice of maps of attribute values. +// +// This is useful for when you need to unmarshal the Items from a DynamoDB +// Query API call. +// +// The output value provided must be a non-nil pointer +func UnmarshalListOfMaps(l []map[string]*dynamodb.AttributeValue, out interface{}) error { + items := make([]*dynamodb.AttributeValue, len(l)) + for i, m := range l { + items[i] = &dynamodb.AttributeValue{M: m} + } + + return UnmarshalList(items, out) +} + +// A Decoder provides unmarshaling AttributeValues to Go value types. +type Decoder struct { + MarshalOptions + + // Instructs the decoder to decode AttributeValue Numbers as + // Number type instead of float64 when the destination type + // is interface{}. Similar to encoding/json.Number + UseNumber bool +} + +// NewDecoder creates a new Decoder with default configuration. Use +// the `opts` functional options to override the default configuration. +func NewDecoder(opts ...func(*Decoder)) *Decoder { + d := &Decoder{ + MarshalOptions: MarshalOptions{ + SupportJSONTags: true, + }, + } + for _, o := range opts { + o(d) + } + + return d +} + +// Decode will unmarshal an AttributeValue into a Go value type. An error +// will be return if the decoder is unable to unmarshal the AttributeValue +// to the provide Go value type. +// +// The output value provided must be a non-nil pointer +func (d *Decoder) Decode(av *dynamodb.AttributeValue, out interface{}, opts ...func(*Decoder)) error { + v := reflect.ValueOf(out) + if v.Kind() != reflect.Ptr || v.IsNil() || !v.IsValid() { + return &InvalidUnmarshalError{Type: reflect.TypeOf(out)} + } + + return d.decode(av, v, tag{}) +} + +var stringInterfaceMapType = reflect.TypeOf(map[string]interface{}(nil)) +var byteSliceType = reflect.TypeOf([]byte(nil)) +var byteSliceSlicetype = reflect.TypeOf([][]byte(nil)) +var numberType = reflect.TypeOf(Number("")) +var timeType = reflect.TypeOf(time.Time{}) + +func (d *Decoder) decode(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error { + var u Unmarshaler + if av == nil || av.NULL != nil { + u, v = indirect(v, true) + if u != nil { + return u.UnmarshalDynamoDBAttributeValue(av) + } + return d.decodeNull(v) + } + + u, v = indirect(v, false) + if u != nil { + return u.UnmarshalDynamoDBAttributeValue(av) + } + + switch { + case len(av.B) != 0: + return d.decodeBinary(av.B, v) + case av.BOOL != nil: + return d.decodeBool(av.BOOL, v) + case len(av.BS) != 0: + return d.decodeBinarySet(av.BS, v) + case len(av.L) != 0: + return d.decodeList(av.L, v) + case len(av.M) != 0: + return d.decodeMap(av.M, v) + case av.N != nil: + return d.decodeNumber(av.N, v, fieldTag) + case len(av.NS) != 0: + return d.decodeNumberSet(av.NS, v) + case av.S != nil: + return d.decodeString(av.S, v, fieldTag) + case len(av.SS) != 0: + return d.decodeStringSet(av.SS, v) + } + + return nil +} + +func (d *Decoder) decodeBinary(b []byte, v reflect.Value) error { + if v.Kind() == reflect.Interface { + buf := make([]byte, len(b)) + copy(buf, b) + v.Set(reflect.ValueOf(buf)) + return nil + } + + if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { + return &UnmarshalTypeError{Value: "binary", Type: v.Type()} + } + + if v.Type() == byteSliceType { + // Optimization for []byte types + if v.IsNil() || v.Cap() < len(b) { + v.Set(reflect.MakeSlice(byteSliceType, len(b), len(b))) + } else if v.Len() != len(b) { + v.SetLen(len(b)) + } + copy(v.Interface().([]byte), b) + return nil + } + + switch v.Type().Elem().Kind() { + case reflect.Uint8: + // Fallback to reflection copy for type aliased of []byte type + if v.Kind() != reflect.Array && (v.IsNil() || v.Cap() < len(b)) { + v.Set(reflect.MakeSlice(v.Type(), len(b), len(b))) + } else if v.Len() != len(b) { + v.SetLen(len(b)) + } + for i := 0; i < len(b); i++ { + v.Index(i).SetUint(uint64(b[i])) + } + default: + if v.Kind() == reflect.Array { + switch v.Type().Elem().Kind() { + case reflect.Uint8: + reflect.Copy(v, reflect.ValueOf(b)) + default: + return &UnmarshalTypeError{Value: "binary", Type: v.Type()} + } + + break + } + + return &UnmarshalTypeError{Value: "binary", Type: v.Type()} + } + + return nil +} + +func (d *Decoder) decodeBool(b *bool, v reflect.Value) error { + switch v.Kind() { + case reflect.Bool, reflect.Interface: + v.Set(reflect.ValueOf(*b).Convert(v.Type())) + default: + return &UnmarshalTypeError{Value: "bool", Type: v.Type()} + } + + return nil +} + +func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { + isArray := false + + switch v.Kind() { + case reflect.Slice: + // Make room for the slice elements if needed + if v.IsNil() || v.Cap() < len(bs) { + // What about if ignoring nil/empty values? + v.Set(reflect.MakeSlice(v.Type(), 0, len(bs))) + } + case reflect.Array: + // Limited to capacity of existing array. + isArray = true + case reflect.Interface: + set := make([][]byte, len(bs)) + for i, b := range bs { + if err := d.decodeBinary(b, reflect.ValueOf(&set[i]).Elem()); err != nil { + return err + } + } + v.Set(reflect.ValueOf(set)) + return nil + default: + return &UnmarshalTypeError{Value: "binary set", Type: v.Type()} + } + + for i := 0; i < v.Cap() && i < len(bs); i++ { + if !isArray { + v.SetLen(i + 1) + } + u, elem := indirect(v.Index(i), false) + if u != nil { + return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{BS: bs}) + } + if err := d.decodeBinary(bs[i], elem); err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeNumber(n *string, v reflect.Value, fieldTag tag) error { + switch v.Kind() { + case reflect.Interface: + i, err := d.decodeNumberToInterface(n) + if err != nil { + return err + } + v.Set(reflect.ValueOf(i)) + return nil + case reflect.String: + if v.Type() == numberType { // Support Number value type + v.Set(reflect.ValueOf(Number(*n))) + return nil + } + v.Set(reflect.ValueOf(*n)) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + i, err := strconv.ParseInt(*n, 10, 64) + if err != nil { + return err + } + if v.OverflowInt(i) { + return &UnmarshalTypeError{ + Value: fmt.Sprintf("number overflow, %s", *n), + Type: v.Type(), + } + } + v.SetInt(i) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + i, err := strconv.ParseUint(*n, 10, 64) + if err != nil { + return err + } + if v.OverflowUint(i) { + return &UnmarshalTypeError{ + Value: fmt.Sprintf("number overflow, %s", *n), + Type: v.Type(), + } + } + v.SetUint(i) + case reflect.Float32, reflect.Float64: + i, err := strconv.ParseFloat(*n, 64) + if err != nil { + return err + } + if v.OverflowFloat(i) { + return &UnmarshalTypeError{ + Value: fmt.Sprintf("number overflow, %s", *n), + Type: v.Type(), + } + } + v.SetFloat(i) + default: + if v.Type().ConvertibleTo(timeType) && fieldTag.AsUnixTime { + t, err := decodeUnixTime(*n) + if err != nil { + return err + } + v.Set(reflect.ValueOf(t).Convert(v.Type())) + return nil + } + return &UnmarshalTypeError{Value: "number", Type: v.Type()} + } + + return nil +} + +func (d *Decoder) decodeNumberToInterface(n *string) (interface{}, error) { + if d.UseNumber { + return Number(*n), nil + } + + // Default to float64 for all numbers + return strconv.ParseFloat(*n, 64) +} + +func (d *Decoder) decodeNumberSet(ns []*string, v reflect.Value) error { + isArray := false + + switch v.Kind() { + case reflect.Slice: + // Make room for the slice elements if needed + if v.IsNil() || v.Cap() < len(ns) { + // What about if ignoring nil/empty values? + v.Set(reflect.MakeSlice(v.Type(), 0, len(ns))) + } + case reflect.Array: + // Limited to capacity of existing array. + isArray = true + case reflect.Interface: + if d.UseNumber { + set := make([]Number, len(ns)) + for i, n := range ns { + if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil { + return err + } + } + v.Set(reflect.ValueOf(set)) + } else { + set := make([]float64, len(ns)) + for i, n := range ns { + if err := d.decodeNumber(n, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil { + return err + } + } + v.Set(reflect.ValueOf(set)) + } + return nil + default: + return &UnmarshalTypeError{Value: "number set", Type: v.Type()} + } + + for i := 0; i < v.Cap() && i < len(ns); i++ { + if !isArray { + v.SetLen(i + 1) + } + u, elem := indirect(v.Index(i), false) + if u != nil { + return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{NS: ns}) + } + if err := d.decodeNumber(ns[i], elem, tag{}); err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeList(avList []*dynamodb.AttributeValue, v reflect.Value) error { + isArray := false + + switch v.Kind() { + case reflect.Slice: + // Make room for the slice elements if needed + if v.IsNil() || v.Cap() < len(avList) { + // What about if ignoring nil/empty values? + v.Set(reflect.MakeSlice(v.Type(), 0, len(avList))) + } + case reflect.Array: + // Limited to capacity of existing array. + isArray = true + case reflect.Interface: + s := make([]interface{}, len(avList)) + for i, av := range avList { + if err := d.decode(av, reflect.ValueOf(&s[i]).Elem(), tag{}); err != nil { + return err + } + } + v.Set(reflect.ValueOf(s)) + return nil + default: + return &UnmarshalTypeError{Value: "list", Type: v.Type()} + } + + // If v is not a slice, array + for i := 0; i < v.Cap() && i < len(avList); i++ { + if !isArray { + v.SetLen(i + 1) + } + + if err := d.decode(avList[i], v.Index(i), tag{}); err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeMap(avMap map[string]*dynamodb.AttributeValue, v reflect.Value) error { + switch v.Kind() { + case reflect.Map: + t := v.Type() + if t.Key().Kind() != reflect.String { + return &UnmarshalTypeError{Value: "map string key", Type: t.Key()} + } + if v.IsNil() { + v.Set(reflect.MakeMap(t)) + } + case reflect.Struct: + case reflect.Interface: + v.Set(reflect.MakeMap(stringInterfaceMapType)) + v = v.Elem() + default: + return &UnmarshalTypeError{Value: "map", Type: v.Type()} + } + + if v.Kind() == reflect.Map { + for k, av := range avMap { + key := reflect.ValueOf(k) + elem := reflect.New(v.Type().Elem()).Elem() + if err := d.decode(av, elem, tag{}); err != nil { + return err + } + v.SetMapIndex(key, elem) + } + } else if v.Kind() == reflect.Struct { + fields := unionStructFields(v.Type(), d.MarshalOptions) + for k, av := range avMap { + if f, ok := fieldByName(fields, k); ok { + fv := fieldByIndex(v, f.Index, func(v *reflect.Value) bool { + v.Set(reflect.New(v.Type().Elem())) + return true // to continue the loop. + }) + if err := d.decode(av, fv, f.tag); err != nil { + return err + } + } + } + } + + return nil +} + +func (d *Decoder) decodeNull(v reflect.Value) error { + if v.IsValid() && v.CanSet() { + v.Set(reflect.Zero(v.Type())) + } + + return nil +} + +func (d *Decoder) decodeString(s *string, v reflect.Value, fieldTag tag) error { + if fieldTag.AsString { + return d.decodeNumber(s, v, fieldTag) + } + + // To maintain backwards compatibility with ConvertFrom family of methods which + // converted strings to time.Time structs + if v.Type().ConvertibleTo(timeType) { + t, err := time.Parse(time.RFC3339, *s) + if err != nil { + return err + } + v.Set(reflect.ValueOf(t).Convert(v.Type())) + return nil + } + + switch v.Kind() { + case reflect.String: + v.SetString(*s) + case reflect.Interface: + // Ensure type aliasing is handled properly + v.Set(reflect.ValueOf(*s).Convert(v.Type())) + default: + return &UnmarshalTypeError{Value: "string", Type: v.Type()} + } + + return nil +} + +func (d *Decoder) decodeStringSet(ss []*string, v reflect.Value) error { + isArray := false + + switch v.Kind() { + case reflect.Slice: + // Make room for the slice elements if needed + if v.IsNil() || v.Cap() < len(ss) { + v.Set(reflect.MakeSlice(v.Type(), 0, len(ss))) + } + case reflect.Array: + // Limited to capacity of existing array. + isArray = true + case reflect.Interface: + set := make([]string, len(ss)) + for i, s := range ss { + if err := d.decodeString(s, reflect.ValueOf(&set[i]).Elem(), tag{}); err != nil { + return err + } + } + v.Set(reflect.ValueOf(set)) + return nil + default: + return &UnmarshalTypeError{Value: "string set", Type: v.Type()} + } + + for i := 0; i < v.Cap() && i < len(ss); i++ { + if !isArray { + v.SetLen(i + 1) + } + u, elem := indirect(v.Index(i), false) + if u != nil { + return u.UnmarshalDynamoDBAttributeValue(&dynamodb.AttributeValue{SS: ss}) + } + if err := d.decodeString(ss[i], elem, tag{}); err != nil { + return err + } + } + + return nil +} + +func decodeUnixTime(n string) (time.Time, error) { + v, err := strconv.ParseInt(n, 10, 64) + if err != nil { + return time.Time{}, &UnmarshalError{ + Err: err, Value: n, Type: timeType, + } + } + + return time.Unix(v, 0), nil +} + +// indirect will walk a value's interface or pointer value types. Returning +// the final value or the value a unmarshaler is defined on. +// +// Based on the enoding/json type reflect value type indirection in Go Stdlib +// https://golang.org/src/encoding/json/decode.go indirect func. +func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) { + if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + v = v.Addr() + } + for { + if v.Kind() == reflect.Interface && !v.IsNil() { + e := v.Elem() + if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { + v = e + continue + } + } + if v.Kind() != reflect.Ptr { + break + } + if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { + break + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + if v.Type().NumMethod() > 0 { + if u, ok := v.Interface().(Unmarshaler); ok { + return u, reflect.Value{} + } + } + v = v.Elem() + } + + return nil, v +} + +// A Number represents a Attributevalue number literal. +type Number string + +// Float64 attempts to cast the number ot a float64, returning +// the result of the case or error if the case failed. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 attempts to cast the number ot a int64, returning +// the result of the case or error if the case failed. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +// Uint64 attempts to cast the number ot a uint64, returning +// the result of the case or error if the case failed. +func (n Number) Uint64() (uint64, error) { + return strconv.ParseUint(string(n), 10, 64) +} + +// String returns the raw number represented as a string +func (n Number) String() string { + return string(n) +} + +type emptyOrigError struct{} + +func (e emptyOrigError) OrigErr() error { + return nil +} + +// An UnmarshalTypeError is an error type representing a error +// unmarshaling the AttributeValue's element to a Go value type. +// Includes details about the AttributeValue type and Go value type. +type UnmarshalTypeError struct { + emptyOrigError + Value string + Type reflect.Type +} + +// Error returns the string representation of the error. +// satisfying the error interface +func (e *UnmarshalTypeError) Error() string { + return fmt.Sprintf("%s: %s", e.Code(), e.Message()) +} + +// Code returns the code of the error, satisfying the awserr.Error +// interface. +func (e *UnmarshalTypeError) Code() string { + return "UnmarshalTypeError" +} + +// Message returns the detailed message of the error, satisfying +// the awserr.Error interface. +func (e *UnmarshalTypeError) Message() string { + return "cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() +} + +// An InvalidUnmarshalError is an error type representing an invalid type +// encountered while unmarshaling a AttributeValue to a Go value type. +type InvalidUnmarshalError struct { + emptyOrigError + Type reflect.Type +} + +// Error returns the string representation of the error. +// satisfying the error interface +func (e *InvalidUnmarshalError) Error() string { + return fmt.Sprintf("%s: %s", e.Code(), e.Message()) +} + +// Code returns the code of the error, satisfying the awserr.Error +// interface. +func (e *InvalidUnmarshalError) Code() string { + return "InvalidUnmarshalError" +} + +// Message returns the detailed message of the error, satisfying +// the awserr.Error interface. +func (e *InvalidUnmarshalError) Message() string { + if e.Type == nil { + return "cannot unmarshal to nil value" + } + if e.Type.Kind() != reflect.Ptr { + return "cannot unmarshal to non-pointer value, got " + e.Type.String() + } + return "cannot unmarshal to nil value, " + e.Type.String() +} + +// An UnmarshalError wraps an error that occured while unmarshaling a DynamoDB +// AttributeValue element into a Go type. This is different from UnmarshalTypeError +// in that it wraps the underlying error that occured. +type UnmarshalError struct { + Err error + Value string + Type reflect.Type +} + +// Error returns the string representation of the error. +// satisfying the error interface. +func (e *UnmarshalError) Error() string { + return fmt.Sprintf("%s: %s\ncaused by: %v", e.Code(), e.Message(), e.Err) +} + +// OrigErr returns the original error that caused this issue. +func (e UnmarshalError) OrigErr() error { + return e.Err +} + +// Code returns the code of the error, satisfying the awserr.Error +// interface. +func (e *UnmarshalError) Code() string { + return "UnmarshalError" +} + +// Message returns the detailed message of the error, satisfying +// the awserr.Error interface. +func (e *UnmarshalError) Message() string { + return fmt.Sprintf("cannot unmarshal %q into %s.", + e.Value, e.Type.String()) +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode_test.go new file mode 100644 index 0000000..1313064 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/decode_test.go @@ -0,0 +1,598 @@ +package dynamodbattribute + +import ( + "fmt" + "reflect" + "strconv" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +func TestUnmarshalErrorTypes(t *testing.T) { + var _ awserr.Error = (*UnmarshalTypeError)(nil) + var _ awserr.Error = (*InvalidUnmarshalError)(nil) +} + +func TestUnmarshalShared(t *testing.T) { + for i, c := range sharedTestCases { + err := Unmarshal(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +func TestUnmarshal(t *testing.T) { + cases := []struct { + in *dynamodb.AttributeValue + actual, expected interface{} + err error + }{ + //------------ + // Sets + //------------ + { + in: &dynamodb.AttributeValue{BS: [][]byte{ + {48, 49}, {50, 51}, + }}, + actual: &[][]byte{}, + expected: [][]byte{{48, 49}, {50, 51}}, + }, + { + in: &dynamodb.AttributeValue{NS: []*string{ + aws.String("123"), aws.String("321"), + }}, + actual: &[]int{}, + expected: []int{123, 321}, + }, + { + in: &dynamodb.AttributeValue{NS: []*string{ + aws.String("123"), aws.String("321"), + }}, + actual: &[]interface{}{}, + expected: []interface{}{123., 321.}, + }, + { + in: &dynamodb.AttributeValue{SS: []*string{ + aws.String("abc"), aws.String("123"), + }}, + actual: &[]string{}, + expected: &[]string{"abc", "123"}, + }, + { + in: &dynamodb.AttributeValue{SS: []*string{ + aws.String("abc"), aws.String("123"), + }}, + actual: &[]*string{}, + expected: &[]*string{aws.String("abc"), aws.String("123")}, + }, + //------------ + // Interfaces + //------------ + { + in: &dynamodb.AttributeValue{B: []byte{48, 49}}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: []byte{48, 49}, + }, + { + in: &dynamodb.AttributeValue{BS: [][]byte{ + {48, 49}, {50, 51}, + }}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: [][]byte{{48, 49}, {50, 51}}, + }, + { + in: &dynamodb.AttributeValue{BOOL: aws.Bool(true)}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: bool(true), + }, + { + in: &dynamodb.AttributeValue{L: []*dynamodb.AttributeValue{ + {S: aws.String("abc")}, {S: aws.String("123")}, + }}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: []interface{}{"abc", "123"}, + }, + { + in: &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{ + "123": {S: aws.String("abc")}, + "abc": {S: aws.String("123")}, + }}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: map[string]interface{}{"123": "abc", "abc": "123"}, + }, + { + in: &dynamodb.AttributeValue{N: aws.String("123")}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: float64(123), + }, + { + in: &dynamodb.AttributeValue{NS: []*string{ + aws.String("123"), aws.String("321"), + }}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: []float64{123., 321.}, + }, + { + in: &dynamodb.AttributeValue{S: aws.String("123")}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: "123", + }, + { + in: &dynamodb.AttributeValue{SS: []*string{ + aws.String("123"), aws.String("321"), + }}, + actual: func() interface{} { + var v interface{} + return &v + }(), + expected: []string{"123", "321"}, + }, + { + in: &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{ + "abc": {S: aws.String("123")}, + "Cba": {S: aws.String("321")}, + }}, + actual: &struct{ Abc, Cba string }{}, + expected: struct{ Abc, Cba string }{Abc: "123", Cba: "321"}, + }, + { + in: &dynamodb.AttributeValue{N: aws.String("512")}, + actual: new(uint8), + err: &UnmarshalTypeError{ + Value: fmt.Sprintf("number overflow, 512"), + Type: reflect.TypeOf(uint8(0)), + }, + }, + } + + for i, c := range cases { + err := Unmarshal(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +func TestInterfaceInput(t *testing.T) { + var v interface{} + expected := []interface{}{"abc", "123"} + err := Unmarshal(&dynamodb.AttributeValue{L: []*dynamodb.AttributeValue{ + {S: aws.String("abc")}, {S: aws.String("123")}, + }}, &v) + assertConvertTest(t, 0, v, expected, err, nil) +} + +func TestUnmarshalError(t *testing.T) { + cases := []struct { + in *dynamodb.AttributeValue + actual, expected interface{} + err error + }{ + { + in: &dynamodb.AttributeValue{}, + actual: int(0), + expected: nil, + err: &InvalidUnmarshalError{Type: reflect.TypeOf(int(0))}, + }, + } + + for i, c := range cases { + err := Unmarshal(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +func TestUnmarshalListShared(t *testing.T) { + for i, c := range sharedListTestCases { + err := UnmarshalList(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +func TestUnmarshalListError(t *testing.T) { + cases := []struct { + in []*dynamodb.AttributeValue + actual, expected interface{} + err error + }{ + { + in: []*dynamodb.AttributeValue{}, + actual: []interface{}{}, + expected: nil, + err: &InvalidUnmarshalError{Type: reflect.TypeOf([]interface{}{})}, + }, + } + + for i, c := range cases { + err := UnmarshalList(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +func TestUnmarshalMapShared(t *testing.T) { + for i, c := range sharedMapTestCases { + err := UnmarshalMap(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +func TestUnmarshalMapError(t *testing.T) { + cases := []struct { + in map[string]*dynamodb.AttributeValue + actual, expected interface{} + err error + }{ + { + in: map[string]*dynamodb.AttributeValue{}, + actual: map[string]interface{}{}, + expected: nil, + err: &InvalidUnmarshalError{Type: reflect.TypeOf(map[string]interface{}{})}, + }, + { + in: map[string]*dynamodb.AttributeValue{ + "BOOL": {BOOL: aws.Bool(true)}, + }, + actual: &map[int]interface{}{}, + expected: nil, + err: &UnmarshalTypeError{Value: "map string key", Type: reflect.TypeOf(int(0))}, + }, + } + + for i, c := range cases { + err := UnmarshalMap(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +func TestUnmarshalListOfMaps(t *testing.T) { + type testItem struct { + Value string + Value2 int + } + + cases := []struct { + in []map[string]*dynamodb.AttributeValue + actual, expected interface{} + err error + }{ + { // Simple map conversion. + in: []map[string]*dynamodb.AttributeValue{ + { + "Value": &dynamodb.AttributeValue{ + BOOL: aws.Bool(true), + }, + }, + }, + actual: &[]map[string]interface{}{}, + expected: []map[string]interface{}{ + { + "Value": true, + }, + }, + }, + { // attribute to struct. + in: []map[string]*dynamodb.AttributeValue{ + { + "Value": &dynamodb.AttributeValue{ + S: aws.String("abc"), + }, + "Value2": &dynamodb.AttributeValue{ + N: aws.String("123"), + }, + }, + }, + actual: &[]testItem{}, + expected: []testItem{ + { + Value: "abc", + Value2: 123, + }, + }, + }, + } + + for i, c := range cases { + err := UnmarshalListOfMaps(c.in, c.actual) + assertConvertTest(t, i, c.actual, c.expected, err, c.err) + } +} + +type unmarshalUnmarshaler struct { + Value string + Value2 int + Value3 bool + Value4 time.Time +} + +func (u *unmarshalUnmarshaler) UnmarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error { + if av.M == nil { + return fmt.Errorf("expected AttributeValue to be map") + } + + if v, ok := av.M["abc"]; !ok { + return fmt.Errorf("expected `abc` map key") + } else if v.S == nil { + return fmt.Errorf("expected `abc` map value string") + } else { + u.Value = *v.S + } + + if v, ok := av.M["def"]; !ok { + return fmt.Errorf("expected `def` map key") + } else if v.N == nil { + return fmt.Errorf("expected `def` map value number") + } else { + n, err := strconv.ParseInt(*v.N, 10, 64) + if err != nil { + return err + } + u.Value2 = int(n) + } + + if v, ok := av.M["ghi"]; !ok { + return fmt.Errorf("expected `ghi` map key") + } else if v.BOOL == nil { + return fmt.Errorf("expected `ghi` map value number") + } else { + u.Value3 = *v.BOOL + } + + if v, ok := av.M["jkl"]; !ok { + return fmt.Errorf("expected `jkl` map key") + } else if v.S == nil { + return fmt.Errorf("expected `jkl` map value string") + } else { + t, err := time.Parse(time.RFC3339, *v.S) + if err != nil { + return err + } + u.Value4 = t + } + + return nil +} + +func TestUnmarshalUnmashaler(t *testing.T) { + u := &unmarshalUnmarshaler{} + av := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "abc": {S: aws.String("value")}, + "def": {N: aws.String("123")}, + "ghi": {BOOL: aws.Bool(true)}, + "jkl": {S: aws.String("2016-05-03T17:06:26.209072Z")}, + }, + } + + err := Unmarshal(av, u) + if err != nil { + t.Errorf("expect no error, got %v", err) + } + + if e, a := "value", u.Value; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := 123, u.Value2; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := true, u.Value3; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := testDate, u.Value4; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestDecodeUseNumber(t *testing.T) { + u := map[string]interface{}{} + av := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "abc": {S: aws.String("value")}, + "def": {N: aws.String("123")}, + "ghi": {BOOL: aws.Bool(true)}, + }, + } + + decoder := NewDecoder(func(d *Decoder) { + d.UseNumber = true + }) + err := decoder.Decode(av, &u) + if err != nil { + t.Errorf("expect no error, got %v", err) + } + + if e, a := "value", u["abc"]; e != a { + t.Errorf("expect %v, got %v", e, a) + } + n := u["def"].(Number) + if e, a := "123", n.String(); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := true, u["ghi"]; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestDecodeUseNumberNumberSet(t *testing.T) { + u := map[string]interface{}{} + av := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "ns": { + NS: []*string{ + aws.String("123"), aws.String("321"), + }, + }, + }, + } + + decoder := NewDecoder(func(d *Decoder) { + d.UseNumber = true + }) + err := decoder.Decode(av, &u) + if err != nil { + t.Errorf("expect no error, got %v", err) + } + + ns := u["ns"].([]Number) + + if e, a := "123", ns[0].String(); e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := "321", ns[1].String(); e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestDecodeEmbeddedPointerStruct(t *testing.T) { + type B struct { + Bint int + } + type C struct { + Cint int + } + type A struct { + Aint int + *B + *C + } + av := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Aint": { + N: aws.String("321"), + }, + "Bint": { + N: aws.String("123"), + }, + }, + } + decoder := NewDecoder() + a := A{} + err := decoder.Decode(av, &a) + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if e, a := 321, a.Aint; e != a { + t.Errorf("expect %v, got %v", e, a) + } + // Embedded pointer struct can be created automatically. + if e, a := 123, a.Bint; e != a { + t.Errorf("expect %v, got %v", e, a) + } + // But not for absent fields. + if a.C != nil { + t.Errorf("expect nil, got %v", a.C) + } +} + +func TestDecodeBooleanOverlay(t *testing.T) { + type BooleanOverlay bool + + av := &dynamodb.AttributeValue{ + BOOL: aws.Bool(true), + } + + decoder := NewDecoder() + + var v BooleanOverlay + + err := decoder.Decode(av, &v) + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if e, a := BooleanOverlay(true), v; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestDecodeUnixTime(t *testing.T) { + type A struct { + Normal time.Time + Tagged time.Time `dynamodbav:",unixtime"` + Typed UnixTime + } + + expect := A{ + Normal: time.Unix(123, 0).UTC(), + Tagged: time.Unix(456, 0), + Typed: UnixTime(time.Unix(789, 0)), + } + + input := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Normal": { + S: aws.String("1970-01-01T00:02:03Z"), + }, + "Tagged": { + N: aws.String("456"), + }, + "Typed": { + N: aws.String("789"), + }, + }, + } + actual := A{} + + err := Unmarshal(input, &actual) + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if e, a := expect, actual; e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestDecodeAliasedUnixTime(t *testing.T) { + type A struct { + Normal AliasedTime + Tagged AliasedTime `dynamodbav:",unixtime"` + } + + expect := A{ + Normal: AliasedTime(time.Unix(123, 0).UTC()), + Tagged: AliasedTime(time.Unix(456, 0)), + } + + input := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Normal": { + S: aws.String("1970-01-01T00:02:03Z"), + }, + "Tagged": { + N: aws.String("456"), + }, + }, + } + actual := A{} + + err := Unmarshal(input, &actual) + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if expect != actual { + t.Errorf("expect %v, got %v", expect, actual) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/doc.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/doc.go new file mode 100644 index 0000000..7a51ac0 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/doc.go @@ -0,0 +1,95 @@ +// Package dynamodbattribute provides marshaling and unmarshaling utilities to +// convert between Go types and dynamodb.AttributeValues. +// +// These utilities allow you to marshal slices, maps, structs, and scalar values +// to and from dynamodb.AttributeValue. These are useful when marshaling +// Go value tyes to dynamodb.AttributeValue for DynamoDB requests, or +// unmarshaling the dynamodb.AttributeValue back into a Go value type. +// +// AttributeValue Marshaling +// +// To marshal a Go type to a dynamodbAttributeValue you can use the Marshal +// functions in the dynamodbattribute package. There are specialized versions +// of these functions for collections of Attributevalue, such as maps and lists. +// +// The following example uses MarshalMap to convert the Record Go type to a +// dynamodb.AttributeValue type and use the value to make a PutItem API request. +// +// type Record struct { +// ID string +// URLs []string +// } +// +// //... +// +// r := Record{ +// ID: "ABC123", +// URLs: []string{ +// "https://example.com/first/link", +// "https://example.com/second/url", +// }, +// } +// av, err := dynamodbattribute.MarshalMap(r) +// if err != nil { +// panic(fmt.Sprintf("failed to DynamoDB marshal Record, %v", err)) +// } +// +// _, err = svc.PutItem(&dynamodb.PutItemInput{ +// TableName: aws.String(myTableName), +// Item: av, +// }) +// if err != nil { +// panic(fmt.Sprintf("failed to put Record to DynamoDB, %v", err)) +// } +// +// AttributeValue Unmarshaling +// +// To unmarshal a dynamodb.AttributeValue to a Go type you can use the Unmarshal +// functions in the dynamodbattribute package. There are specialized versions +// of these functions for collections of Attributevalue, such as maps and lists. +// +// The following example will unmarshal the DynamoDB's Scan API operation. The +// Items returned by the operation will be unmarshaled into the slice of Records +// Go type. +// +// type Record struct { +// ID string +// URLs []string +// } +// +// //... +// +// var records []Record +// +// // Use the ScanPages method to perform the scan with pagination. Use +// // just Scan method to make the API call without pagination. +// err := svc.ScanPages(&dynamodb.ScanInput{ +// TableName: aws.String(myTableName), +// }, func(page *dynamodb.ScanOutput, last bool) bool { +// recs := []Record{} +// +// err := dynamodbattribute.UnmarshalListOfMaps(page.Items, &recs) +// if err != nil { +// panic(fmt.Sprintf("failed to unmarshal Dynamodb Scan Items, %v", err)) +// } +// +// records = append(records, recs...) +// +// return true // keep paging +// }) +// +// The ConvertTo, ConvertToList, ConvertToMap, ConvertFrom, ConvertFromMap +// and ConvertFromList methods have been deprecated. The Marshal and Unmarshal +// functions should be used instead. The ConvertTo|From marshallers do not +// support BinarySet, NumberSet, nor StringSets, and will incorrect marshal +// binary data fields in structs as base64 strings. +// +// The Marshal and Unmarshal functions correct this behavior, and removes +// the reliance on encoding.json. `json` struct tags are still supported. In +// addition support for a new struct tag `dynamodbav` was added. Support for +// the json.Marshaler and json.Unmarshaler interfaces have been removed and +// replaced with have been replaced with dynamodbattribute.Marshaler and +// dynamodbattribute.Unmarshaler interfaces. +// +// `time.Time` is marshaled as RFC3339 format. +package dynamodbattribute diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode.go new file mode 100644 index 0000000..fb30eff --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode.go @@ -0,0 +1,641 @@ +package dynamodbattribute + +import ( + "fmt" + "reflect" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +// An UnixTime provides aliasing of time.Time into a type that when marshaled +// and unmarshaled with DynamoDB AttributeValues it will be done so as number +// instead of string in seconds since January 1, 1970 UTC. +// +// This type is useful as an alternative to the struct tag `unixtime` when you +// want to have your time value marshaled as Unix time in seconds intead of +// the default time.RFC3339. +// +// Important to note that zero value time as unixtime is not 0 seconds +// from January 1, 1970 UTC, but -62135596800. Which is seconds between +// January 1, 0001 UTC, and January 1, 0001 UTC. +type UnixTime time.Time + +// MarshalDynamoDBAttributeValue implements the Marshaler interface so that +// the UnixTime can be marshaled from to a DynamoDB AttributeValue number +// value encoded in the number of seconds since January 1, 1970 UTC. +func (e UnixTime) MarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error { + t := time.Time(e) + s := strconv.FormatInt(t.Unix(), 10) + av.N = &s + + return nil +} + +// UnmarshalDynamoDBAttributeValue implements the Unmarshaler interface so that +// the UnixTime can be unmarshaled from a DynamoDB AttributeValue number representing +// the number of seconds since January 1, 1970 UTC. +// +// If an error parsing the AttributeValue number occurs UnmarshalError will be +// returned. +func (e *UnixTime) UnmarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error { + t, err := decodeUnixTime(aws.StringValue(av.N)) + if err != nil { + return err + } + + *e = UnixTime(t) + return nil +} + +// A Marshaler is an interface to provide custom marshaling of Go value types +// to AttributeValues. Use this to provide custom logic determining how a +// Go Value type should be marshaled. +// +// type ExampleMarshaler struct { +// Value int +// } +// func (m *ExampleMarshaler) MarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error { +// n := fmt.Sprintf("%v", m.Value) +// av.N = &n +// return nil +// } +// +type Marshaler interface { + MarshalDynamoDBAttributeValue(*dynamodb.AttributeValue) error +} + +// Marshal will serialize the passed in Go value type into a DynamoDB AttributeValue +// type. This value can be used in DynamoDB API operations to simplify marshaling +// your Go value types into AttributeValues. +// +// Marshal will recursively transverse the passed in value marshaling its +// contents into a AttributeValue. Marshal supports basic scalars +// (int,uint,float,bool,string), maps, slices, and structs. Anonymous +// nested types are flattened based on Go anonymous type visibility. +// +// Marshaling slices to AttributeValue will default to a List for all +// types except for []byte and [][]byte. []byte will be marshaled as +// Binary data (B), and [][]byte will be marshaled as binary data set +// (BS). +// +// `dynamodbav` struct tag can be used to control how the value will be +// marshaled into a AttributeValue. +// +// // Field is ignored +// Field int `dynamodbav:"-"` +// +// // Field AttributeValue map key "myName" +// Field int `dynamodbav:"myName"` +// +// // Field AttributeValue map key "myName", and +// // Field is omitted if it is empty +// Field int `dynamodbav:"myName,omitempty"` +// +// // Field AttributeValue map key "Field", and +// // Field is omitted if it is empty +// Field int `dynamodbav:",omitempty"` +// +// // Field's elems will be omitted if empty +// // only valid for slices, and maps. +// Field []string `dynamodbav:",omitemptyelem"` +// +// // Field will be marshaled as a AttributeValue string +// // only value for number types, (int,uint,float) +// Field int `dynamodbav:",string"` +// +// // Field will be marshaled as a binary set +// Field [][]byte `dynamodbav:",binaryset"` +// +// // Field will be marshaled as a number set +// Field []int `dynamodbav:",numberset"` +// +// // Field will be marshaled as a string set +// Field []string `dynamodbav:",stringset"` +// +// // Field will be marshaled as Unix time number in seconds. +// // This tag is only valid with time.Time typed struct fields. +// // Important to note that zero value time as unixtime is not 0 seconds +// // from January 1, 1970 UTC, but -62135596800. Which is seconds between +// // January 1, 0001 UTC, and January 1, 0001 UTC. +// Field time.Time `dynamodbav:",unixtime"` +// +// The omitempty tag is only used during Marshaling and is ignored for +// Unmarshal. Any zero value or a value when marshaled results in a +// AttributeValue NULL will be added to AttributeValue Maps during struct +// marshal. The omitemptyelem tag works the same as omitempty except it +// applies to maps and slices instead of struct fields, and will not be +// included in the marshaled AttributeValue Map, List, or Set. +// +// For convenience and backwards compatibility with ConvertTo functions +// json struct tags are supported by the Marshal and Unmarshal. If +// both json and dynamodbav struct tags are provided the json tag will +// be ignored in favor of dynamodbav. +// +// All struct fields and with anonymous fields, are marshaled unless the +// any of the following conditions are meet. +// +// - the field is not exported +// - json or dynamodbav field tag is "-" +// - json or dynamodbav field tag specifies "omitempty", and is empty. +// +// Pointer and interfaces values encode as the value pointed to or contained +// in the interface. A nil value encodes as the AttributeValue NULL value. +// +// Channel, complex, and function values are not encoded and will be skipped +// when walking the value to be marshaled. +// +// When marshaling any error that occurs will halt the marshal and return +// the error. +// +// Marshal cannot represent cyclic data structures and will not handle them. +// Passing cyclic structures to Marshal will result in an infinite recursion. +func Marshal(in interface{}) (*dynamodb.AttributeValue, error) { + return NewEncoder().Encode(in) +} + +// MarshalMap is an alias for Marshal func which marshals Go value +// type to a map of AttributeValues. +// +// This is useful for DynamoDB APIs such as PutItem. +func MarshalMap(in interface{}) (map[string]*dynamodb.AttributeValue, error) { + av, err := NewEncoder().Encode(in) + if err != nil || av == nil || av.M == nil { + return map[string]*dynamodb.AttributeValue{}, err + } + + return av.M, nil +} + +// MarshalList is an alias for Marshal func which marshals Go value +// type to a slice of AttributeValues. +func MarshalList(in interface{}) ([]*dynamodb.AttributeValue, error) { + av, err := NewEncoder().Encode(in) + if err != nil || av == nil || av.L == nil { + return []*dynamodb.AttributeValue{}, err + } + + return av.L, nil +} + +// A MarshalOptions is a collection of options shared between marshaling +// and unmarshaling +type MarshalOptions struct { + // States that the encoding/json struct tags should be supported. + // if a `dynamodbav` struct tag is also provided the encoding/json + // tag will be ignored. + // + // Enabled by default. + SupportJSONTags bool +} + +// An Encoder provides marshaling Go value types to AttributeValues. +type Encoder struct { + MarshalOptions + + // Empty strings, "", will be marked as NULL AttributeValue types. + // Empty strings are not valid values for DynamoDB. Will not apply + // to lists, sets, or maps. Use the struct tag `omitemptyelem` + // to skip empty (zero) values in lists, sets and maps. + // + // Enabled by default. + NullEmptyString bool +} + +// NewEncoder creates a new Encoder with default configuration. Use +// the `opts` functional options to override the default configuration. +func NewEncoder(opts ...func(*Encoder)) *Encoder { + e := &Encoder{ + MarshalOptions: MarshalOptions{ + SupportJSONTags: true, + }, + NullEmptyString: true, + } + for _, o := range opts { + o(e) + } + + return e +} + +// Encode will marshal a Go value type to an AttributeValue. Returning +// the AttributeValue constructed or error. +func (e *Encoder) Encode(in interface{}) (*dynamodb.AttributeValue, error) { + av := &dynamodb.AttributeValue{} + if err := e.encode(av, reflect.ValueOf(in), tag{}); err != nil { + return nil, err + } + + return av, nil +} + +func fieldByIndex(v reflect.Value, index []int, + OnEmbeddedNilStruct func(*reflect.Value) bool) reflect.Value { + fv := v + for i, x := range index { + if i > 0 { + if fv.Kind() == reflect.Ptr && fv.Type().Elem().Kind() == reflect.Struct { + if fv.IsNil() && !OnEmbeddedNilStruct(&fv) { + break + } + fv = fv.Elem() + } + } + fv = fv.Field(x) + } + return fv +} + +func (e *Encoder) encode(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error { + // We should check for omitted values first before dereferencing. + if fieldTag.OmitEmpty && emptyValue(v) { + encodeNull(av) + return nil + } + + // Handle both pointers and interface conversion into types + v = valueElem(v) + + if v.Kind() != reflect.Invalid { + if used, err := tryMarshaler(av, v); used { + return err + } + } + + switch v.Kind() { + case reflect.Invalid: + encodeNull(av) + case reflect.Struct: + return e.encodeStruct(av, v, fieldTag) + case reflect.Map: + return e.encodeMap(av, v, fieldTag) + case reflect.Slice, reflect.Array: + return e.encodeSlice(av, v, fieldTag) + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + // do nothing for unsupported types + default: + return e.encodeScalar(av, v, fieldTag) + } + + return nil +} + +func (e *Encoder) encodeStruct(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error { + // To maintain backwards compatibility with ConvertTo family of methods which + // converted time.Time structs to strings + if v.Type().ConvertibleTo(timeType) { + var t time.Time + t = v.Convert(timeType).Interface().(time.Time) + if fieldTag.AsUnixTime { + return UnixTime(t).MarshalDynamoDBAttributeValue(av) + } + s := t.Format(time.RFC3339Nano) + av.S = &s + return nil + } + + av.M = map[string]*dynamodb.AttributeValue{} + fields := unionStructFields(v.Type(), e.MarshalOptions) + for _, f := range fields { + if f.Name == "" { + return &InvalidMarshalError{msg: "map key cannot be empty"} + } + + found := true + fv := fieldByIndex(v, f.Index, func(v *reflect.Value) bool { + found = false + return false // to break the loop. + }) + if !found { + continue + } + elem := &dynamodb.AttributeValue{} + err := e.encode(elem, fv, f.tag) + if err != nil { + return err + } + skip, err := keepOrOmitEmpty(f.OmitEmpty, elem, err) + if err != nil { + return err + } else if skip { + continue + } + + av.M[f.Name] = elem + } + if len(av.M) == 0 { + encodeNull(av) + } + + return nil +} + +func (e *Encoder) encodeMap(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error { + av.M = map[string]*dynamodb.AttributeValue{} + for _, key := range v.MapKeys() { + keyName := fmt.Sprint(key.Interface()) + if keyName == "" { + return &InvalidMarshalError{msg: "map key cannot be empty"} + } + + elemVal := v.MapIndex(key) + elem := &dynamodb.AttributeValue{} + err := e.encode(elem, elemVal, tag{}) + skip, err := keepOrOmitEmpty(fieldTag.OmitEmptyElem, elem, err) + if err != nil { + return err + } else if skip { + continue + } + + av.M[keyName] = elem + } + if len(av.M) == 0 { + encodeNull(av) + } + + return nil +} + +func (e *Encoder) encodeSlice(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error { + switch v.Type().Elem().Kind() { + case reflect.Uint8: + slice := reflect.MakeSlice(byteSliceType, v.Len(), v.Len()) + reflect.Copy(slice, v) + + b := slice.Bytes() + if len(b) == 0 { + encodeNull(av) + return nil + } + av.B = append([]byte{}, b...) + default: + var elemFn func(dynamodb.AttributeValue) error + + if fieldTag.AsBinSet || v.Type() == byteSliceSlicetype { // Binary Set + av.BS = make([][]byte, 0, v.Len()) + elemFn = func(elem dynamodb.AttributeValue) error { + if elem.B == nil { + return &InvalidMarshalError{msg: "binary set must only contain non-nil byte slices"} + } + av.BS = append(av.BS, elem.B) + return nil + } + } else if fieldTag.AsNumSet { // Number Set + av.NS = make([]*string, 0, v.Len()) + elemFn = func(elem dynamodb.AttributeValue) error { + if elem.N == nil { + return &InvalidMarshalError{msg: "number set must only contain non-nil string numbers"} + } + av.NS = append(av.NS, elem.N) + return nil + } + } else if fieldTag.AsStrSet { // String Set + av.SS = make([]*string, 0, v.Len()) + elemFn = func(elem dynamodb.AttributeValue) error { + if elem.S == nil { + return &InvalidMarshalError{msg: "string set must only contain non-nil strings"} + } + av.SS = append(av.SS, elem.S) + return nil + } + } else { // List + av.L = make([]*dynamodb.AttributeValue, 0, v.Len()) + elemFn = func(elem dynamodb.AttributeValue) error { + av.L = append(av.L, &elem) + return nil + } + } + + if n, err := e.encodeList(v, fieldTag, elemFn); err != nil { + return err + } else if n == 0 { + encodeNull(av) + } + } + + return nil +} + +func (e *Encoder) encodeList(v reflect.Value, fieldTag tag, elemFn func(dynamodb.AttributeValue) error) (int, error) { + count := 0 + for i := 0; i < v.Len(); i++ { + elem := dynamodb.AttributeValue{} + err := e.encode(&elem, v.Index(i), tag{OmitEmpty: fieldTag.OmitEmptyElem}) + skip, err := keepOrOmitEmpty(fieldTag.OmitEmptyElem, &elem, err) + if err != nil { + return 0, err + } else if skip { + continue + } + + if err := elemFn(elem); err != nil { + return 0, err + } + count++ + } + + return count, nil +} + +func (e *Encoder) encodeScalar(av *dynamodb.AttributeValue, v reflect.Value, fieldTag tag) error { + if v.Type() == numberType { + s := v.String() + if fieldTag.AsString { + av.S = &s + } else { + av.N = &s + } + return nil + } + + switch v.Kind() { + case reflect.Bool: + av.BOOL = new(bool) + *av.BOOL = v.Bool() + case reflect.String: + if err := e.encodeString(av, v); err != nil { + return err + } + default: + // Fallback to encoding numbers, will return invalid type if not supported + if err := e.encodeNumber(av, v); err != nil { + return err + } + if fieldTag.AsString && av.NULL == nil && av.N != nil { + av.S = av.N + av.N = nil + } + } + + return nil +} + +func (e *Encoder) encodeNumber(av *dynamodb.AttributeValue, v reflect.Value) error { + if used, err := tryMarshaler(av, v); used { + return err + } + + var out string + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + out = encodeInt(v.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + out = encodeUint(v.Uint()) + case reflect.Float32, reflect.Float64: + out = encodeFloat(v.Float()) + default: + return &unsupportedMarshalTypeError{Type: v.Type()} + } + + av.N = &out + + return nil +} + +func (e *Encoder) encodeString(av *dynamodb.AttributeValue, v reflect.Value) error { + if used, err := tryMarshaler(av, v); used { + return err + } + + switch v.Kind() { + case reflect.String: + s := v.String() + if len(s) == 0 && e.NullEmptyString { + encodeNull(av) + } else { + av.S = &s + } + default: + return &unsupportedMarshalTypeError{Type: v.Type()} + } + + return nil +} + +func encodeInt(i int64) string { + return strconv.FormatInt(i, 10) +} +func encodeUint(u uint64) string { + return strconv.FormatUint(u, 10) +} +func encodeFloat(f float64) string { + return strconv.FormatFloat(f, 'f', -1, 64) +} +func encodeNull(av *dynamodb.AttributeValue) { + t := true + *av = dynamodb.AttributeValue{NULL: &t} +} + +func valueElem(v reflect.Value) reflect.Value { + switch v.Kind() { + case reflect.Interface, reflect.Ptr: + for v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr { + v = v.Elem() + } + } + + return v +} + +func emptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func tryMarshaler(av *dynamodb.AttributeValue, v reflect.Value) (bool, error) { + if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + v = v.Addr() + } + + if v.Type().NumMethod() == 0 { + return false, nil + } + + if m, ok := v.Interface().(Marshaler); ok { + return true, m.MarshalDynamoDBAttributeValue(av) + } + + return false, nil +} + +func keepOrOmitEmpty(omitEmpty bool, av *dynamodb.AttributeValue, err error) (bool, error) { + if err != nil { + if _, ok := err.(*unsupportedMarshalTypeError); ok { + return true, nil + } + return false, err + } + + if av.NULL != nil && omitEmpty { + return true, nil + } + + return false, nil +} + +// An InvalidMarshalError is an error type representing an error +// occurring when marshaling a Go value type to an AttributeValue. +type InvalidMarshalError struct { + emptyOrigError + msg string +} + +// Error returns the string representation of the error. +// satisfying the error interface +func (e *InvalidMarshalError) Error() string { + return fmt.Sprintf("%s: %s", e.Code(), e.Message()) +} + +// Code returns the code of the error, satisfying the awserr.Error +// interface. +func (e *InvalidMarshalError) Code() string { + return "InvalidMarshalError" +} + +// Message returns the detailed message of the error, satisfying +// the awserr.Error interface. +func (e *InvalidMarshalError) Message() string { + return e.msg +} + +// An unsupportedMarshalTypeError represents a Go value type +// which cannot be marshaled into an AttributeValue and should +// be skipped by the marshaler. +type unsupportedMarshalTypeError struct { + emptyOrigError + Type reflect.Type +} + +// Error returns the string representation of the error. +// satisfying the error interface +func (e *unsupportedMarshalTypeError) Error() string { + return fmt.Sprintf("%s: %s", e.Code(), e.Message()) +} + +// Code returns the code of the error, satisfying the awserr.Error +// interface. +func (e *unsupportedMarshalTypeError) Code() string { + return "unsupportedMarshalTypeError" +} + +// Message returns the detailed message of the error, satisfying +// the awserr.Error interface. +func (e *unsupportedMarshalTypeError) Message() string { + return "Go value type " + e.Type.String() + " is not supported" +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode_test.go new file mode 100644 index 0000000..deb1efd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/encode_test.go @@ -0,0 +1,271 @@ +package dynamodbattribute + +import ( + "fmt" + "reflect" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +func TestMarshalErrorTypes(t *testing.T) { + var _ awserr.Error = (*InvalidMarshalError)(nil) + var _ awserr.Error = (*unsupportedMarshalTypeError)(nil) +} + +func TestMarshalShared(t *testing.T) { + for i, c := range sharedTestCases { + av, err := Marshal(c.expected) + assertConvertTest(t, i, av, c.in, err, c.err) + } +} + +func TestMarshalListShared(t *testing.T) { + for i, c := range sharedListTestCases { + av, err := MarshalList(c.expected) + assertConvertTest(t, i, av, c.in, err, c.err) + } +} + +func TestMarshalMapShared(t *testing.T) { + for i, c := range sharedMapTestCases { + av, err := MarshalMap(c.expected) + assertConvertTest(t, i, av, c.in, err, c.err) + } +} + +type marshalMarshaler struct { + Value string + Value2 int + Value3 bool + Value4 time.Time +} + +func (m *marshalMarshaler) MarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error { + av.M = map[string]*dynamodb.AttributeValue{ + "abc": {S: &m.Value}, + "def": {N: aws.String(fmt.Sprintf("%d", m.Value2))}, + "ghi": {BOOL: &m.Value3}, + "jkl": {S: aws.String(m.Value4.Format(time.RFC3339Nano))}, + } + + return nil +} + +func TestMarshalMashaler(t *testing.T) { + m := &marshalMarshaler{ + Value: "value", + Value2: 123, + Value3: true, + Value4: testDate, + } + + expect := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "abc": {S: aws.String("value")}, + "def": {N: aws.String("123")}, + "ghi": {BOOL: aws.Bool(true)}, + "jkl": {S: aws.String("2016-05-03T17:06:26.209072Z")}, + }, + } + + actual, err := Marshal(m) + if err != nil { + t.Errorf("expect nil, got %v", err) + } + + if e, a := expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } +} + +type testOmitEmptyElemListStruct struct { + Values []string `dynamodbav:",omitemptyelem"` +} + +type testOmitEmptyElemMapStruct struct { + Values map[string]interface{} `dynamodbav:",omitemptyelem"` +} + +func TestMarshalListOmitEmptyElem(t *testing.T) { + expect := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Values": {L: []*dynamodb.AttributeValue{ + {S: aws.String("abc")}, + {S: aws.String("123")}, + }}, + }, + } + + m := testOmitEmptyElemListStruct{Values: []string{"abc", "", "123"}} + + actual, err := Marshal(m) + if err != nil { + t.Errorf("expect nil, got %v", err) + } + if e, a := expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestMarshalMapOmitEmptyElem(t *testing.T) { + expect := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Values": {M: map[string]*dynamodb.AttributeValue{ + "abc": {N: aws.String("123")}, + "klm": {S: aws.String("abc")}, + }}, + }, + } + + m := testOmitEmptyElemMapStruct{Values: map[string]interface{}{ + "abc": 123., + "efg": nil, + "hij": "", + "klm": "abc", + }} + + actual, err := Marshal(m) + if err != nil { + t.Errorf("expect nil, got %v", err) + } + if e, a := expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } +} + +type testOmitEmptyScalar struct { + IntZero int `dynamodbav:",omitempty"` + IntPtrNil *int `dynamodbav:",omitempty"` + IntPtrSetZero *int `dynamodbav:",omitempty"` +} + +func TestMarshalOmitEmpty(t *testing.T) { + expect := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "IntPtrSetZero": {N: aws.String("0")}, + }, + } + + m := testOmitEmptyScalar{IntPtrSetZero: aws.Int(0)} + + actual, err := Marshal(m) + if err != nil { + t.Errorf("expect nil, got %v", err) + } + if e, a := expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestEncodeEmbeddedPointerStruct(t *testing.T) { + type B struct { + Bint int + } + type C struct { + Cint int + } + type A struct { + Aint int + *B + *C + } + a := A{Aint: 321, B: &B{123}} + if e, a := 321, a.Aint; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if e, a := 123, a.Bint; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if a.C != nil { + t.Errorf("expect nil, got %v", a.C) + } + + actual, err := Marshal(a) + if err != nil { + t.Errorf("expect nil, got %v", err) + } + expect := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Aint": { + N: aws.String("321"), + }, + "Bint": { + N: aws.String("123"), + }, + }, + } + if e, a := expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestEncodeUnixTime(t *testing.T) { + type A struct { + Normal time.Time + Tagged time.Time `dynamodbav:",unixtime"` + Typed UnixTime + } + + a := A{ + Normal: time.Unix(123, 0).UTC(), + Tagged: time.Unix(456, 0), + Typed: UnixTime(time.Unix(789, 0)), + } + + actual, err := Marshal(a) + if err != nil { + t.Errorf("expect nil, got %v", err) + } + expect := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Normal": { + S: aws.String("1970-01-01T00:02:03Z"), + }, + "Tagged": { + N: aws.String("456"), + }, + "Typed": { + N: aws.String("789"), + }, + }, + } + if e, a := expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } +} + +type AliasedTime time.Time + +func TestEncodeAliasedUnixTime(t *testing.T) { + type A struct { + Normal AliasedTime + Tagged AliasedTime `dynamodbav:",unixtime"` + } + + a := A{ + Normal: AliasedTime(time.Unix(123, 0).UTC()), + Tagged: AliasedTime(time.Unix(456, 0)), + } + + actual, err := Marshal(a) + if err != nil { + t.Errorf("expect no err, got %v", err) + } + expect := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Normal": { + S: aws.String("1970-01-01T00:02:03Z"), + }, + "Tagged": { + N: aws.String("456"), + }, + }, + } + if e, a := expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field.go new file mode 100644 index 0000000..1fe0d35 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field.go @@ -0,0 +1,269 @@ +package dynamodbattribute + +import ( + "reflect" + "sort" + "strings" +) + +type field struct { + tag + + Name string + NameFromTag bool + + Index []int + Type reflect.Type +} + +func fieldByName(fields []field, name string) (field, bool) { + foldExists := false + foldField := field{} + + for _, f := range fields { + if f.Name == name { + return f, true + } + if !foldExists && strings.EqualFold(f.Name, name) { + foldField = f + foldExists = true + } + } + + return foldField, foldExists +} + +func buildField(pIdx []int, i int, sf reflect.StructField, fieldTag tag) field { + f := field{ + Name: sf.Name, + Type: sf.Type, + tag: fieldTag, + } + if len(fieldTag.Name) != 0 { + f.NameFromTag = true + f.Name = fieldTag.Name + } + + f.Index = make([]int, len(pIdx)+1) + copy(f.Index, pIdx) + f.Index[len(pIdx)] = i + + return f +} + +func unionStructFields(t reflect.Type, opts MarshalOptions) []field { + fields := enumFields(t, opts) + + sort.Sort(fieldsByName(fields)) + + fields = visibleFields(fields) + + return fields +} + +// enumFields will recursively iterate through a structure and its nested +// anonymous fields. +// +// Based on the enoding/json struct field enumeration of the Go Stdlib +// https://golang.org/src/encoding/json/encode.go typeField func. +func enumFields(t reflect.Type, opts MarshalOptions) []field { + // Fields to explore + current := []field{} + next := []field{{Type: t}} + + // count of queued names + count := map[reflect.Type]int{} + nextCount := map[reflect.Type]int{} + + visited := map[reflect.Type]struct{}{} + fields := []field{} + + for len(next) > 0 { + current, next = next, current[:0] + count, nextCount = nextCount, map[reflect.Type]int{} + + for _, f := range current { + if _, ok := visited[f.Type]; ok { + continue + } + visited[f.Type] = struct{}{} + + for i := 0; i < f.Type.NumField(); i++ { + sf := f.Type.Field(i) + if sf.PkgPath != "" && !sf.Anonymous { + // Ignore unexported and non-anonymous fields + // unexported but anonymous field may still be used if + // the type has exported nested fields + continue + } + + fieldTag := tag{} + fieldTag.parseAVTag(sf.Tag) + if opts.SupportJSONTags && fieldTag == (tag{}) { + fieldTag.parseJSONTag(sf.Tag) + } + + if fieldTag.Ignore { + continue + } + + ft := sf.Type + if ft.Name() == "" && ft.Kind() == reflect.Ptr { + ft = ft.Elem() + } + + structField := buildField(f.Index, i, sf, fieldTag) + structField.Type = ft + + if !sf.Anonymous || ft.Kind() != reflect.Struct { + fields = append(fields, structField) + if count[f.Type] > 1 { + // If there were multiple instances, add a second, + // so that the annihilation code will see a duplicate. + // It only cares about the distinction between 1 or 2, + // so don't bother generating any more copies. + fields = append(fields, structField) + } + continue + } + + // Record new anon struct to explore next round + nextCount[ft]++ + if nextCount[ft] == 1 { + next = append(next, structField) + } + } + } + } + + return fields +} + +// visibleFields will return a slice of fields which are visible based on +// Go's standard visiblity rules with the exception of ties being broken +// by depth and struct tag naming. +// +// Based on the enoding/json field filtering of the Go Stdlib +// https://golang.org/src/encoding/json/encode.go typeField func. +func visibleFields(fields []field) []field { + // Delete all fields that are hidden by the Go rules for embedded fields, + // except that fields with JSON tags are promoted. + + // The fields are sorted in primary order of name, secondary order + // of field index length. Loop over names; for each name, delete + // hidden fields by choosing the one dominant field that survives. + out := fields[:0] + for advance, i := 0, 0; i < len(fields); i += advance { + // One iteration per name. + // Find the sequence of fields with the name of this first field. + fi := fields[i] + name := fi.Name + for advance = 1; i+advance < len(fields); advance++ { + fj := fields[i+advance] + if fj.Name != name { + break + } + } + if advance == 1 { // Only one field with this name + out = append(out, fi) + continue + } + dominant, ok := dominantField(fields[i : i+advance]) + if ok { + out = append(out, dominant) + } + } + + fields = out + sort.Sort(fieldsByIndex(fields)) + + return fields +} + +// dominantField looks through the fields, all of which are known to +// have the same name, to find the single field that dominates the +// others using Go's embedding rules, modified by the presence of +// JSON tags. If there are multiple top-level fields, the boolean +// will be false: This condition is an error in Go and we skip all +// the fields. +// +// Based on the enoding/json field filtering of the Go Stdlib +// https://golang.org/src/encoding/json/encode.go dominantField func. +func dominantField(fields []field) (field, bool) { + // The fields are sorted in increasing index-length order. The winner + // must therefore be one with the shortest index length. Drop all + // longer entries, which is easy: just truncate the slice. + length := len(fields[0].Index) + tagged := -1 // Index of first tagged field. + for i, f := range fields { + if len(f.Index) > length { + fields = fields[:i] + break + } + if f.NameFromTag { + if tagged >= 0 { + // Multiple tagged fields at the same level: conflict. + // Return no field. + return field{}, false + } + tagged = i + } + } + if tagged >= 0 { + return fields[tagged], true + } + // All remaining fields have the same length. If there's more than one, + // we have a conflict (two fields named "X" at the same level) and we + // return no field. + if len(fields) > 1 { + return field{}, false + } + return fields[0], true +} + +// fieldsByName sorts field by name, breaking ties with depth, +// then breaking ties with "name came from json tag", then +// breaking ties with index sequence. +// +// Based on the enoding/json field filtering of the Go Stdlib +// https://golang.org/src/encoding/json/encode.go fieldsByName type. +type fieldsByName []field + +func (x fieldsByName) Len() int { return len(x) } + +func (x fieldsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func (x fieldsByName) Less(i, j int) bool { + if x[i].Name != x[j].Name { + return x[i].Name < x[j].Name + } + if len(x[i].Index) != len(x[j].Index) { + return len(x[i].Index) < len(x[j].Index) + } + if x[i].NameFromTag != x[j].NameFromTag { + return x[i].NameFromTag + } + return fieldsByIndex(x).Less(i, j) +} + +// fieldsByIndex sorts field by index sequence. +// +// Based on the enoding/json field filtering of the Go Stdlib +// https://golang.org/src/encoding/json/encode.go fieldsByIndex type. +type fieldsByIndex []field + +func (x fieldsByIndex) Len() int { return len(x) } + +func (x fieldsByIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func (x fieldsByIndex) Less(i, j int) bool { + for k, xik := range x[i].Index { + if k >= len(x[j].Index) { + return false + } + if xik != x[j].Index[k] { + return xik < x[j].Index[k] + } + } + return len(x[i].Index) < len(x[j].Index) +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field_test.go new file mode 100644 index 0000000..52eeb1c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/field_test.go @@ -0,0 +1,116 @@ +package dynamodbattribute + +import ( + "reflect" + "testing" +) + +type testUnionValues struct { + Name string + Value interface{} +} + +type unionSimple struct { + A int + B string + C []string +} + +type unionComplex struct { + unionSimple + A int +} + +type unionTagged struct { + A int `json:"A"` +} + +type unionTaggedComplex struct { + unionSimple + unionTagged + B string +} + +func TestUnionStructFields(t *testing.T) { + var cases = []struct { + in interface{} + expect []testUnionValues + }{ + { + in: unionSimple{1, "2", []string{"abc"}}, + expect: []testUnionValues{ + {"A", 1}, + {"B", "2"}, + {"C", []string{"abc"}}, + }, + }, + { + in: unionComplex{ + unionSimple: unionSimple{1, "2", []string{"abc"}}, + A: 2, + }, + expect: []testUnionValues{ + {"B", "2"}, + {"C", []string{"abc"}}, + {"A", 2}, + }, + }, + { + in: unionTaggedComplex{ + unionSimple: unionSimple{1, "2", []string{"abc"}}, + unionTagged: unionTagged{3}, + B: "3", + }, + expect: []testUnionValues{ + {"C", []string{"abc"}}, + {"A", 3}, + {"B", "3"}, + }, + }, + } + + for i, c := range cases { + v := reflect.ValueOf(c.in) + + fields := unionStructFields(v.Type(), MarshalOptions{SupportJSONTags: true}) + for j, f := range fields { + expected := c.expect[j] + if e, a := expected.Name, f.Name; e != a { + t.Errorf("%d:%d expect %v, got %v", i, j, e, f) + } + actual := v.FieldByIndex(f.Index).Interface() + if e, a := expected.Value, actual; !reflect.DeepEqual(e, a) { + t.Errorf("%d:%d expect %v, got %v", i, j, e, f) + } + } + } +} + +func TestFieldByName(t *testing.T) { + fields := []field{ + {Name: "Abc"}, {Name: "mixCase"}, {Name: "UPPERCASE"}, + } + + cases := []struct { + Name, FieldName string + Found bool + }{ + {"abc", "Abc", true}, {"ABC", "Abc", true}, {"Abc", "Abc", true}, + {"123", "", false}, + {"ab", "", false}, + {"MixCase", "mixCase", true}, + {"uppercase", "UPPERCASE", true}, {"UPPERCASE", "UPPERCASE", true}, + } + + for _, c := range cases { + f, ok := fieldByName(fields, c.Name) + if e, a := c.Found, ok; e != a { + t.Errorf("expect %v, got %v", e, a) + } + if ok { + if e, a := c.FieldName, f.Name; e != a { + t.Errorf("expect %v, got %v", e, a) + } + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_examples_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_examples_test.go new file mode 100644 index 0000000..049d3e7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_examples_test.go @@ -0,0 +1,104 @@ +package dynamodbattribute_test + +import ( + "fmt" + "reflect" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" +) + +func ExampleMarshal() { + type Record struct { + Bytes []byte + MyField string + Letters []string + Numbers []int + } + + r := Record{ + Bytes: []byte{48, 49}, + MyField: "MyFieldValue", + Letters: []string{"a", "b", "c", "d"}, + Numbers: []int{1, 2, 3}, + } + av, err := dynamodbattribute.Marshal(r) + fmt.Println("err", err) + fmt.Println("Bytes", av.M["Bytes"]) + fmt.Println("MyField", av.M["MyField"]) + fmt.Println("Letters", av.M["Letters"]) + fmt.Println("Numbers", av.M["Numbers"]) + + // Output: + // err + // Bytes { + // B: len 2 + // } + // MyField { + // S: "MyFieldValue" + // } + // Letters { + // L: [ + // { + // S: "a" + // }, + // { + // S: "b" + // }, + // { + // S: "c" + // }, + // { + // S: "d" + // } + // ] + // } + // Numbers { + // L: [{ + // N: "1" + // },{ + // N: "2" + // },{ + // N: "3" + // }] + // } +} + +func ExampleUnmarshal() { + type Record struct { + Bytes []byte + MyField string + Letters []string + A2Num map[string]int + } + + expect := Record{ + Bytes: []byte{48, 49}, + MyField: "MyFieldValue", + Letters: []string{"a", "b", "c", "d"}, + A2Num: map[string]int{"a": 1, "b": 2, "c": 3}, + } + + av := &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Bytes": {B: []byte{48, 49}}, + "MyField": {S: aws.String("MyFieldValue")}, + "Letters": {L: []*dynamodb.AttributeValue{ + {S: aws.String("a")}, {S: aws.String("b")}, {S: aws.String("c")}, {S: aws.String("d")}, + }}, + "A2Num": {M: map[string]*dynamodb.AttributeValue{ + "a": {N: aws.String("1")}, + "b": {N: aws.String("2")}, + "c": {N: aws.String("3")}, + }}, + }, + } + + actual := Record{} + err := dynamodbattribute.Unmarshal(av, &actual) + fmt.Println(err, reflect.DeepEqual(expect, actual)) + + // Output: + // true +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_test.go new file mode 100644 index 0000000..c589383 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/marshaler_test.go @@ -0,0 +1,573 @@ +package dynamodbattribute + +import ( + "math" + "reflect" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +type simpleMarshalStruct struct { + Byte []byte + String string + Int int + Uint uint + Float32 float32 + Float64 float64 + Bool bool + Null *interface{} +} + +type complexMarshalStruct struct { + Simple []simpleMarshalStruct +} + +type myByteStruct struct { + Byte []byte +} + +type myByteSetStruct struct { + ByteSet [][]byte +} + +type marshallerTestInput struct { + input interface{} + expected interface{} + err awserr.Error +} + +var marshalerScalarInputs = []marshallerTestInput{ + { + input: nil, + expected: &dynamodb.AttributeValue{NULL: &trueValue}, + }, + { + input: "some string", + expected: &dynamodb.AttributeValue{S: aws.String("some string")}, + }, + { + input: true, + expected: &dynamodb.AttributeValue{BOOL: &trueValue}, + }, + { + input: false, + expected: &dynamodb.AttributeValue{BOOL: &falseValue}, + }, + { + input: 3.14, + expected: &dynamodb.AttributeValue{N: aws.String("3.14")}, + }, + { + input: math.MaxFloat32, + expected: &dynamodb.AttributeValue{N: aws.String("340282346638528860000000000000000000000")}, + }, + { + input: math.MaxFloat64, + expected: &dynamodb.AttributeValue{N: aws.String("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")}, + }, + { + input: 12, + expected: &dynamodb.AttributeValue{N: aws.String("12")}, + }, + { + input: Number("12"), + expected: &dynamodb.AttributeValue{N: aws.String("12")}, + }, + { + input: simpleMarshalStruct{}, + expected: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Byte": {NULL: &trueValue}, + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {NULL: &trueValue}, + "Uint": {N: aws.String("0")}, + }, + }, + }, +} + +var marshallerMapTestInputs = []marshallerTestInput{ + // Scalar tests + { + input: nil, + expected: map[string]*dynamodb.AttributeValue{}, + }, + { + input: map[string]interface{}{"string": "some string"}, + expected: map[string]*dynamodb.AttributeValue{"string": {S: aws.String("some string")}}, + }, + { + input: map[string]interface{}{"bool": true}, + expected: map[string]*dynamodb.AttributeValue{"bool": {BOOL: &trueValue}}, + }, + { + input: map[string]interface{}{"bool": false}, + expected: map[string]*dynamodb.AttributeValue{"bool": {BOOL: &falseValue}}, + }, + { + input: map[string]interface{}{"null": nil}, + expected: map[string]*dynamodb.AttributeValue{"null": {NULL: &trueValue}}, + }, + { + input: map[string]interface{}{"float": 3.14}, + expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("3.14")}}, + }, + { + input: map[string]interface{}{"float": math.MaxFloat32}, + expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("340282346638528860000000000000000000000")}}, + }, + { + input: map[string]interface{}{"float": math.MaxFloat64}, + expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")}}, + }, + { + input: map[string]interface{}{"num": 12.}, + expected: map[string]*dynamodb.AttributeValue{"num": {N: aws.String("12")}}, + }, + { + input: map[string]interface{}{"byte": []byte{48, 49}}, + expected: map[string]*dynamodb.AttributeValue{"byte": {B: []byte{48, 49}}}, + }, + { + input: struct{ Byte []byte }{Byte: []byte{48, 49}}, + expected: map[string]*dynamodb.AttributeValue{"Byte": {B: []byte{48, 49}}}, + }, + { + input: map[string]interface{}{"byte_set": [][]byte{{48, 49}, {50, 51}}}, + expected: map[string]*dynamodb.AttributeValue{"byte_set": {BS: [][]byte{{48, 49}, {50, 51}}}}, + }, + { + input: struct{ ByteSet [][]byte }{ByteSet: [][]byte{{48, 49}, {50, 51}}}, + expected: map[string]*dynamodb.AttributeValue{"ByteSet": {BS: [][]byte{{48, 49}, {50, 51}}}}, + }, + // List + { + input: map[string]interface{}{"list": []interface{}{"a string", 12., 3.14, true, nil, false}}, + expected: map[string]*dynamodb.AttributeValue{ + "list": { + L: []*dynamodb.AttributeValue{ + {S: aws.String("a string")}, + {N: aws.String("12")}, + {N: aws.String("3.14")}, + {BOOL: &trueValue}, + {NULL: &trueValue}, + {BOOL: &falseValue}, + }, + }, + }, + }, + // Map + { + input: map[string]interface{}{"map": map[string]interface{}{"nestednum": 12.}}, + expected: map[string]*dynamodb.AttributeValue{ + "map": { + M: map[string]*dynamodb.AttributeValue{ + "nestednum": { + N: aws.String("12"), + }, + }, + }, + }, + }, + // Structs + { + input: simpleMarshalStruct{}, + expected: map[string]*dynamodb.AttributeValue{ + "Byte": {NULL: &trueValue}, + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {NULL: &trueValue}, + "Uint": {N: aws.String("0")}, + }, + }, + { + input: complexMarshalStruct{}, + expected: map[string]*dynamodb.AttributeValue{ + "Simple": {NULL: &trueValue}, + }, + }, + { + input: struct { + Simple []string `json:"simple"` + }{}, + expected: map[string]*dynamodb.AttributeValue{ + "simple": {NULL: &trueValue}, + }, + }, + { + input: struct { + Simple []string `json:"simple,omitempty"` + }{}, + expected: map[string]*dynamodb.AttributeValue{}, + }, + { + input: struct { + Simple []string `json:"-"` + }{}, + expected: map[string]*dynamodb.AttributeValue{}, + }, + { + input: complexMarshalStruct{Simple: []simpleMarshalStruct{{Int: -2}, {Uint: 5}}}, + expected: map[string]*dynamodb.AttributeValue{ + "Simple": { + L: []*dynamodb.AttributeValue{ + { + M: map[string]*dynamodb.AttributeValue{ + "Byte": {NULL: &trueValue}, + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("-2")}, + "Null": {NULL: &trueValue}, + "String": {NULL: &trueValue}, + "Uint": {N: aws.String("0")}, + }, + }, + { + M: map[string]*dynamodb.AttributeValue{ + "Byte": {NULL: &trueValue}, + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {NULL: &trueValue}, + "Uint": {N: aws.String("5")}, + }, + }, + }, + }, + }, + }, +} + +var marshallerListTestInputs = []marshallerTestInput{ + { + input: nil, + expected: []*dynamodb.AttributeValue{}, + }, + { + input: []interface{}{}, + expected: []*dynamodb.AttributeValue{}, + }, + { + input: []simpleMarshalStruct{}, + expected: []*dynamodb.AttributeValue{}, + }, + { + input: []interface{}{"a string", 12., 3.14, true, nil, false}, + expected: []*dynamodb.AttributeValue{ + {S: aws.String("a string")}, + {N: aws.String("12")}, + {N: aws.String("3.14")}, + {BOOL: &trueValue}, + {NULL: &trueValue}, + {BOOL: &falseValue}, + }, + }, + { + input: []simpleMarshalStruct{{}}, + expected: []*dynamodb.AttributeValue{ + { + M: map[string]*dynamodb.AttributeValue{ + "Byte": {NULL: &trueValue}, + "Bool": {BOOL: &falseValue}, + "Float32": {N: aws.String("0")}, + "Float64": {N: aws.String("0")}, + "Int": {N: aws.String("0")}, + "Null": {NULL: &trueValue}, + "String": {NULL: &trueValue}, + "Uint": {N: aws.String("0")}, + }, + }, + }, + }, +} + +func Test_New_Marshal(t *testing.T) { + for _, test := range marshalerScalarInputs { + testMarshal(t, test) + } +} + +func testMarshal(t *testing.T, test marshallerTestInput) { + actual, err := Marshal(test.input) + if test.err != nil { + if err == nil { + t.Errorf("Marshal with input %#v retured %#v, expected error `%s`", test.input, actual, test.err) + } else if err.Error() != test.err.Error() { + t.Errorf("Marshal with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err) + } + } else { + if err != nil { + t.Errorf("Marshal with input %#v retured error `%s`", test.input, err) + } + compareObjects(t, test.expected, actual) + } +} + +func Test_New_Unmarshal(t *testing.T) { + // Using the same inputs from Marshal, test the reverse mapping. + for i, test := range marshalerScalarInputs { + if test.input == nil { + continue + } + actual := reflect.New(reflect.TypeOf(test.input)).Interface() + if err := Unmarshal(test.expected.(*dynamodb.AttributeValue), actual); err != nil { + t.Errorf("Unmarshal %d, with input %#v retured error `%s`", i+1, test.expected, err) + } + compareObjects(t, test.input, reflect.ValueOf(actual).Elem().Interface()) + } +} + +func Test_New_UnmarshalError(t *testing.T) { + // Test that we get an error using Unmarshal to convert to a nil value. + expected := &InvalidUnmarshalError{Type: reflect.TypeOf(nil)} + if err := Unmarshal(nil, nil); err == nil { + t.Errorf("Unmarshal with input %T returned no error, expected error `%v`", nil, expected) + } else if err.Error() != expected.Error() { + t.Errorf("Unmarshal with input %T returned error `%v`, expected error `%v`", nil, err, expected) + } + + // Test that we get an error using Unmarshal to convert to a non-pointer value. + var actual map[string]interface{} + expected = &InvalidUnmarshalError{Type: reflect.TypeOf(actual)} + if err := Unmarshal(nil, actual); err == nil { + t.Errorf("Unmarshal with input %T returned no error, expected error `%v`", actual, expected) + } else if err.Error() != expected.Error() { + t.Errorf("Unmarshal with input %T returned error `%v`, expected error `%v`", actual, err, expected) + } + + // Test that we get an error using Unmarshal to convert to nil struct. + var actual2 *struct{ A int } + expected = &InvalidUnmarshalError{Type: reflect.TypeOf(actual2)} + if err := Unmarshal(nil, actual2); err == nil { + t.Errorf("Unmarshal with input %T returned no error, expected error `%v`", actual2, expected) + } else if err.Error() != expected.Error() { + t.Errorf("Unmarshal with input %T returned error `%v`, expected error `%v`", actual2, err, expected) + } +} + +func Test_New_MarshalMap(t *testing.T) { + for _, test := range marshallerMapTestInputs { + testMarshalMap(t, test) + } +} + +func testMarshalMap(t *testing.T, test marshallerTestInput) { + actual, err := MarshalMap(test.input) + if test.err != nil { + if err == nil { + t.Errorf("MarshalMap with input %#v retured %#v, expected error `%s`", test.input, actual, test.err) + } else if err.Error() != test.err.Error() { + t.Errorf("MarshalMap with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err) + } + } else { + if err != nil { + t.Errorf("MarshalMap with input %#v retured error `%s`", test.input, err) + } + compareObjects(t, test.expected, actual) + } +} + +func Test_New_UnmarshalMap(t *testing.T) { + // Using the same inputs from MarshalMap, test the reverse mapping. + for i, test := range marshallerMapTestInputs { + if test.input == nil { + continue + } + actual := reflect.New(reflect.TypeOf(test.input)).Interface() + if err := UnmarshalMap(test.expected.(map[string]*dynamodb.AttributeValue), actual); err != nil { + t.Errorf("Unmarshal %d, with input %#v retured error `%s`", i+1, test.expected, err) + } + compareObjects(t, test.input, reflect.ValueOf(actual).Elem().Interface()) + } +} + +func Test_New_UnmarshalMapError(t *testing.T) { + // Test that we get an error using UnmarshalMap to convert to a nil value. + expected := &InvalidUnmarshalError{Type: reflect.TypeOf(nil)} + if err := UnmarshalMap(nil, nil); err == nil { + t.Errorf("UnmarshalMap with input %T returned no error, expected error `%v`", nil, expected) + } else if err.Error() != expected.Error() { + t.Errorf("UnmarshalMap with input %T returned error `%v`, expected error `%v`", nil, err, expected) + } + + // Test that we get an error using UnmarshalMap to convert to a non-pointer value. + var actual map[string]interface{} + expected = &InvalidUnmarshalError{Type: reflect.TypeOf(actual)} + if err := UnmarshalMap(nil, actual); err == nil { + t.Errorf("UnmarshalMap with input %T returned no error, expected error `%v`", actual, expected) + } else if err.Error() != expected.Error() { + t.Errorf("UnmarshalMap with input %T returned error `%v`, expected error `%v`", actual, err, expected) + } + + // Test that we get an error using UnmarshalMap to convert to nil struct. + var actual2 *struct{ A int } + expected = &InvalidUnmarshalError{Type: reflect.TypeOf(actual2)} + if err := UnmarshalMap(nil, actual2); err == nil { + t.Errorf("UnmarshalMap with input %T returned no error, expected error `%v`", actual2, expected) + } else if err.Error() != expected.Error() { + t.Errorf("UnmarshalMap with input %T returned error `%v`, expected error `%v`", actual2, err, expected) + } +} + +func Test_New_MarshalList(t *testing.T) { + for _, test := range marshallerListTestInputs { + testMarshalList(t, test) + } +} + +func testMarshalList(t *testing.T, test marshallerTestInput) { + actual, err := MarshalList(test.input) + if test.err != nil { + if err == nil { + t.Errorf("MarshalList with input %#v retured %#v, expected error `%s`", test.input, actual, test.err) + } else if err.Error() != test.err.Error() { + t.Errorf("MarshalList with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err) + } + } else { + if err != nil { + t.Errorf("MarshalList with input %#v retured error `%s`", test.input, err) + } + compareObjects(t, test.expected, actual) + } +} + +func Test_New_UnmarshalList(t *testing.T) { + // Using the same inputs from MarshalList, test the reverse mapping. + for i, test := range marshallerListTestInputs { + if test.input == nil { + continue + } + iv := reflect.ValueOf(test.input) + + actual := reflect.New(iv.Type()) + if iv.Kind() == reflect.Slice { + actual.Elem().Set(reflect.MakeSlice(iv.Type(), iv.Len(), iv.Cap())) + } + + if err := UnmarshalList(test.expected.([]*dynamodb.AttributeValue), actual.Interface()); err != nil { + t.Errorf("Unmarshal %d, with input %#v retured error `%s`", i+1, test.expected, err) + } + compareObjects(t, test.input, actual.Elem().Interface()) + } +} + +func Test_New_UnmarshalListError(t *testing.T) { + // Test that we get an error using UnmarshalList to convert to a nil value. + expected := &InvalidUnmarshalError{Type: reflect.TypeOf(nil)} + if err := UnmarshalList(nil, nil); err == nil { + t.Errorf("UnmarshalList with input %T returned no error, expected error `%v`", nil, expected) + } else if err.Error() != expected.Error() { + t.Errorf("UnmarshalList with input %T returned error `%v`, expected error `%v`", nil, err, expected) + } + + // Test that we get an error using UnmarshalList to convert to a non-pointer value. + var actual map[string]interface{} + expected = &InvalidUnmarshalError{Type: reflect.TypeOf(actual)} + if err := UnmarshalList(nil, actual); err == nil { + t.Errorf("UnmarshalList with input %T returned no error, expected error `%v`", actual, expected) + } else if err.Error() != expected.Error() { + t.Errorf("UnmarshalList with input %T returned error `%v`, expected error `%v`", actual, err, expected) + } + + // Test that we get an error using UnmarshalList to convert to nil struct. + var actual2 *struct{ A int } + expected = &InvalidUnmarshalError{Type: reflect.TypeOf(actual2)} + if err := UnmarshalList(nil, actual2); err == nil { + t.Errorf("UnmarshalList with input %T returned no error, expected error `%v`", actual2, expected) + } else if err.Error() != expected.Error() { + t.Errorf("UnmarshalList with input %T returned error `%v`, expected error `%v`", actual2, err, expected) + } +} + +// see github issue #1594 +func TestDecodeArrayType(t *testing.T) { + cases := []struct { + to, from interface{} + }{ + { + &[2]int{1, 2}, + &[2]int{}, + }, + { + &[2]int64{1, 2}, + &[2]int64{}, + }, + { + &[2]byte{1, 2}, + &[2]byte{}, + }, + { + &[2]bool{true, false}, + &[2]bool{}, + }, + { + &[2]string{"1", "2"}, + &[2]string{}, + }, + { + &[2][]string{{"1", "2"}}, + &[2][]string{}, + }, + } + + for _, c := range cases { + marshaled, err := Marshal(c.to) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } + + if err = Unmarshal(marshaled, c.from); err != nil { + t.Errorf("expected no error, but received %v", err) + } + + if !reflect.DeepEqual(c.to, c.from) { + t.Errorf("expected %v, but received %v", c.to, c.from) + } + } +} + +func compareObjects(t *testing.T, expected interface{}, actual interface{}) { + if !reflect.DeepEqual(expected, actual) { + ev := reflect.ValueOf(expected) + av := reflect.ValueOf(actual) + t.Errorf("\nExpected kind(%s,%T):\n%s\nActual kind(%s,%T):\n%s\n", + ev.Kind(), + ev.Interface(), + awsutil.Prettify(expected), + av.Kind(), + ev.Interface(), + awsutil.Prettify(actual)) + } +} + +func BenchmarkMarshal(b *testing.B) { + d := simpleMarshalStruct{ + String: "abc", + Int: 123, + Uint: 123, + Float32: 123.321, + Float64: 123.321, + Bool: true, + Null: nil, + } + for i := 0; i < b.N; i++ { + _, err := Marshal(d) + if err != nil { + b.Fatal("unexpected error", err) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/shared_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/shared_test.go new file mode 100644 index 0000000..3e0568d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/shared_test.go @@ -0,0 +1,405 @@ +package dynamodbattribute + +import ( + "reflect" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +type testBinarySetStruct struct { + Binarys [][]byte `dynamodbav:",binaryset"` +} +type testNumberSetStruct struct { + Numbers []int `dynamodbav:",numberset"` +} +type testStringSetStruct struct { + Strings []string `dynamodbav:",stringset"` +} + +type testIntAsStringStruct struct { + Value int `dynamodbav:",string"` +} + +type testOmitEmptyStruct struct { + Value string `dynamodbav:",omitempty"` + Value2 *string `dynamodbav:",omitempty"` + Value3 int +} + +type testAliasedString string +type testAliasedStringSlice []string +type testAliasedInt int +type testAliasedIntSlice []int +type testAliasedMap map[string]int +type testAliasedSlice []string +type testAliasedByteSlice []byte +type testAliasedBool bool +type testAliasedBoolSlice []bool + +type testAliasedStruct struct { + Value testAliasedString + Value2 testAliasedInt + Value3 testAliasedMap + Value4 testAliasedSlice + + Value5 testAliasedByteSlice + Value6 []testAliasedInt + Value7 []testAliasedString + + Value8 []testAliasedByteSlice `dynamodbav:",binaryset"` + Value9 []testAliasedInt `dynamodbav:",numberset"` + Value10 []testAliasedString `dynamodbav:",stringset"` + + Value11 testAliasedIntSlice + Value12 testAliasedStringSlice + + Value13 testAliasedBool + Value14 testAliasedBoolSlice +} + +type testNamedPointer *int + +var testDate, _ = time.Parse(time.RFC3339, "2016-05-03T17:06:26.209072Z") + +var sharedTestCases = []struct { + in *dynamodb.AttributeValue + actual, expected interface{} + err error +}{ + { // Binary slice + in: &dynamodb.AttributeValue{B: []byte{48, 49}}, + actual: &[]byte{}, + expected: []byte{48, 49}, + }, + { // Binary slice + in: &dynamodb.AttributeValue{B: []byte{48, 49}}, + actual: &[]byte{}, + expected: []byte{48, 49}, + }, + { // Binary slice oversized + in: &dynamodb.AttributeValue{B: []byte{48, 49}}, + actual: func() *[]byte { + v := make([]byte, 0, 10) + return &v + }(), + expected: []byte{48, 49}, + }, + { // Binary slice pointer + in: &dynamodb.AttributeValue{B: []byte{48, 49}}, + actual: func() **[]byte { + v := make([]byte, 0, 10) + v2 := &v + return &v2 + }(), + expected: []byte{48, 49}, + }, + { // Bool + in: &dynamodb.AttributeValue{BOOL: aws.Bool(true)}, + actual: new(bool), + expected: true, + }, + { // List + in: &dynamodb.AttributeValue{L: []*dynamodb.AttributeValue{ + {N: aws.String("123")}, + }}, + actual: &[]int{}, + expected: []int{123}, + }, + { // Map, interface + in: &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{ + "abc": {N: aws.String("123")}, + }}, + actual: &map[string]int{}, + expected: map[string]int{"abc": 123}, + }, + { // Map, struct + in: &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{ + "Abc": {N: aws.String("123")}, + }}, + actual: &struct{ Abc int }{}, + expected: struct{ Abc int }{Abc: 123}, + }, + { // Map, struct + in: &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{ + "abc": {N: aws.String("123")}, + }}, + actual: &struct { + Abc int `json:"abc" dynamodbav:"abc"` + }{}, + expected: struct { + Abc int `json:"abc" dynamodbav:"abc"` + }{Abc: 123}, + }, + { // Number, int + in: &dynamodb.AttributeValue{N: aws.String("123")}, + actual: new(int), + expected: 123, + }, + { // Number, Float + in: &dynamodb.AttributeValue{N: aws.String("123.1")}, + actual: new(float64), + expected: float64(123.1), + }, + { // Null + in: &dynamodb.AttributeValue{NULL: aws.Bool(true)}, + actual: new(string), + expected: "", + }, + { // Null ptr + in: &dynamodb.AttributeValue{NULL: aws.Bool(true)}, + actual: new(*string), + expected: nil, + }, + { // String + in: &dynamodb.AttributeValue{S: aws.String("abc")}, + actual: new(string), + expected: "abc", + }, + { // Binary Set + in: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Binarys": {BS: [][]byte{{48, 49}, {50, 51}}}, + }, + }, + actual: &testBinarySetStruct{}, + expected: testBinarySetStruct{Binarys: [][]byte{{48, 49}, {50, 51}}}, + }, + { // Number Set + in: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Numbers": {NS: []*string{aws.String("123"), aws.String("321")}}, + }, + }, + actual: &testNumberSetStruct{}, + expected: testNumberSetStruct{Numbers: []int{123, 321}}, + }, + { // String Set + in: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Strings": {SS: []*string{aws.String("abc"), aws.String("efg")}}, + }, + }, + actual: &testStringSetStruct{}, + expected: testStringSetStruct{Strings: []string{"abc", "efg"}}, + }, + { // Int value as string + in: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Value": {S: aws.String("123")}, + }, + }, + actual: &testIntAsStringStruct{}, + expected: testIntAsStringStruct{Value: 123}, + }, + { // Omitempty + in: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Value3": {N: aws.String("0")}, + }, + }, + actual: &testOmitEmptyStruct{}, + expected: testOmitEmptyStruct{Value: "", Value2: nil, Value3: 0}, + }, + { // aliased type + in: &dynamodb.AttributeValue{ + M: map[string]*dynamodb.AttributeValue{ + "Value": {S: aws.String("123")}, + "Value2": {N: aws.String("123")}, + "Value3": {M: map[string]*dynamodb.AttributeValue{ + "Key": {N: aws.String("321")}, + }}, + "Value4": {L: []*dynamodb.AttributeValue{ + {S: aws.String("1")}, + {S: aws.String("2")}, + {S: aws.String("3")}, + }}, + "Value5": {B: []byte{0, 1, 2}}, + "Value6": {L: []*dynamodb.AttributeValue{ + {N: aws.String("1")}, + {N: aws.String("2")}, + {N: aws.String("3")}, + }}, + "Value7": {L: []*dynamodb.AttributeValue{ + {S: aws.String("1")}, + {S: aws.String("2")}, + {S: aws.String("3")}, + }}, + "Value8": {BS: [][]byte{ + {0, 1, 2}, {3, 4, 5}, + }}, + "Value9": {NS: []*string{ + aws.String("1"), + aws.String("2"), + aws.String("3"), + }}, + "Value10": {SS: []*string{ + aws.String("1"), + aws.String("2"), + aws.String("3"), + }}, + "Value11": {L: []*dynamodb.AttributeValue{ + {N: aws.String("1")}, + {N: aws.String("2")}, + {N: aws.String("3")}, + }}, + "Value12": {L: []*dynamodb.AttributeValue{ + {S: aws.String("1")}, + {S: aws.String("2")}, + {S: aws.String("3")}, + }}, + "Value13": {BOOL: aws.Bool(true)}, + "Value14": {L: []*dynamodb.AttributeValue{ + {BOOL: aws.Bool(true)}, + {BOOL: aws.Bool(false)}, + {BOOL: aws.Bool(true)}, + }}, + }, + }, + actual: &testAliasedStruct{}, + expected: testAliasedStruct{ + Value: "123", Value2: 123, + Value3: testAliasedMap{ + "Key": 321, + }, + Value4: testAliasedSlice{"1", "2", "3"}, + Value5: testAliasedByteSlice{0, 1, 2}, + Value6: []testAliasedInt{1, 2, 3}, + Value7: []testAliasedString{"1", "2", "3"}, + Value8: []testAliasedByteSlice{ + {0, 1, 2}, + {3, 4, 5}, + }, + Value9: []testAliasedInt{1, 2, 3}, + Value10: []testAliasedString{"1", "2", "3"}, + Value11: testAliasedIntSlice{1, 2, 3}, + Value12: testAliasedStringSlice{"1", "2", "3"}, + Value13: true, + Value14: testAliasedBoolSlice{true, false, true}, + }, + }, + { + in: &dynamodb.AttributeValue{N: aws.String("123")}, + actual: new(testNamedPointer), + expected: testNamedPointer(aws.Int(123)), + }, + { // time.Time + in: &dynamodb.AttributeValue{S: aws.String("2016-05-03T17:06:26.209072Z")}, + actual: new(time.Time), + expected: testDate, + }, + { // time.Time List + in: &dynamodb.AttributeValue{L: []*dynamodb.AttributeValue{ + {S: aws.String("2016-05-03T17:06:26.209072Z")}, + {S: aws.String("2016-05-04T17:06:26.209072Z")}, + }}, + actual: new([]time.Time), + expected: []time.Time{testDate, testDate.Add(24 * time.Hour)}, + }, + { // time.Time struct + in: &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{ + "abc": {S: aws.String("2016-05-03T17:06:26.209072Z")}, + }}, + actual: &struct { + Abc time.Time `json:"abc" dynamodbav:"abc"` + }{}, + expected: struct { + Abc time.Time `json:"abc" dynamodbav:"abc"` + }{Abc: testDate}, + }, + { // time.Time ptr struct + in: &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{ + "abc": {S: aws.String("2016-05-03T17:06:26.209072Z")}, + }}, + actual: &struct { + Abc *time.Time `json:"abc" dynamodbav:"abc"` + }{}, + expected: struct { + Abc *time.Time `json:"abc" dynamodbav:"abc"` + }{Abc: &testDate}, + }, +} + +var sharedListTestCases = []struct { + in []*dynamodb.AttributeValue + actual, expected interface{} + err error +}{ + { + in: []*dynamodb.AttributeValue{ + {B: []byte{48, 49}}, + {BOOL: aws.Bool(true)}, + {N: aws.String("123")}, + {S: aws.String("123")}, + }, + actual: func() *[]interface{} { + v := []interface{}{} + return &v + }(), + expected: []interface{}{[]byte{48, 49}, true, 123., "123"}, + }, + { + in: []*dynamodb.AttributeValue{ + {N: aws.String("1")}, + {N: aws.String("2")}, + {N: aws.String("3")}, + }, + actual: &[]interface{}{}, + expected: []interface{}{1., 2., 3.}, + }, +} + +var sharedMapTestCases = []struct { + in map[string]*dynamodb.AttributeValue + actual, expected interface{} + err error +}{ + { + in: map[string]*dynamodb.AttributeValue{ + "B": {B: []byte{48, 49}}, + "BOOL": {BOOL: aws.Bool(true)}, + "N": {N: aws.String("123")}, + "S": {S: aws.String("123")}, + }, + actual: &map[string]interface{}{}, + expected: map[string]interface{}{ + "B": []byte{48, 49}, "BOOL": true, + "N": 123., "S": "123", + }, + }, +} + +func assertConvertTest(t *testing.T, i int, actual, expected interface{}, err, expectedErr error) { + i++ + if expectedErr != nil { + if err != nil { + if e, a := expectedErr, err; !reflect.DeepEqual(e, a) { + t.Errorf("case %d expect %v, got %v", i, e, a) + } + } else { + t.Fatalf("case %d, expected error, %v", i, expectedErr) + } + } else if err != nil { + t.Fatalf("case %d, expect no error, got %v", i, err) + } else { + if e, a := ptrToValue(expected), ptrToValue(actual); !reflect.DeepEqual(e, a) { + t.Errorf("case %d, expect %v, got %v", i, e, a) + } + } +} + +func ptrToValue(in interface{}) interface{} { + v := reflect.ValueOf(in) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if !v.IsValid() { + return nil + } + if v.Kind() == reflect.Ptr { + return ptrToValue(v.Interface()) + } + return v.Interface() +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag.go new file mode 100644 index 0000000..60bd609 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag.go @@ -0,0 +1,68 @@ +package dynamodbattribute + +import ( + "reflect" + "strings" +) + +type tag struct { + Name string + Ignore bool + OmitEmpty bool + OmitEmptyElem bool + AsString bool + AsBinSet, AsNumSet, AsStrSet bool + AsUnixTime bool +} + +func (t *tag) parseAVTag(structTag reflect.StructTag) { + tagStr := structTag.Get("dynamodbav") + if len(tagStr) == 0 { + return + } + + t.parseTagStr(tagStr) +} + +func (t *tag) parseJSONTag(structTag reflect.StructTag) { + tagStr := structTag.Get("json") + if len(tagStr) == 0 { + return + } + + t.parseTagStr(tagStr) +} + +func (t *tag) parseTagStr(tagStr string) { + parts := strings.Split(tagStr, ",") + if len(parts) == 0 { + return + } + + if name := parts[0]; name == "-" { + t.Name = "" + t.Ignore = true + } else { + t.Name = name + t.Ignore = false + } + + for _, opt := range parts[1:] { + switch opt { + case "omitempty": + t.OmitEmpty = true + case "omitemptyelem": + t.OmitEmptyElem = true + case "string": + t.AsString = true + case "binaryset": + t.AsBinSet = true + case "numberset": + t.AsNumSet = true + case "stringset": + t.AsStrSet = true + case "unixtime": + t.AsUnixTime = true + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag_test.go new file mode 100644 index 0000000..f47f402 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute/tag_test.go @@ -0,0 +1,47 @@ +package dynamodbattribute + +import ( + "reflect" + "testing" +) + +func TestTagParse(t *testing.T) { + cases := []struct { + in reflect.StructTag + json, av bool + expect tag + }{ + {`json:""`, true, false, tag{}}, + {`json:"name"`, true, false, tag{Name: "name"}}, + {`json:"name,omitempty"`, true, false, tag{Name: "name", OmitEmpty: true}}, + {`json:"-"`, true, false, tag{Ignore: true}}, + {`json:",omitempty"`, true, false, tag{OmitEmpty: true}}, + {`json:",string"`, true, false, tag{AsString: true}}, + {`dynamodbav:""`, false, true, tag{}}, + {`dynamodbav:","`, false, true, tag{}}, + {`dynamodbav:"name"`, false, true, tag{Name: "name"}}, + {`dynamodbav:"name"`, false, true, tag{Name: "name"}}, + {`dynamodbav:"-"`, false, true, tag{Ignore: true}}, + {`dynamodbav:",omitempty"`, false, true, tag{OmitEmpty: true}}, + {`dynamodbav:",omitemptyelem"`, false, true, tag{OmitEmptyElem: true}}, + {`dynamodbav:",string"`, false, true, tag{AsString: true}}, + {`dynamodbav:",binaryset"`, false, true, tag{AsBinSet: true}}, + {`dynamodbav:",numberset"`, false, true, tag{AsNumSet: true}}, + {`dynamodbav:",stringset"`, false, true, tag{AsStrSet: true}}, + {`dynamodbav:",stringset,omitemptyelem"`, false, true, tag{AsStrSet: true, OmitEmptyElem: true}}, + {`dynamodbav:"name,stringset,omitemptyelem"`, false, true, tag{Name: "name", AsStrSet: true, OmitEmptyElem: true}}, + } + + for i, c := range cases { + actual := tag{} + if c.json { + actual.parseJSONTag(c.in) + } + if c.av { + actual.parseAVTag(c.in) + } + if e, a := c.expect, actual; !reflect.DeepEqual(e, a) { + t.Errorf("case %d, expect %v, got %v", i, e, a) + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/errors.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/errors.go new file mode 100644 index 0000000..41986cf --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/errors.go @@ -0,0 +1,126 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package dynamodb + +const ( + + // ErrCodeBackupInUseException for service response error code + // "BackupInUseException". + // + // There is another ongoing conflicting backup control plane operation on the + // table. The backups is either being created, deleted or restored to a table. + ErrCodeBackupInUseException = "BackupInUseException" + + // ErrCodeBackupNotFoundException for service response error code + // "BackupNotFoundException". + // + // Backup not found for the given BackupARN. + ErrCodeBackupNotFoundException = "BackupNotFoundException" + + // ErrCodeConditionalCheckFailedException for service response error code + // "ConditionalCheckFailedException". + // + // A condition specified in the operation could not be evaluated. + ErrCodeConditionalCheckFailedException = "ConditionalCheckFailedException" + + // ErrCodeContinuousBackupsUnavailableException for service response error code + // "ContinuousBackupsUnavailableException". + // + // Backups have not yet been enabled for this table. + ErrCodeContinuousBackupsUnavailableException = "ContinuousBackupsUnavailableException" + + // ErrCodeGlobalTableAlreadyExistsException for service response error code + // "GlobalTableAlreadyExistsException". + // + // The specified global table already exists. + ErrCodeGlobalTableAlreadyExistsException = "GlobalTableAlreadyExistsException" + + // ErrCodeGlobalTableNotFoundException for service response error code + // "GlobalTableNotFoundException". + // + // The specified global table does not exist. + ErrCodeGlobalTableNotFoundException = "GlobalTableNotFoundException" + + // ErrCodeInternalServerError for service response error code + // "InternalServerError". + // + // An error occurred on the server side. + ErrCodeInternalServerError = "InternalServerError" + + // ErrCodeItemCollectionSizeLimitExceededException for service response error code + // "ItemCollectionSizeLimitExceededException". + // + // An item collection is too large. This exception is only returned for tables + // that have one or more local secondary indexes. + ErrCodeItemCollectionSizeLimitExceededException = "ItemCollectionSizeLimitExceededException" + + // ErrCodeLimitExceededException for service response error code + // "LimitExceededException". + // + // The number of concurrent table requests (cumulative number of tables in the + // CREATING, DELETING or UPDATING state) exceeds the maximum allowed of 10. + // + // Also, for tables with secondary indexes, only one of those tables can be + // in the CREATING state at any point in time. Do not attempt to create more + // than one such table simultaneously. + // + // The total limit of tables in the ACTIVE state is 250. + ErrCodeLimitExceededException = "LimitExceededException" + + // ErrCodeProvisionedThroughputExceededException for service response error code + // "ProvisionedThroughputExceededException". + // + // Your request rate is too high. The AWS SDKs for DynamoDB automatically retry + // requests that receive this exception. Your request is eventually successful, + // unless your retry queue is too large to finish. Reduce the frequency of requests + // and use exponential backoff. For more information, go to Error Retries and + // Exponential Backoff (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.RetryAndBackoff) + // in the Amazon DynamoDB Developer Guide. + ErrCodeProvisionedThroughputExceededException = "ProvisionedThroughputExceededException" + + // ErrCodeReplicaAlreadyExistsException for service response error code + // "ReplicaAlreadyExistsException". + // + // The specified replica is already part of the global table. + ErrCodeReplicaAlreadyExistsException = "ReplicaAlreadyExistsException" + + // ErrCodeReplicaNotFoundException for service response error code + // "ReplicaNotFoundException". + // + // The specified replica is no longer part of the global table. + ErrCodeReplicaNotFoundException = "ReplicaNotFoundException" + + // ErrCodeResourceInUseException for service response error code + // "ResourceInUseException". + // + // The operation conflicts with the resource's availability. For example, you + // attempted to recreate an existing table, or tried to delete a table currently + // in the CREATING state. + ErrCodeResourceInUseException = "ResourceInUseException" + + // ErrCodeResourceNotFoundException for service response error code + // "ResourceNotFoundException". + // + // The operation tried to access a nonexistent table or index. The resource + // might not be specified correctly, or its status might not be ACTIVE. + ErrCodeResourceNotFoundException = "ResourceNotFoundException" + + // ErrCodeTableAlreadyExistsException for service response error code + // "TableAlreadyExistsException". + // + // A table with the name already exists. + ErrCodeTableAlreadyExistsException = "TableAlreadyExistsException" + + // ErrCodeTableInUseException for service response error code + // "TableInUseException". + // + // A table by that name is either being created or deleted. + ErrCodeTableInUseException = "TableInUseException" + + // ErrCodeTableNotFoundException for service response error code + // "TableNotFoundException". + // + // A table with the name TableName does not currently exist within the subscriber's + // account. + ErrCodeTableNotFoundException = "TableNotFoundException" +) diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/examples_test.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/examples_test.go new file mode 100644 index 0000000..668d0a9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/examples_test.go @@ -0,0 +1,677 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package dynamodb_test + +import ( + "fmt" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/dynamodb" +) + +var _ time.Duration +var _ strings.Reader +var _ aws.Config + +func parseTime(layout, value string) *time.Time { + t, err := time.Parse(layout, value) + if err != nil { + panic(err) + } + return &t +} + +// To retrieve multiple items from a table +// +// This example reads multiple items from the Music table using a batch of three GetItem +// requests. Only the AlbumTitle attribute is returned. +func ExampleDynamoDB_BatchGetItem_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.BatchGetItemInput{ + RequestItems: map[string]*dynamodb.KeysAndAttributes{ + "Music": { + Keys: []map[string]*dynamodb.AttributeValue{ + { + "Artist": &dynamodb.AttributeValue{ + S: aws.String("No One You Know"), + }, + "SongTitle": &dynamodb.AttributeValue{ + S: aws.String("Call Me Today"), + }, + }, + { + "Artist": &dynamodb.AttributeValue{ + S: aws.String("Acme Band"), + }, + "SongTitle": &dynamodb.AttributeValue{ + S: aws.String("Happy Day"), + }, + }, + { + "Artist": &dynamodb.AttributeValue{ + S: aws.String("No One You Know"), + }, + "SongTitle": &dynamodb.AttributeValue{ + S: aws.String("Scared of My Shadow"), + }, + }, + }, + ProjectionExpression: aws.String("AlbumTitle"), + }, + }, + } + + result, err := svc.BatchGetItem(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To add multiple items to a table +// +// This example adds three new items to the Music table using a batch of three PutItem +// requests. +func ExampleDynamoDB_BatchWriteItem_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.BatchWriteItemInput{ + RequestItems: map[string][]*dynamodb.WriteRequest{ + "Music": { + { + PutRequest: &dynamodb.PutRequest{ + Item: map[string]*dynamodb.AttributeValue{ + "AlbumTitle": { + S: aws.String("Somewhat Famous"), + }, + "Artist": { + S: aws.String("No One You Know"), + }, + "SongTitle": { + S: aws.String("Call Me Today"), + }, + }, + }, + }, + { + PutRequest: &dynamodb.PutRequest{ + Item: map[string]*dynamodb.AttributeValue{ + "AlbumTitle": { + S: aws.String("Songs About Life"), + }, + "Artist": { + S: aws.String("Acme Band"), + }, + "SongTitle": { + S: aws.String("Happy Day"), + }, + }, + }, + }, + { + PutRequest: &dynamodb.PutRequest{ + Item: map[string]*dynamodb.AttributeValue{ + "AlbumTitle": { + S: aws.String("Blue Sky Blues"), + }, + "Artist": { + S: aws.String("No One You Know"), + }, + "SongTitle": { + S: aws.String("Scared of My Shadow"), + }, + }, + }, + }, + }, + }, + } + + result, err := svc.BatchWriteItem(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeItemCollectionSizeLimitExceededException: + fmt.Println(dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To create a table +// +// This example creates a table named Music. +func ExampleDynamoDB_CreateTable_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.CreateTableInput{ + AttributeDefinitions: []*dynamodb.AttributeDefinition{ + { + AttributeName: aws.String("Artist"), + AttributeType: aws.String("S"), + }, + { + AttributeName: aws.String("SongTitle"), + AttributeType: aws.String("S"), + }, + }, + KeySchema: []*dynamodb.KeySchemaElement{ + { + AttributeName: aws.String("Artist"), + KeyType: aws.String("HASH"), + }, + { + AttributeName: aws.String("SongTitle"), + KeyType: aws.String("RANGE"), + }, + }, + ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ + ReadCapacityUnits: aws.Int64(5), + WriteCapacityUnits: aws.Int64(5), + }, + TableName: aws.String("Music"), + } + + result, err := svc.CreateTable(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeResourceInUseException: + fmt.Println(dynamodb.ErrCodeResourceInUseException, aerr.Error()) + case dynamodb.ErrCodeLimitExceededException: + fmt.Println(dynamodb.ErrCodeLimitExceededException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To delete an item +// +// This example deletes an item from the Music table. +func ExampleDynamoDB_DeleteItem_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.DeleteItemInput{ + Key: map[string]*dynamodb.AttributeValue{ + "Artist": { + S: aws.String("No One You Know"), + }, + "SongTitle": { + S: aws.String("Scared of My Shadow"), + }, + }, + TableName: aws.String("Music"), + } + + result, err := svc.DeleteItem(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeConditionalCheckFailedException: + fmt.Println(dynamodb.ErrCodeConditionalCheckFailedException, aerr.Error()) + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeItemCollectionSizeLimitExceededException: + fmt.Println(dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To delete a table +// +// This example deletes the Music table. +func ExampleDynamoDB_DeleteTable_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.DeleteTableInput{ + TableName: aws.String("Music"), + } + + result, err := svc.DeleteTable(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeResourceInUseException: + fmt.Println(dynamodb.ErrCodeResourceInUseException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeLimitExceededException: + fmt.Println(dynamodb.ErrCodeLimitExceededException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To determine capacity limits per table and account, in the current AWS region +// +// The following example returns the maximum read and write capacity units per table, +// and for the AWS account, in the current AWS region. +func ExampleDynamoDB_DescribeLimits_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.DescribeLimitsInput{} + + result, err := svc.DescribeLimits(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To describe a table +// +// This example describes the Music table. +func ExampleDynamoDB_DescribeTable_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.DescribeTableInput{ + TableName: aws.String("Music"), + } + + result, err := svc.DescribeTable(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To read an item from a table +// +// This example retrieves an item from the Music table. The table has a partition key +// and a sort key (Artist and SongTitle), so you must specify both of these attributes. +func ExampleDynamoDB_GetItem_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.GetItemInput{ + Key: map[string]*dynamodb.AttributeValue{ + "Artist": { + S: aws.String("Acme Band"), + }, + "SongTitle": { + S: aws.String("Happy Day"), + }, + }, + TableName: aws.String("Music"), + } + + result, err := svc.GetItem(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To list tables +// +// This example lists all of the tables associated with the current AWS account and +// endpoint. +func ExampleDynamoDB_ListTables_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.ListTablesInput{} + + result, err := svc.ListTables(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To add an item to a table +// +// This example adds a new item to the Music table. +func ExampleDynamoDB_PutItem_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.PutItemInput{ + Item: map[string]*dynamodb.AttributeValue{ + "AlbumTitle": { + S: aws.String("Somewhat Famous"), + }, + "Artist": { + S: aws.String("No One You Know"), + }, + "SongTitle": { + S: aws.String("Call Me Today"), + }, + }, + ReturnConsumedCapacity: aws.String("TOTAL"), + TableName: aws.String("Music"), + } + + result, err := svc.PutItem(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeConditionalCheckFailedException: + fmt.Println(dynamodb.ErrCodeConditionalCheckFailedException, aerr.Error()) + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeItemCollectionSizeLimitExceededException: + fmt.Println(dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To query an item +// +// This example queries items in the Music table. The table has a partition key and +// sort key (Artist and SongTitle), but this query only specifies the partition key +// value. It returns song titles by the artist named "No One You Know". +func ExampleDynamoDB_Query_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.QueryInput{ + ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ + ":v1": { + S: aws.String("No One You Know"), + }, + }, + KeyConditionExpression: aws.String("Artist = :v1"), + ProjectionExpression: aws.String("SongTitle"), + TableName: aws.String("Music"), + } + + result, err := svc.Query(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To scan a table +// +// This example scans the entire Music table, and then narrows the results to songs +// by the artist "No One You Know". For each item, only the album title and song title +// are returned. +func ExampleDynamoDB_Scan_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.ScanInput{ + ExpressionAttributeNames: map[string]*string{ + "AT": aws.String("AlbumTitle"), + "ST": aws.String("SongTitle"), + }, + ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ + ":a": { + S: aws.String("No One You Know"), + }, + }, + FilterExpression: aws.String("Artist = :a"), + ProjectionExpression: aws.String("#ST, #AT"), + TableName: aws.String("Music"), + } + + result, err := svc.Scan(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To update an item in a table +// +// This example updates an item in the Music table. It adds a new attribute (Year) and +// modifies the AlbumTitle attribute. All of the attributes in the item, as they appear +// after the update, are returned in the response. +func ExampleDynamoDB_UpdateItem_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.UpdateItemInput{ + ExpressionAttributeNames: map[string]*string{ + "#AT": aws.String("AlbumTitle"), + "#Y": aws.String("Year"), + }, + ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ + ":t": { + S: aws.String("Louder Than Ever"), + }, + ":y": { + N: aws.String("2015"), + }, + }, + Key: map[string]*dynamodb.AttributeValue{ + "Artist": { + S: aws.String("Acme Band"), + }, + "SongTitle": { + S: aws.String("Happy Day"), + }, + }, + ReturnValues: aws.String("ALL_NEW"), + TableName: aws.String("Music"), + UpdateExpression: aws.String("SET #Y = :y, #AT = :t"), + } + + result, err := svc.UpdateItem(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeConditionalCheckFailedException: + fmt.Println(dynamodb.ErrCodeConditionalCheckFailedException, aerr.Error()) + case dynamodb.ErrCodeProvisionedThroughputExceededException: + fmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeItemCollectionSizeLimitExceededException: + fmt.Println(dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To modify a table's provisioned throughput +// +// This example increases the provisioned read and write capacity on the Music table. +func ExampleDynamoDB_UpdateTable_shared00() { + svc := dynamodb.New(session.New()) + input := &dynamodb.UpdateTableInput{ + ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ + ReadCapacityUnits: aws.Int64(10), + WriteCapacityUnits: aws.Int64(10), + }, + TableName: aws.String("MusicCollection"), + } + + result, err := svc.UpdateTable(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case dynamodb.ErrCodeResourceInUseException: + fmt.Println(dynamodb.ErrCodeResourceInUseException, aerr.Error()) + case dynamodb.ErrCodeResourceNotFoundException: + fmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error()) + case dynamodb.ErrCodeLimitExceededException: + fmt.Println(dynamodb.ErrCodeLimitExceededException, aerr.Error()) + case dynamodb.ErrCodeInternalServerError: + fmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/service.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/service.go new file mode 100644 index 0000000..80dcd19 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/service.go @@ -0,0 +1,95 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package dynamodb + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/private/protocol/jsonrpc" +) + +// DynamoDB provides the API operation methods for making requests to +// Amazon DynamoDB. See this package's package overview docs +// for details on the service. +// +// DynamoDB methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type DynamoDB struct { + *client.Client +} + +// Used for custom client initialization logic +var initClient func(*client.Client) + +// Used for custom request initialization logic +var initRequest func(*request.Request) + +// Service information constants +const ( + ServiceName = "dynamodb" // Service endpoint prefix API calls made to. + EndpointsID = ServiceName // Service ID for Regions and Endpoints metadata. +) + +// New creates a new instance of the DynamoDB client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a DynamoDB client from just a session. +// svc := dynamodb.New(mySession) +// +// // Create a DynamoDB client with additional configuration +// svc := dynamodb.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *DynamoDB { + c := p.ClientConfig(EndpointsID, cfgs...) + return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *DynamoDB { + svc := &DynamoDB{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2012-08-10", + JSONVersion: "1.0", + TargetPrefix: "DynamoDB_20120810", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(jsonrpc.UnmarshalErrorHandler) + + // Run custom client initialization if present + if initClient != nil { + initClient(svc.Client) + } + + return svc +} + +// newRequest creates a new request for a DynamoDB operation and runs any +// custom request initialization. +func (c *DynamoDB) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + // Run custom request initialization if present + if initRequest != nil { + initRequest(req) + } + + return req +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/dynamodb/waiters.go b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/waiters.go new file mode 100644 index 0000000..ae515f7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/dynamodb/waiters.go @@ -0,0 +1,107 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package dynamodb + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" +) + +// WaitUntilTableExists uses the DynamoDB API operation +// DescribeTable to wait for a condition to be met before returning. +// If the condition is not met within the max attempt window, an error will +// be returned. +func (c *DynamoDB) WaitUntilTableExists(input *DescribeTableInput) error { + return c.WaitUntilTableExistsWithContext(aws.BackgroundContext(), input) +} + +// WaitUntilTableExistsWithContext is an extended version of WaitUntilTableExists. +// With the support for passing in a context and options to configure the +// Waiter and the underlying request options. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) WaitUntilTableExistsWithContext(ctx aws.Context, input *DescribeTableInput, opts ...request.WaiterOption) error { + w := request.Waiter{ + Name: "WaitUntilTableExists", + MaxAttempts: 25, + Delay: request.ConstantWaiterDelay(20 * time.Second), + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.PathWaiterMatch, Argument: "Table.TableStatus", + Expected: "ACTIVE", + }, + { + State: request.RetryWaiterState, + Matcher: request.ErrorWaiterMatch, + Expected: "ResourceNotFoundException", + }, + }, + Logger: c.Config.Logger, + NewRequest: func(opts []request.Option) (*request.Request, error) { + var inCpy *DescribeTableInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.DescribeTableRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + w.ApplyOptions(opts...) + + return w.WaitWithContext(ctx) +} + +// WaitUntilTableNotExists uses the DynamoDB API operation +// DescribeTable to wait for a condition to be met before returning. +// If the condition is not met within the max attempt window, an error will +// be returned. +func (c *DynamoDB) WaitUntilTableNotExists(input *DescribeTableInput) error { + return c.WaitUntilTableNotExistsWithContext(aws.BackgroundContext(), input) +} + +// WaitUntilTableNotExistsWithContext is an extended version of WaitUntilTableNotExists. +// With the support for passing in a context and options to configure the +// Waiter and the underlying request options. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *DynamoDB) WaitUntilTableNotExistsWithContext(ctx aws.Context, input *DescribeTableInput, opts ...request.WaiterOption) error { + w := request.Waiter{ + Name: "WaitUntilTableNotExists", + MaxAttempts: 25, + Delay: request.ConstantWaiterDelay(20 * time.Second), + Acceptors: []request.WaiterAcceptor{ + { + State: request.SuccessWaiterState, + Matcher: request.ErrorWaiterMatch, + Expected: "ResourceNotFoundException", + }, + }, + Logger: c.Config.Logger, + NewRequest: func(opts []request.Option) (*request.Request, error) { + var inCpy *DescribeTableInput + if input != nil { + tmp := *input + inCpy = &tmp + } + req, _ := c.DescribeTableRequest(inCpy) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return req, nil + }, + } + w.ApplyOptions(opts...) + + return w.WaitWithContext(ctx) +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/generate.go b/vendor/github.com/aws/aws-sdk-go/service/generate.go new file mode 100644 index 0000000..3ffc9fc --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/generate.go @@ -0,0 +1,5 @@ +// Package service contains automatically generated AWS clients. +package service + +//go:generate go run -tags codegen ../private/model/cli/gen-api/main.go -path=../service ../models/apis/*/*/api-2.json +//go:generate gofmt -s -w ../service diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/api.go b/vendor/github.com/aws/aws-sdk-go/service/sts/api.go new file mode 100644 index 0000000..23f0a06 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/api.go @@ -0,0 +1,2358 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package sts + +import ( + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awsutil" + "github.com/aws/aws-sdk-go/aws/request" +) + +const opAssumeRole = "AssumeRole" + +// AssumeRoleRequest generates a "aws/request.Request" representing the +// client's request for the AssumeRole operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See AssumeRole for more information on using the AssumeRole +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the AssumeRoleRequest method. +// req, resp := client.AssumeRoleRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole +func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, output *AssumeRoleOutput) { + op := &request.Operation{ + Name: opAssumeRole, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleInput{} + } + + output = &AssumeRoleOutput{} + req = c.newRequest(op, input, output) + return +} + +// AssumeRole API operation for AWS Security Token Service. +// +// Returns a set of temporary security credentials (consisting of an access +// key ID, a secret access key, and a security token) that you can use to access +// AWS resources that you might not normally have access to. Typically, you +// use AssumeRole for cross-account access or federation. For a comparison of +// AssumeRole with the other APIs that produce temporary credentials, see Requesting +// Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) +// and Comparing the AWS STS APIs (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison) +// in the IAM User Guide. +// +// Important: You cannot call AssumeRole by using AWS root account credentials; +// access is denied. You must use credentials for an IAM user or an IAM role +// to call AssumeRole. +// +// For cross-account access, imagine that you own multiple accounts and need +// to access resources in each account. You could create long-term credentials +// in each account to access those resources. However, managing all those credentials +// and remembering which one can access which account can be time consuming. +// Instead, you can create one set of long-term credentials in one account and +// then use temporary security credentials to access all the other accounts +// by assuming roles in those accounts. For more information about roles, see +// IAM Roles (Delegation and Federation) (http://docs.aws.amazon.com/IAM/latest/UserGuide/roles-toplevel.html) +// in the IAM User Guide. +// +// For federation, you can, for example, grant single sign-on access to the +// AWS Management Console. If you already have an identity and authentication +// system in your corporate network, you don't have to recreate user identities +// in AWS in order to grant those user identities access to AWS. Instead, after +// a user has been authenticated, you call AssumeRole (and specify the role +// with the appropriate permissions) to get temporary security credentials for +// that user. With those temporary security credentials, you construct a sign-in +// URL that users can use to access the console. For more information, see Common +// Scenarios for Temporary Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html#sts-introduction) +// in the IAM User Guide. +// +// The temporary security credentials are valid for the duration that you specified +// when calling AssumeRole, which can be from 900 seconds (15 minutes) to a +// maximum of 3600 seconds (1 hour). The default is 1 hour. +// +// The temporary security credentials created by AssumeRole can be used to make +// API calls to any AWS service with the following exception: you cannot call +// the STS service's GetFederationToken or GetSessionToken APIs. +// +// Optionally, you can pass an IAM access policy to this operation. If you choose +// not to pass a policy, the temporary security credentials that are returned +// by the operation have the permissions that are defined in the access policy +// of the role that is being assumed. If you pass a policy to this operation, +// the temporary security credentials that are returned by the operation have +// the permissions that are allowed by both the access policy of the role that +// is being assumed, and the policy that you pass. This gives you a way to further +// restrict the permissions for the resulting temporary security credentials. +// You cannot use the passed policy to grant permissions that are in excess +// of those allowed by the access policy of the role that is being assumed. +// For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, +// and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the IAM User Guide. +// +// To assume a role, your AWS account must be trusted by the role. The trust +// relationship is defined in the role's trust policy when the role is created. +// That trust policy states which accounts are allowed to delegate access to +// this account's role. +// +// The user who wants to access the role must also have permissions delegated +// from the role's administrator. If the user is in a different account than +// the role, then the user's administrator must attach a policy that allows +// the user to call AssumeRole on the ARN of the role in the other account. +// If the user is in the same account as the role, then you can either attach +// a policy to the user (identical to the previous different account user), +// or you can add the user as a principal directly in the role's trust policy +// +// Using MFA with AssumeRole +// +// You can optionally include multi-factor authentication (MFA) information +// when you call AssumeRole. This is useful for cross-account scenarios in which +// you want to make sure that the user who is assuming the role has been authenticated +// using an AWS MFA device. In that scenario, the trust policy of the role being +// assumed includes a condition that tests for MFA authentication; if the caller +// does not include valid MFA information, the request to assume the role is +// denied. The condition in a trust policy that tests for MFA authentication +// might look like the following example. +// +// "Condition": {"Bool": {"aws:MultiFactorAuthPresent": true}} +// +// For more information, see Configuring MFA-Protected API Access (http://docs.aws.amazon.com/IAM/latest/UserGuide/MFAProtectedAPI.html) +// in the IAM User Guide guide. +// +// To use MFA with AssumeRole, you pass values for the SerialNumber and TokenCode +// parameters. The SerialNumber value identifies the user's hardware or virtual +// MFA device. The TokenCode is the time-based one-time password (TOTP) that +// the MFA devices produces. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Security Token Service's +// API operation AssumeRole for usage and error information. +// +// Returned Error Codes: +// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument" +// The request was rejected because the policy document was malformed. The error +// message describes the specific error. +// +// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge" +// The request was rejected because the policy document was too large. The error +// message describes how big the policy document is, in packed form, as a percentage +// of what the API allows. +// +// * ErrCodeRegionDisabledException "RegionDisabledException" +// STS is not activated in the requested region for the account that is being +// asked to generate credentials. The account administrator must use the IAM +// console to activate STS in that region. For more information, see Activating +// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the IAM User Guide. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole +func (c *STS) AssumeRole(input *AssumeRoleInput) (*AssumeRoleOutput, error) { + req, out := c.AssumeRoleRequest(input) + return out, req.Send() +} + +// AssumeRoleWithContext is the same as AssumeRole with the addition of +// the ability to pass a context and additional request options. +// +// See AssumeRole for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *STS) AssumeRoleWithContext(ctx aws.Context, input *AssumeRoleInput, opts ...request.Option) (*AssumeRoleOutput, error) { + req, out := c.AssumeRoleRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opAssumeRoleWithSAML = "AssumeRoleWithSAML" + +// AssumeRoleWithSAMLRequest generates a "aws/request.Request" representing the +// client's request for the AssumeRoleWithSAML operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See AssumeRoleWithSAML for more information on using the AssumeRoleWithSAML +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the AssumeRoleWithSAMLRequest method. +// req, resp := client.AssumeRoleWithSAMLRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML +func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *request.Request, output *AssumeRoleWithSAMLOutput) { + op := &request.Operation{ + Name: opAssumeRoleWithSAML, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleWithSAMLInput{} + } + + output = &AssumeRoleWithSAMLOutput{} + req = c.newRequest(op, input, output) + return +} + +// AssumeRoleWithSAML API operation for AWS Security Token Service. +// +// Returns a set of temporary security credentials for users who have been authenticated +// via a SAML authentication response. This operation provides a mechanism for +// tying an enterprise identity store or directory to role-based AWS access +// without user-specific credentials or configuration. For a comparison of AssumeRoleWithSAML +// with the other APIs that produce temporary credentials, see Requesting Temporary +// Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) +// and Comparing the AWS STS APIs (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison) +// in the IAM User Guide. +// +// The temporary security credentials returned by this operation consist of +// an access key ID, a secret access key, and a security token. Applications +// can use these temporary security credentials to sign calls to AWS services. +// +// The temporary security credentials are valid for the duration that you specified +// when calling AssumeRole, or until the time specified in the SAML authentication +// response's SessionNotOnOrAfter value, whichever is shorter. The duration +// can be from 900 seconds (15 minutes) to a maximum of 3600 seconds (1 hour). +// The default is 1 hour. +// +// The temporary security credentials created by AssumeRoleWithSAML can be used +// to make API calls to any AWS service with the following exception: you cannot +// call the STS service's GetFederationToken or GetSessionToken APIs. +// +// Optionally, you can pass an IAM access policy to this operation. If you choose +// not to pass a policy, the temporary security credentials that are returned +// by the operation have the permissions that are defined in the access policy +// of the role that is being assumed. If you pass a policy to this operation, +// the temporary security credentials that are returned by the operation have +// the permissions that are allowed by the intersection of both the access policy +// of the role that is being assumed, and the policy that you pass. This means +// that both policies must grant the permission for the action to be allowed. +// This gives you a way to further restrict the permissions for the resulting +// temporary security credentials. You cannot use the passed policy to grant +// permissions that are in excess of those allowed by the access policy of the +// role that is being assumed. For more information, see Permissions for AssumeRole, +// AssumeRoleWithSAML, and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the IAM User Guide. +// +// Before your application can call AssumeRoleWithSAML, you must configure your +// SAML identity provider (IdP) to issue the claims required by AWS. Additionally, +// you must use AWS Identity and Access Management (IAM) to create a SAML provider +// entity in your AWS account that represents your identity provider, and create +// an IAM role that specifies this SAML provider in its trust policy. +// +// Calling AssumeRoleWithSAML does not require the use of AWS security credentials. +// The identity of the caller is validated by using keys in the metadata document +// that is uploaded for the SAML provider entity for your identity provider. +// +// Calling AssumeRoleWithSAML can result in an entry in your AWS CloudTrail +// logs. The entry includes the value in the NameID element of the SAML assertion. +// We recommend that you use a NameIDType that is not associated with any personally +// identifiable information (PII). For example, you could instead use the Persistent +// Identifier (urn:oasis:names:tc:SAML:2.0:nameid-format:persistent). +// +// For more information, see the following resources: +// +// * About SAML 2.0-based Federation (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_saml.html) +// in the IAM User Guide. +// +// * Creating SAML Identity Providers (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html) +// in the IAM User Guide. +// +// * Configuring a Relying Party and Claims (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_relying-party.html) +// in the IAM User Guide. +// +// * Creating a Role for SAML 2.0 Federation (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_saml.html) +// in the IAM User Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Security Token Service's +// API operation AssumeRoleWithSAML for usage and error information. +// +// Returned Error Codes: +// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument" +// The request was rejected because the policy document was malformed. The error +// message describes the specific error. +// +// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge" +// The request was rejected because the policy document was too large. The error +// message describes how big the policy document is, in packed form, as a percentage +// of what the API allows. +// +// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim" +// The identity provider (IdP) reported that authentication failed. This might +// be because the claim is invalid. +// +// If this error is returned for the AssumeRoleWithWebIdentity operation, it +// can also mean that the claim has expired or has been explicitly revoked. +// +// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken" +// The web identity token that was passed could not be validated by AWS. Get +// a new identity token from the identity provider and then retry the request. +// +// * ErrCodeExpiredTokenException "ExpiredTokenException" +// The web identity token that was passed is expired or is not valid. Get a +// new identity token from the identity provider and then retry the request. +// +// * ErrCodeRegionDisabledException "RegionDisabledException" +// STS is not activated in the requested region for the account that is being +// asked to generate credentials. The account administrator must use the IAM +// console to activate STS in that region. For more information, see Activating +// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the IAM User Guide. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML +func (c *STS) AssumeRoleWithSAML(input *AssumeRoleWithSAMLInput) (*AssumeRoleWithSAMLOutput, error) { + req, out := c.AssumeRoleWithSAMLRequest(input) + return out, req.Send() +} + +// AssumeRoleWithSAMLWithContext is the same as AssumeRoleWithSAML with the addition of +// the ability to pass a context and additional request options. +// +// See AssumeRoleWithSAML for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *STS) AssumeRoleWithSAMLWithContext(ctx aws.Context, input *AssumeRoleWithSAMLInput, opts ...request.Option) (*AssumeRoleWithSAMLOutput, error) { + req, out := c.AssumeRoleWithSAMLRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opAssumeRoleWithWebIdentity = "AssumeRoleWithWebIdentity" + +// AssumeRoleWithWebIdentityRequest generates a "aws/request.Request" representing the +// client's request for the AssumeRoleWithWebIdentity operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See AssumeRoleWithWebIdentity for more information on using the AssumeRoleWithWebIdentity +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the AssumeRoleWithWebIdentityRequest method. +// req, resp := client.AssumeRoleWithWebIdentityRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity +func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityInput) (req *request.Request, output *AssumeRoleWithWebIdentityOutput) { + op := &request.Operation{ + Name: opAssumeRoleWithWebIdentity, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &AssumeRoleWithWebIdentityInput{} + } + + output = &AssumeRoleWithWebIdentityOutput{} + req = c.newRequest(op, input, output) + return +} + +// AssumeRoleWithWebIdentity API operation for AWS Security Token Service. +// +// Returns a set of temporary security credentials for users who have been authenticated +// in a mobile or web application with a web identity provider, such as Amazon +// Cognito, Login with Amazon, Facebook, Google, or any OpenID Connect-compatible +// identity provider. +// +// For mobile applications, we recommend that you use Amazon Cognito. You can +// use Amazon Cognito with the AWS SDK for iOS (http://aws.amazon.com/sdkforios/) +// and the AWS SDK for Android (http://aws.amazon.com/sdkforandroid/) to uniquely +// identify a user and supply the user with a consistent identity throughout +// the lifetime of an application. +// +// To learn more about Amazon Cognito, see Amazon Cognito Overview (http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/cognito-auth.html#d0e840) +// in the AWS SDK for Android Developer Guide guide and Amazon Cognito Overview +// (http://docs.aws.amazon.com/mobile/sdkforios/developerguide/cognito-auth.html#d0e664) +// in the AWS SDK for iOS Developer Guide. +// +// Calling AssumeRoleWithWebIdentity does not require the use of AWS security +// credentials. Therefore, you can distribute an application (for example, on +// mobile devices) that requests temporary security credentials without including +// long-term AWS credentials in the application, and without deploying server-based +// proxy services that use long-term AWS credentials. Instead, the identity +// of the caller is validated by using a token from the web identity provider. +// For a comparison of AssumeRoleWithWebIdentity with the other APIs that produce +// temporary credentials, see Requesting Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) +// and Comparing the AWS STS APIs (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison) +// in the IAM User Guide. +// +// The temporary security credentials returned by this API consist of an access +// key ID, a secret access key, and a security token. Applications can use these +// temporary security credentials to sign calls to AWS service APIs. +// +// The credentials are valid for the duration that you specified when calling +// AssumeRoleWithWebIdentity, which can be from 900 seconds (15 minutes) to +// a maximum of 3600 seconds (1 hour). The default is 1 hour. +// +// The temporary security credentials created by AssumeRoleWithWebIdentity can +// be used to make API calls to any AWS service with the following exception: +// you cannot call the STS service's GetFederationToken or GetSessionToken APIs. +// +// Optionally, you can pass an IAM access policy to this operation. If you choose +// not to pass a policy, the temporary security credentials that are returned +// by the operation have the permissions that are defined in the access policy +// of the role that is being assumed. If you pass a policy to this operation, +// the temporary security credentials that are returned by the operation have +// the permissions that are allowed by both the access policy of the role that +// is being assumed, and the policy that you pass. This gives you a way to further +// restrict the permissions for the resulting temporary security credentials. +// You cannot use the passed policy to grant permissions that are in excess +// of those allowed by the access policy of the role that is being assumed. +// For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, +// and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) +// in the IAM User Guide. +// +// Before your application can call AssumeRoleWithWebIdentity, you must have +// an identity token from a supported identity provider and create a role that +// the application can assume. The role that your application assumes must trust +// the identity provider that is associated with the identity token. In other +// words, the identity provider must be specified in the role's trust policy. +// +// Calling AssumeRoleWithWebIdentity can result in an entry in your AWS CloudTrail +// logs. The entry includes the Subject (http://openid.net/specs/openid-connect-core-1_0.html#Claims) +// of the provided Web Identity Token. We recommend that you avoid using any +// personally identifiable information (PII) in this field. For example, you +// could instead use a GUID or a pairwise identifier, as suggested in the OIDC +// specification (http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes). +// +// For more information about how to use web identity federation and the AssumeRoleWithWebIdentity +// API, see the following resources: +// +// * Using Web Identity Federation APIs for Mobile Apps (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc_manual.html) +// and Federation Through a Web-based Identity Provider (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity). +// +// +// * Web Identity Federation Playground (https://web-identity-federation-playground.s3.amazonaws.com/index.html). +// This interactive website lets you walk through the process of authenticating +// via Login with Amazon, Facebook, or Google, getting temporary security +// credentials, and then using those credentials to make a request to AWS. +// +// +// * AWS SDK for iOS (http://aws.amazon.com/sdkforios/) and AWS SDK for Android +// (http://aws.amazon.com/sdkforandroid/). These toolkits contain sample +// apps that show how to invoke the identity providers, and then how to use +// the information from these providers to get and use temporary security +// credentials. +// +// * Web Identity Federation with Mobile Applications (http://aws.amazon.com/articles/4617974389850313). +// This article discusses web identity federation and shows an example of +// how to use web identity federation to get access to content in Amazon +// S3. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Security Token Service's +// API operation AssumeRoleWithWebIdentity for usage and error information. +// +// Returned Error Codes: +// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument" +// The request was rejected because the policy document was malformed. The error +// message describes the specific error. +// +// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge" +// The request was rejected because the policy document was too large. The error +// message describes how big the policy document is, in packed form, as a percentage +// of what the API allows. +// +// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim" +// The identity provider (IdP) reported that authentication failed. This might +// be because the claim is invalid. +// +// If this error is returned for the AssumeRoleWithWebIdentity operation, it +// can also mean that the claim has expired or has been explicitly revoked. +// +// * ErrCodeIDPCommunicationErrorException "IDPCommunicationError" +// The request could not be fulfilled because the non-AWS identity provider +// (IDP) that was asked to verify the incoming identity token could not be reached. +// This is often a transient error caused by network conditions. Retry the request +// a limited number of times so that you don't exceed the request rate. If the +// error persists, the non-AWS identity provider might be down or not responding. +// +// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken" +// The web identity token that was passed could not be validated by AWS. Get +// a new identity token from the identity provider and then retry the request. +// +// * ErrCodeExpiredTokenException "ExpiredTokenException" +// The web identity token that was passed is expired or is not valid. Get a +// new identity token from the identity provider and then retry the request. +// +// * ErrCodeRegionDisabledException "RegionDisabledException" +// STS is not activated in the requested region for the account that is being +// asked to generate credentials. The account administrator must use the IAM +// console to activate STS in that region. For more information, see Activating +// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the IAM User Guide. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity +func (c *STS) AssumeRoleWithWebIdentity(input *AssumeRoleWithWebIdentityInput) (*AssumeRoleWithWebIdentityOutput, error) { + req, out := c.AssumeRoleWithWebIdentityRequest(input) + return out, req.Send() +} + +// AssumeRoleWithWebIdentityWithContext is the same as AssumeRoleWithWebIdentity with the addition of +// the ability to pass a context and additional request options. +// +// See AssumeRoleWithWebIdentity for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *STS) AssumeRoleWithWebIdentityWithContext(ctx aws.Context, input *AssumeRoleWithWebIdentityInput, opts ...request.Option) (*AssumeRoleWithWebIdentityOutput, error) { + req, out := c.AssumeRoleWithWebIdentityRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opDecodeAuthorizationMessage = "DecodeAuthorizationMessage" + +// DecodeAuthorizationMessageRequest generates a "aws/request.Request" representing the +// client's request for the DecodeAuthorizationMessage operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See DecodeAuthorizationMessage for more information on using the DecodeAuthorizationMessage +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the DecodeAuthorizationMessageRequest method. +// req, resp := client.DecodeAuthorizationMessageRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage +func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessageInput) (req *request.Request, output *DecodeAuthorizationMessageOutput) { + op := &request.Operation{ + Name: opDecodeAuthorizationMessage, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &DecodeAuthorizationMessageInput{} + } + + output = &DecodeAuthorizationMessageOutput{} + req = c.newRequest(op, input, output) + return +} + +// DecodeAuthorizationMessage API operation for AWS Security Token Service. +// +// Decodes additional information about the authorization status of a request +// from an encoded message returned in response to an AWS request. +// +// For example, if a user is not authorized to perform an action that he or +// she has requested, the request returns a Client.UnauthorizedOperation response +// (an HTTP 403 response). Some AWS actions additionally return an encoded message +// that can provide details about this authorization failure. +// +// Only certain AWS actions return an encoded authorization message. The documentation +// for an individual action indicates whether that action returns an encoded +// message in addition to returning an HTTP code. +// +// The message is encoded because the details of the authorization status can +// constitute privileged information that the user who requested the action +// should not see. To decode an authorization status message, a user must be +// granted permissions via an IAM policy to request the DecodeAuthorizationMessage +// (sts:DecodeAuthorizationMessage) action. +// +// The decoded message includes the following type of information: +// +// * Whether the request was denied due to an explicit deny or due to the +// absence of an explicit allow. For more information, see Determining Whether +// a Request is Allowed or Denied (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow) +// in the IAM User Guide. +// +// * The principal who made the request. +// +// * The requested action. +// +// * The requested resource. +// +// * The values of condition keys in the context of the user's request. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Security Token Service's +// API operation DecodeAuthorizationMessage for usage and error information. +// +// Returned Error Codes: +// * ErrCodeInvalidAuthorizationMessageException "InvalidAuthorizationMessageException" +// The error returned if the message passed to DecodeAuthorizationMessage was +// invalid. This can happen if the token contains invalid characters, such as +// linebreaks. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage +func (c *STS) DecodeAuthorizationMessage(input *DecodeAuthorizationMessageInput) (*DecodeAuthorizationMessageOutput, error) { + req, out := c.DecodeAuthorizationMessageRequest(input) + return out, req.Send() +} + +// DecodeAuthorizationMessageWithContext is the same as DecodeAuthorizationMessage with the addition of +// the ability to pass a context and additional request options. +// +// See DecodeAuthorizationMessage for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *STS) DecodeAuthorizationMessageWithContext(ctx aws.Context, input *DecodeAuthorizationMessageInput, opts ...request.Option) (*DecodeAuthorizationMessageOutput, error) { + req, out := c.DecodeAuthorizationMessageRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opGetCallerIdentity = "GetCallerIdentity" + +// GetCallerIdentityRequest generates a "aws/request.Request" representing the +// client's request for the GetCallerIdentity operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See GetCallerIdentity for more information on using the GetCallerIdentity +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the GetCallerIdentityRequest method. +// req, resp := client.GetCallerIdentityRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity +func (c *STS) GetCallerIdentityRequest(input *GetCallerIdentityInput) (req *request.Request, output *GetCallerIdentityOutput) { + op := &request.Operation{ + Name: opGetCallerIdentity, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetCallerIdentityInput{} + } + + output = &GetCallerIdentityOutput{} + req = c.newRequest(op, input, output) + return +} + +// GetCallerIdentity API operation for AWS Security Token Service. +// +// Returns details about the IAM identity whose credentials are used to call +// the API. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Security Token Service's +// API operation GetCallerIdentity for usage and error information. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity +func (c *STS) GetCallerIdentity(input *GetCallerIdentityInput) (*GetCallerIdentityOutput, error) { + req, out := c.GetCallerIdentityRequest(input) + return out, req.Send() +} + +// GetCallerIdentityWithContext is the same as GetCallerIdentity with the addition of +// the ability to pass a context and additional request options. +// +// See GetCallerIdentity for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *STS) GetCallerIdentityWithContext(ctx aws.Context, input *GetCallerIdentityInput, opts ...request.Option) (*GetCallerIdentityOutput, error) { + req, out := c.GetCallerIdentityRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opGetFederationToken = "GetFederationToken" + +// GetFederationTokenRequest generates a "aws/request.Request" representing the +// client's request for the GetFederationToken operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See GetFederationToken for more information on using the GetFederationToken +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the GetFederationTokenRequest method. +// req, resp := client.GetFederationTokenRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken +func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *request.Request, output *GetFederationTokenOutput) { + op := &request.Operation{ + Name: opGetFederationToken, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetFederationTokenInput{} + } + + output = &GetFederationTokenOutput{} + req = c.newRequest(op, input, output) + return +} + +// GetFederationToken API operation for AWS Security Token Service. +// +// Returns a set of temporary security credentials (consisting of an access +// key ID, a secret access key, and a security token) for a federated user. +// A typical use is in a proxy application that gets temporary security credentials +// on behalf of distributed applications inside a corporate network. Because +// you must call the GetFederationToken action using the long-term security +// credentials of an IAM user, this call is appropriate in contexts where those +// credentials can be safely stored, usually in a server-based application. +// For a comparison of GetFederationToken with the other APIs that produce temporary +// credentials, see Requesting Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) +// and Comparing the AWS STS APIs (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison) +// in the IAM User Guide. +// +// If you are creating a mobile-based or browser-based app that can authenticate +// users using a web identity provider like Login with Amazon, Facebook, Google, +// or an OpenID Connect-compatible identity provider, we recommend that you +// use Amazon Cognito (http://aws.amazon.com/cognito/) or AssumeRoleWithWebIdentity. +// For more information, see Federation Through a Web-based Identity Provider +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity). +// +// The GetFederationToken action must be called by using the long-term AWS security +// credentials of an IAM user. You can also call GetFederationToken using the +// security credentials of an AWS root account, but we do not recommended it. +// Instead, we recommend that you create an IAM user for the purpose of the +// proxy application and then attach a policy to the IAM user that limits federated +// users to only the actions and resources that they need access to. For more +// information, see IAM Best Practices (http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) +// in the IAM User Guide. +// +// The temporary security credentials that are obtained by using the long-term +// credentials of an IAM user are valid for the specified duration, from 900 +// seconds (15 minutes) up to a maximium of 129600 seconds (36 hours). The default +// is 43200 seconds (12 hours). Temporary credentials that are obtained by using +// AWS root account credentials have a maximum duration of 3600 seconds (1 hour). +// +// The temporary security credentials created by GetFederationToken can be used +// to make API calls to any AWS service with the following exceptions: +// +// * You cannot use these credentials to call any IAM APIs. +// +// * You cannot call any STS APIs except GetCallerIdentity. +// +// Permissions +// +// The permissions for the temporary security credentials returned by GetFederationToken +// are determined by a combination of the following: +// +// * The policy or policies that are attached to the IAM user whose credentials +// are used to call GetFederationToken. +// +// * The policy that is passed as a parameter in the call. +// +// The passed policy is attached to the temporary security credentials that +// result from the GetFederationToken API call--that is, to the federated user. +// When the federated user makes an AWS request, AWS evaluates the policy attached +// to the federated user in combination with the policy or policies attached +// to the IAM user whose credentials were used to call GetFederationToken. AWS +// allows the federated user's request only when both the federated user and +// the IAM user are explicitly allowed to perform the requested action. The +// passed policy cannot grant more permissions than those that are defined in +// the IAM user policy. +// +// A typical use case is that the permissions of the IAM user whose credentials +// are used to call GetFederationToken are designed to allow access to all the +// actions and resources that any federated user will need. Then, for individual +// users, you pass a policy to the operation that scopes down the permissions +// to a level that's appropriate to that individual user, using a policy that +// allows only a subset of permissions that are granted to the IAM user. +// +// If you do not pass a policy, the resulting temporary security credentials +// have no effective permissions. The only exception is when the temporary security +// credentials are used to access a resource that has a resource-based policy +// that specifically allows the federated user to access the resource. +// +// For more information about how permissions work, see Permissions for GetFederationToken +// (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_getfederationtoken.html). +// For information about using GetFederationToken to create temporary security +// credentials, see GetFederationToken—Federation Through a Custom Identity +// Broker (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getfederationtoken). +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Security Token Service's +// API operation GetFederationToken for usage and error information. +// +// Returned Error Codes: +// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument" +// The request was rejected because the policy document was malformed. The error +// message describes the specific error. +// +// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge" +// The request was rejected because the policy document was too large. The error +// message describes how big the policy document is, in packed form, as a percentage +// of what the API allows. +// +// * ErrCodeRegionDisabledException "RegionDisabledException" +// STS is not activated in the requested region for the account that is being +// asked to generate credentials. The account administrator must use the IAM +// console to activate STS in that region. For more information, see Activating +// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the IAM User Guide. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken +func (c *STS) GetFederationToken(input *GetFederationTokenInput) (*GetFederationTokenOutput, error) { + req, out := c.GetFederationTokenRequest(input) + return out, req.Send() +} + +// GetFederationTokenWithContext is the same as GetFederationToken with the addition of +// the ability to pass a context and additional request options. +// +// See GetFederationToken for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *STS) GetFederationTokenWithContext(ctx aws.Context, input *GetFederationTokenInput, opts ...request.Option) (*GetFederationTokenOutput, error) { + req, out := c.GetFederationTokenRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +const opGetSessionToken = "GetSessionToken" + +// GetSessionTokenRequest generates a "aws/request.Request" representing the +// client's request for the GetSessionToken operation. The "output" return +// value will be populated with the request's response once the request complets +// successfuly. +// +// Use "Send" method on the returned Request to send the API call to the service. +// the "output" return value is not valid until after Send returns without error. +// +// See GetSessionToken for more information on using the GetSessionToken +// API call, and error handling. +// +// This method is useful when you want to inject custom logic or configuration +// into the SDK's request lifecycle. Such as custom headers, or retry logic. +// +// +// // Example sending a request using the GetSessionTokenRequest method. +// req, resp := client.GetSessionTokenRequest(params) +// +// err := req.Send() +// if err == nil { // resp is now filled +// fmt.Println(resp) +// } +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken +func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.Request, output *GetSessionTokenOutput) { + op := &request.Operation{ + Name: opGetSessionToken, + HTTPMethod: "POST", + HTTPPath: "/", + } + + if input == nil { + input = &GetSessionTokenInput{} + } + + output = &GetSessionTokenOutput{} + req = c.newRequest(op, input, output) + return +} + +// GetSessionToken API operation for AWS Security Token Service. +// +// Returns a set of temporary credentials for an AWS account or IAM user. The +// credentials consist of an access key ID, a secret access key, and a security +// token. Typically, you use GetSessionToken if you want to use MFA to protect +// programmatic calls to specific AWS APIs like Amazon EC2 StopInstances. MFA-enabled +// IAM users would need to call GetSessionToken and submit an MFA code that +// is associated with their MFA device. Using the temporary security credentials +// that are returned from the call, IAM users can then make programmatic calls +// to APIs that require MFA authentication. If you do not supply a correct MFA +// code, then the API returns an access denied error. For a comparison of GetSessionToken +// with the other APIs that produce temporary credentials, see Requesting Temporary +// Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) +// and Comparing the AWS STS APIs (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison) +// in the IAM User Guide. +// +// The GetSessionToken action must be called by using the long-term AWS security +// credentials of the AWS account or an IAM user. Credentials that are created +// by IAM users are valid for the duration that you specify, from 900 seconds +// (15 minutes) up to a maximum of 129600 seconds (36 hours), with a default +// of 43200 seconds (12 hours); credentials that are created by using account +// credentials can range from 900 seconds (15 minutes) up to a maximum of 3600 +// seconds (1 hour), with a default of 1 hour. +// +// The temporary security credentials created by GetSessionToken can be used +// to make API calls to any AWS service with the following exceptions: +// +// * You cannot call any IAM APIs unless MFA authentication information is +// included in the request. +// +// * You cannot call any STS API exceptAssumeRole or GetCallerIdentity. +// +// We recommend that you do not call GetSessionToken with root account credentials. +// Instead, follow our best practices (http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#create-iam-users) +// by creating one or more IAM users, giving them the necessary permissions, +// and using IAM users for everyday interaction with AWS. +// +// The permissions associated with the temporary security credentials returned +// by GetSessionToken are based on the permissions associated with account or +// IAM user whose credentials are used to call the action. If GetSessionToken +// is called using root account credentials, the temporary credentials have +// root account permissions. Similarly, if GetSessionToken is called using the +// credentials of an IAM user, the temporary credentials have the same permissions +// as the IAM user. +// +// For more information about using GetSessionToken to create temporary credentials, +// go to Temporary Credentials for Users in Untrusted Environments (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getsessiontoken) +// in the IAM User Guide. +// +// Returns awserr.Error for service API and SDK errors. Use runtime type assertions +// with awserr.Error's Code and Message methods to get detailed information about +// the error. +// +// See the AWS API reference guide for AWS Security Token Service's +// API operation GetSessionToken for usage and error information. +// +// Returned Error Codes: +// * ErrCodeRegionDisabledException "RegionDisabledException" +// STS is not activated in the requested region for the account that is being +// asked to generate credentials. The account administrator must use the IAM +// console to activate STS in that region. For more information, see Activating +// and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the IAM User Guide. +// +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken +func (c *STS) GetSessionToken(input *GetSessionTokenInput) (*GetSessionTokenOutput, error) { + req, out := c.GetSessionTokenRequest(input) + return out, req.Send() +} + +// GetSessionTokenWithContext is the same as GetSessionToken with the addition of +// the ability to pass a context and additional request options. +// +// See GetSessionToken for details on how to use this API operation. +// +// The context must be non-nil and will be used for request cancellation. If +// the context is nil a panic will occur. In the future the SDK may create +// sub-contexts for http.Requests. See https://golang.org/pkg/context/ +// for more information on using Contexts. +func (c *STS) GetSessionTokenWithContext(ctx aws.Context, input *GetSessionTokenInput, opts ...request.Option) (*GetSessionTokenOutput, error) { + req, out := c.GetSessionTokenRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleRequest +type AssumeRoleInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. + // + // This is separate from the duration of a console session that you might request + // using the returned credentials. The request to the federation endpoint for + // a console sign-in token takes a SessionDuration parameter that specifies + // the maximum length of the console session, separately from the DurationSeconds + // parameter on this API. For more information, see Creating a URL that Enables + // Federated Users to Access the AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) + // in the IAM User Guide. + DurationSeconds *int64 `min:"900" type:"integer"` + + // A unique identifier that is used by third parties when assuming roles in + // their customers' accounts. For each role that the third party can assume, + // they should instruct their customers to ensure the role's trust policy checks + // for the external ID that the third party generated. Each time the third party + // assumes the role, they should pass the customer's external ID. The external + // ID is useful in order to help third parties bind a role to the customer who + // created it. For more information about the external ID, see How to Use an + // External ID When Granting Access to Your AWS Resources to a Third Party (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html) + // in the IAM User Guide. + // + // The regex used to validated this parameter is a string of characters consisting + // of upper- and lower-case alphanumeric characters with no spaces. You can + // also include underscores or any of the following characters: =,.@:/- + ExternalId *string `min:"2" type:"string"` + + // An IAM policy in JSON format. + // + // This parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both (the intersection of) the access policy of the role that + // is being assumed, and the policy that you pass. This gives you a way to further + // restrict the permissions for the resulting temporary security credentials. + // You cannot use the passed policy to grant permissions that are in excess + // of those allowed by the access policy of the role that is being assumed. + // For more information, see Permissions for AssumeRole, AssumeRoleWithSAML, + // and AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the IAM User Guide. + // + // The format for this parameter, as described by its regex pattern, is a string + // of characters up to 2048 characters in length. The characters can be any + // ASCII character from the space character to the end of the valid character + // list (\u0020-\u00FF). It can also include the tab (\u0009), linefeed (\u000A), + // and carriage return (\u000D) characters. + // + // 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 `min:"1" type:"string"` + + // The Amazon Resource Name (ARN) of the role to assume. + // + // RoleArn is a required field + RoleArn *string `min:"20" type:"string" required:"true"` + + // An identifier for the assumed role session. + // + // Use the role session name to uniquely identify a session when the same role + // is assumed by different principals or for different reasons. In cross-account + // scenarios, the role session name is visible to, and can be logged by the + // account that owns the role. The role session name is also used in the ARN + // of the assumed role principal. This means that subsequent cross-account API + // requests using the temporary security credentials will expose the role session + // name to the external account in their CloudTrail logs. + // + // The regex used to validate this parameter is a string of characters consisting + // of upper- and lower-case alphanumeric characters with no spaces. You can + // also include underscores or any of the following characters: =,.@- + // + // RoleSessionName is a required field + RoleSessionName *string `min:"2" type:"string" required:"true"` + + // 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). + // + // The regex used to validate this parameter is a string of characters consisting + // of upper- and lower-case alphanumeric characters with no spaces. You can + // also include underscores or any of the following characters: =,.@- + SerialNumber *string `min:"9" type:"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. + // + // The format for this parameter, as described by its regex pattern, is a sequence + // of six numeric digits. + TokenCode *string `min:"6" type:"string"` +} + +// String returns the string representation +func (s AssumeRoleInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *AssumeRoleInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "AssumeRoleInput"} + if s.DurationSeconds != nil && *s.DurationSeconds < 900 { + invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900)) + } + if s.ExternalId != nil && len(*s.ExternalId) < 2 { + invalidParams.Add(request.NewErrParamMinLen("ExternalId", 2)) + } + if s.Policy != nil && len(*s.Policy) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Policy", 1)) + } + if s.RoleArn == nil { + invalidParams.Add(request.NewErrParamRequired("RoleArn")) + } + if s.RoleArn != nil && len(*s.RoleArn) < 20 { + invalidParams.Add(request.NewErrParamMinLen("RoleArn", 20)) + } + if s.RoleSessionName == nil { + invalidParams.Add(request.NewErrParamRequired("RoleSessionName")) + } + if s.RoleSessionName != nil && len(*s.RoleSessionName) < 2 { + invalidParams.Add(request.NewErrParamMinLen("RoleSessionName", 2)) + } + if s.SerialNumber != nil && len(*s.SerialNumber) < 9 { + invalidParams.Add(request.NewErrParamMinLen("SerialNumber", 9)) + } + if s.TokenCode != nil && len(*s.TokenCode) < 6 { + invalidParams.Add(request.NewErrParamMinLen("TokenCode", 6)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetDurationSeconds sets the DurationSeconds field's value. +func (s *AssumeRoleInput) SetDurationSeconds(v int64) *AssumeRoleInput { + s.DurationSeconds = &v + return s +} + +// SetExternalId sets the ExternalId field's value. +func (s *AssumeRoleInput) SetExternalId(v string) *AssumeRoleInput { + s.ExternalId = &v + return s +} + +// SetPolicy sets the Policy field's value. +func (s *AssumeRoleInput) SetPolicy(v string) *AssumeRoleInput { + s.Policy = &v + return s +} + +// SetRoleArn sets the RoleArn field's value. +func (s *AssumeRoleInput) SetRoleArn(v string) *AssumeRoleInput { + s.RoleArn = &v + return s +} + +// SetRoleSessionName sets the RoleSessionName field's value. +func (s *AssumeRoleInput) SetRoleSessionName(v string) *AssumeRoleInput { + s.RoleSessionName = &v + return s +} + +// SetSerialNumber sets the SerialNumber field's value. +func (s *AssumeRoleInput) SetSerialNumber(v string) *AssumeRoleInput { + s.SerialNumber = &v + return s +} + +// SetTokenCode sets the TokenCode field's value. +func (s *AssumeRoleInput) SetTokenCode(v string) *AssumeRoleInput { + s.TokenCode = &v + return s +} + +// Contains the response to a successful AssumeRole request, including temporary +// AWS credentials that can be used to make AWS requests. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleResponse +type AssumeRoleOutput struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers + // that you can use to refer to the resulting temporary security credentials. + // For example, you can reference these credentials as a principal in a resource-based + // policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName + // that you specified when you called AssumeRole. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. We + // strongly recommend that you make no assumptions about the maximum size. As + // of this writing, the typical size is less than 4096 bytes, but that can vary. + // Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` +} + +// String returns the string representation +func (s AssumeRoleOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleOutput) GoString() string { + return s.String() +} + +// SetAssumedRoleUser sets the AssumedRoleUser field's value. +func (s *AssumeRoleOutput) SetAssumedRoleUser(v *AssumedRoleUser) *AssumeRoleOutput { + s.AssumedRoleUser = v + return s +} + +// SetCredentials sets the Credentials field's value. +func (s *AssumeRoleOutput) SetCredentials(v *Credentials) *AssumeRoleOutput { + s.Credentials = v + return s +} + +// SetPackedPolicySize sets the PackedPolicySize field's value. +func (s *AssumeRoleOutput) SetPackedPolicySize(v int64) *AssumeRoleOutput { + s.PackedPolicySize = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAMLRequest +type AssumeRoleWithSAMLInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. An expiration can also be specified in the SAML authentication + // response's SessionNotOnOrAfter value. The actual expiration time is whichever + // value is shorter. + // + // This is separate from the duration of a console session that you might request + // using the returned credentials. The request to the federation endpoint for + // a console sign-in token takes a SessionDuration parameter that specifies + // the maximum length of the console session, separately from the DurationSeconds + // parameter on this API. For more information, see Enabling SAML 2.0 Federated + // Users to Access the AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-saml.html) + // in the IAM User Guide. + DurationSeconds *int64 `min:"900" type:"integer"` + + // An IAM policy in JSON format. + // + // The policy parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both the access policy of the role that is being assumed, + // and the policy that you pass. This gives you a way to further restrict the + // permissions for the resulting temporary security credentials. You cannot + // use the passed policy to grant permissions that are in excess of those allowed + // by the access policy of the role that is being assumed. For more information, + // Permissions for AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity + // (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the IAM User Guide. + // + // The format for this parameter, as described by its regex pattern, is a string + // of characters up to 2048 characters in length. The characters can be any + // ASCII character from the space character to the end of the valid character + // list (\u0020-\u00FF). It can also include the tab (\u0009), linefeed (\u000A), + // and carriage return (\u000D) characters. + // + // 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 `min:"1" type:"string"` + + // The Amazon Resource Name (ARN) of the SAML provider in IAM that describes + // the IdP. + // + // PrincipalArn is a required field + PrincipalArn *string `min:"20" type:"string" required:"true"` + + // The Amazon Resource Name (ARN) of the role that the caller is assuming. + // + // RoleArn is a required field + RoleArn *string `min:"20" type:"string" required:"true"` + + // The base-64 encoded SAML authentication response provided by the IdP. + // + // For more information, see Configuring a Relying Party and Adding Claims (http://docs.aws.amazon.com/IAM/latest/UserGuide/create-role-saml-IdP-tasks.html) + // in the Using IAM guide. + // + // SAMLAssertion is a required field + SAMLAssertion *string `min:"4" type:"string" required:"true"` +} + +// String returns the string representation +func (s AssumeRoleWithSAMLInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithSAMLInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *AssumeRoleWithSAMLInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "AssumeRoleWithSAMLInput"} + if s.DurationSeconds != nil && *s.DurationSeconds < 900 { + invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900)) + } + if s.Policy != nil && len(*s.Policy) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Policy", 1)) + } + if s.PrincipalArn == nil { + invalidParams.Add(request.NewErrParamRequired("PrincipalArn")) + } + if s.PrincipalArn != nil && len(*s.PrincipalArn) < 20 { + invalidParams.Add(request.NewErrParamMinLen("PrincipalArn", 20)) + } + if s.RoleArn == nil { + invalidParams.Add(request.NewErrParamRequired("RoleArn")) + } + if s.RoleArn != nil && len(*s.RoleArn) < 20 { + invalidParams.Add(request.NewErrParamMinLen("RoleArn", 20)) + } + if s.SAMLAssertion == nil { + invalidParams.Add(request.NewErrParamRequired("SAMLAssertion")) + } + if s.SAMLAssertion != nil && len(*s.SAMLAssertion) < 4 { + invalidParams.Add(request.NewErrParamMinLen("SAMLAssertion", 4)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetDurationSeconds sets the DurationSeconds field's value. +func (s *AssumeRoleWithSAMLInput) SetDurationSeconds(v int64) *AssumeRoleWithSAMLInput { + s.DurationSeconds = &v + return s +} + +// SetPolicy sets the Policy field's value. +func (s *AssumeRoleWithSAMLInput) SetPolicy(v string) *AssumeRoleWithSAMLInput { + s.Policy = &v + return s +} + +// SetPrincipalArn sets the PrincipalArn field's value. +func (s *AssumeRoleWithSAMLInput) SetPrincipalArn(v string) *AssumeRoleWithSAMLInput { + s.PrincipalArn = &v + return s +} + +// SetRoleArn sets the RoleArn field's value. +func (s *AssumeRoleWithSAMLInput) SetRoleArn(v string) *AssumeRoleWithSAMLInput { + s.RoleArn = &v + return s +} + +// SetSAMLAssertion sets the SAMLAssertion field's value. +func (s *AssumeRoleWithSAMLInput) SetSAMLAssertion(v string) *AssumeRoleWithSAMLInput { + s.SAMLAssertion = &v + return s +} + +// Contains the response to a successful AssumeRoleWithSAML request, including +// temporary AWS credentials that can be used to make AWS requests. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAMLResponse +type AssumeRoleWithSAMLOutput struct { + _ struct{} `type:"structure"` + + // The identifiers for the temporary security credentials that the operation + // returns. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The value of the Recipient attribute of the SubjectConfirmationData element + // of the SAML assertion. + Audience *string `type:"string"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. We + // strongly recommend that you make no assumptions about the maximum size. As + // of this writing, the typical size is less than 4096 bytes, but that can vary. + // Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // The value of the Issuer element of the SAML assertion. + Issuer *string `type:"string"` + + // A hash value based on the concatenation of the Issuer response value, the + // AWS account ID, and the friendly name (the last part of the ARN) of the SAML + // provider in IAM. The combination of NameQualifier and Subject can be used + // to uniquely identify a federated user. + // + // The following pseudocode shows how the hash value is calculated: + // + // BASE64 ( SHA1 ( "https://example.com/saml" + "123456789012" + "/MySAMLIdP" + // ) ) + NameQualifier *string `type:"string"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` + + // The value of the NameID element in the Subject element of the SAML assertion. + Subject *string `type:"string"` + + // The format of the name ID, as defined by the Format attribute in the NameID + // element of the SAML assertion. Typical examples of the format are transient + // or persistent. + // + // If the format includes the prefix urn:oasis:names:tc:SAML:2.0:nameid-format, + // that prefix is removed. For example, urn:oasis:names:tc:SAML:2.0:nameid-format:transient + // is returned as transient. If the format includes any other prefix, the format + // is returned with no modifications. + SubjectType *string `type:"string"` +} + +// String returns the string representation +func (s AssumeRoleWithSAMLOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithSAMLOutput) GoString() string { + return s.String() +} + +// SetAssumedRoleUser sets the AssumedRoleUser field's value. +func (s *AssumeRoleWithSAMLOutput) SetAssumedRoleUser(v *AssumedRoleUser) *AssumeRoleWithSAMLOutput { + s.AssumedRoleUser = v + return s +} + +// SetAudience sets the Audience field's value. +func (s *AssumeRoleWithSAMLOutput) SetAudience(v string) *AssumeRoleWithSAMLOutput { + s.Audience = &v + return s +} + +// SetCredentials sets the Credentials field's value. +func (s *AssumeRoleWithSAMLOutput) SetCredentials(v *Credentials) *AssumeRoleWithSAMLOutput { + s.Credentials = v + return s +} + +// SetIssuer sets the Issuer field's value. +func (s *AssumeRoleWithSAMLOutput) SetIssuer(v string) *AssumeRoleWithSAMLOutput { + s.Issuer = &v + return s +} + +// SetNameQualifier sets the NameQualifier field's value. +func (s *AssumeRoleWithSAMLOutput) SetNameQualifier(v string) *AssumeRoleWithSAMLOutput { + s.NameQualifier = &v + return s +} + +// SetPackedPolicySize sets the PackedPolicySize field's value. +func (s *AssumeRoleWithSAMLOutput) SetPackedPolicySize(v int64) *AssumeRoleWithSAMLOutput { + s.PackedPolicySize = &v + return s +} + +// SetSubject sets the Subject field's value. +func (s *AssumeRoleWithSAMLOutput) SetSubject(v string) *AssumeRoleWithSAMLOutput { + s.Subject = &v + return s +} + +// SetSubjectType sets the SubjectType field's value. +func (s *AssumeRoleWithSAMLOutput) SetSubjectType(v string) *AssumeRoleWithSAMLOutput { + s.SubjectType = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentityRequest +type AssumeRoleWithWebIdentityInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, of the role session. The value can range from 900 + // seconds (15 minutes) to 3600 seconds (1 hour). By default, the value is set + // to 3600 seconds. + // + // This is separate from the duration of a console session that you might request + // using the returned credentials. The request to the federation endpoint for + // a console sign-in token takes a SessionDuration parameter that specifies + // the maximum length of the console session, separately from the DurationSeconds + // parameter on this API. For more information, see Creating a URL that Enables + // Federated Users to Access the AWS Management Console (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) + // in the IAM User Guide. + DurationSeconds *int64 `min:"900" type:"integer"` + + // An IAM policy in JSON format. + // + // The policy parameter is optional. If you pass a policy, the temporary security + // credentials that are returned by the operation have the permissions that + // are allowed by both the access policy of the role that is being assumed, + // and the policy that you pass. This gives you a way to further restrict the + // permissions for the resulting temporary security credentials. You cannot + // use the passed policy to grant permissions that are in excess of those allowed + // by the access policy of the role that is being assumed. For more information, + // see Permissions for AssumeRoleWithWebIdentity (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html) + // in the IAM User Guide. + // + // The format for this parameter, as described by its regex pattern, is a string + // of characters up to 2048 characters in length. The characters can be any + // ASCII character from the space character to the end of the valid character + // list (\u0020-\u00FF). It can also include the tab (\u0009), linefeed (\u000A), + // and carriage return (\u000D) characters. + // + // 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 `min:"1" type:"string"` + + // The fully qualified host component of the domain name of the identity provider. + // + // Specify this value only for OAuth 2.0 access tokens. Currently www.amazon.com + // and graph.facebook.com are the only supported identity providers for OAuth + // 2.0 access tokens. Do not include URL schemes and port numbers. + // + // Do not specify this value for OpenID Connect ID tokens. + ProviderId *string `min:"4" type:"string"` + + // The Amazon Resource Name (ARN) of the role that the caller is assuming. + // + // RoleArn is a required field + RoleArn *string `min:"20" type:"string" required:"true"` + + // An identifier for the assumed role session. Typically, you pass the name + // or identifier that is associated with the user who is using your application. + // That way, the temporary security credentials that your application will use + // are associated with that user. This session name is included as part of the + // ARN and assumed role ID in the AssumedRoleUser response element. + // + // The regex used to validate this parameter is a string of characters consisting + // of upper- and lower-case alphanumeric characters with no spaces. You can + // also include underscores or any of the following characters: =,.@- + // + // RoleSessionName is a required field + RoleSessionName *string `min:"2" type:"string" required:"true"` + + // The OAuth 2.0 access token or OpenID Connect ID token that is provided by + // the identity provider. Your application must get this token by authenticating + // the user who is using your application with a web identity provider before + // the application makes an AssumeRoleWithWebIdentity call. + // + // WebIdentityToken is a required field + WebIdentityToken *string `min:"4" type:"string" required:"true"` +} + +// String returns the string representation +func (s AssumeRoleWithWebIdentityInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithWebIdentityInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *AssumeRoleWithWebIdentityInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "AssumeRoleWithWebIdentityInput"} + if s.DurationSeconds != nil && *s.DurationSeconds < 900 { + invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900)) + } + if s.Policy != nil && len(*s.Policy) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Policy", 1)) + } + if s.ProviderId != nil && len(*s.ProviderId) < 4 { + invalidParams.Add(request.NewErrParamMinLen("ProviderId", 4)) + } + if s.RoleArn == nil { + invalidParams.Add(request.NewErrParamRequired("RoleArn")) + } + if s.RoleArn != nil && len(*s.RoleArn) < 20 { + invalidParams.Add(request.NewErrParamMinLen("RoleArn", 20)) + } + if s.RoleSessionName == nil { + invalidParams.Add(request.NewErrParamRequired("RoleSessionName")) + } + if s.RoleSessionName != nil && len(*s.RoleSessionName) < 2 { + invalidParams.Add(request.NewErrParamMinLen("RoleSessionName", 2)) + } + if s.WebIdentityToken == nil { + invalidParams.Add(request.NewErrParamRequired("WebIdentityToken")) + } + if s.WebIdentityToken != nil && len(*s.WebIdentityToken) < 4 { + invalidParams.Add(request.NewErrParamMinLen("WebIdentityToken", 4)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetDurationSeconds sets the DurationSeconds field's value. +func (s *AssumeRoleWithWebIdentityInput) SetDurationSeconds(v int64) *AssumeRoleWithWebIdentityInput { + s.DurationSeconds = &v + return s +} + +// SetPolicy sets the Policy field's value. +func (s *AssumeRoleWithWebIdentityInput) SetPolicy(v string) *AssumeRoleWithWebIdentityInput { + s.Policy = &v + return s +} + +// SetProviderId sets the ProviderId field's value. +func (s *AssumeRoleWithWebIdentityInput) SetProviderId(v string) *AssumeRoleWithWebIdentityInput { + s.ProviderId = &v + return s +} + +// SetRoleArn sets the RoleArn field's value. +func (s *AssumeRoleWithWebIdentityInput) SetRoleArn(v string) *AssumeRoleWithWebIdentityInput { + s.RoleArn = &v + return s +} + +// SetRoleSessionName sets the RoleSessionName field's value. +func (s *AssumeRoleWithWebIdentityInput) SetRoleSessionName(v string) *AssumeRoleWithWebIdentityInput { + s.RoleSessionName = &v + return s +} + +// SetWebIdentityToken sets the WebIdentityToken field's value. +func (s *AssumeRoleWithWebIdentityInput) SetWebIdentityToken(v string) *AssumeRoleWithWebIdentityInput { + s.WebIdentityToken = &v + return s +} + +// Contains the response to a successful AssumeRoleWithWebIdentity request, +// including temporary AWS credentials that can be used to make AWS requests. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentityResponse +type AssumeRoleWithWebIdentityOutput struct { + _ struct{} `type:"structure"` + + // The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers + // that you can use to refer to the resulting temporary security credentials. + // For example, you can reference these credentials as a principal in a resource-based + // policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName + // that you specified when you called AssumeRole. + AssumedRoleUser *AssumedRoleUser `type:"structure"` + + // The intended audience (also known as client ID) of the web identity token. + // This is traditionally the client identifier issued to the application that + // requested the web identity token. + Audience *string `type:"string"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security token. + // + // Note: The size of the security token that STS APIs return is not fixed. We + // strongly recommend that you make no assumptions about the maximum size. As + // of this writing, the typical size is less than 4096 bytes, but that can vary. + // Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // A percentage value that indicates the size of the policy in packed form. + // The service rejects any policy with a packed size greater than 100 percent, + // which means the policy exceeded the allowed space. + PackedPolicySize *int64 `type:"integer"` + + // The issuing authority of the web identity token presented. For OpenID Connect + // ID Tokens this contains the value of the iss field. For OAuth 2.0 access + // tokens, this contains the value of the ProviderId parameter that was passed + // in the AssumeRoleWithWebIdentity request. + Provider *string `type:"string"` + + // The unique user identifier that is returned by the identity provider. This + // identifier is associated with the WebIdentityToken that was submitted with + // the AssumeRoleWithWebIdentity call. The identifier is typically unique to + // the user and the application that acquired the WebIdentityToken (pairwise + // identifier). For OpenID Connect ID tokens, this field contains the value + // returned by the identity provider as the token's sub (Subject) claim. + SubjectFromWebIdentityToken *string `min:"6" type:"string"` +} + +// String returns the string representation +func (s AssumeRoleWithWebIdentityOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumeRoleWithWebIdentityOutput) GoString() string { + return s.String() +} + +// SetAssumedRoleUser sets the AssumedRoleUser field's value. +func (s *AssumeRoleWithWebIdentityOutput) SetAssumedRoleUser(v *AssumedRoleUser) *AssumeRoleWithWebIdentityOutput { + s.AssumedRoleUser = v + return s +} + +// SetAudience sets the Audience field's value. +func (s *AssumeRoleWithWebIdentityOutput) SetAudience(v string) *AssumeRoleWithWebIdentityOutput { + s.Audience = &v + return s +} + +// SetCredentials sets the Credentials field's value. +func (s *AssumeRoleWithWebIdentityOutput) SetCredentials(v *Credentials) *AssumeRoleWithWebIdentityOutput { + s.Credentials = v + return s +} + +// SetPackedPolicySize sets the PackedPolicySize field's value. +func (s *AssumeRoleWithWebIdentityOutput) SetPackedPolicySize(v int64) *AssumeRoleWithWebIdentityOutput { + s.PackedPolicySize = &v + return s +} + +// SetProvider sets the Provider field's value. +func (s *AssumeRoleWithWebIdentityOutput) SetProvider(v string) *AssumeRoleWithWebIdentityOutput { + s.Provider = &v + return s +} + +// SetSubjectFromWebIdentityToken sets the SubjectFromWebIdentityToken field's value. +func (s *AssumeRoleWithWebIdentityOutput) SetSubjectFromWebIdentityToken(v string) *AssumeRoleWithWebIdentityOutput { + s.SubjectFromWebIdentityToken = &v + return s +} + +// The identifiers for the temporary security credentials that the operation +// returns. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumedRoleUser +type AssumedRoleUser struct { + _ struct{} `type:"structure"` + + // The ARN of the temporary security credentials that are returned from the + // AssumeRole action. For more information about ARNs and how to use them in + // policies, see IAM Identifiers (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) + // in Using IAM. + // + // Arn is a required field + Arn *string `min:"20" type:"string" required:"true"` + + // A unique identifier that contains the role ID and the role session name of + // the role that is being assumed. The role ID is generated by AWS when the + // role is created. + // + // AssumedRoleId is a required field + AssumedRoleId *string `min:"2" type:"string" required:"true"` +} + +// String returns the string representation +func (s AssumedRoleUser) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s AssumedRoleUser) GoString() string { + return s.String() +} + +// SetArn sets the Arn field's value. +func (s *AssumedRoleUser) SetArn(v string) *AssumedRoleUser { + s.Arn = &v + return s +} + +// SetAssumedRoleId sets the AssumedRoleId field's value. +func (s *AssumedRoleUser) SetAssumedRoleId(v string) *AssumedRoleUser { + s.AssumedRoleId = &v + return s +} + +// AWS credentials for API authentication. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/Credentials +type Credentials struct { + _ struct{} `type:"structure"` + + // The access key ID that identifies the temporary security credentials. + // + // AccessKeyId is a required field + AccessKeyId *string `min:"16" type:"string" required:"true"` + + // The date on which the current credentials expire. + // + // Expiration is a required field + Expiration *time.Time `type:"timestamp" timestampFormat:"iso8601" required:"true"` + + // The secret access key that can be used to sign requests. + // + // SecretAccessKey is a required field + SecretAccessKey *string `type:"string" required:"true"` + + // The token that users must pass to the service API to use the temporary credentials. + // + // SessionToken is a required field + SessionToken *string `type:"string" required:"true"` +} + +// String returns the string representation +func (s Credentials) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s Credentials) GoString() string { + return s.String() +} + +// SetAccessKeyId sets the AccessKeyId field's value. +func (s *Credentials) SetAccessKeyId(v string) *Credentials { + s.AccessKeyId = &v + return s +} + +// SetExpiration sets the Expiration field's value. +func (s *Credentials) SetExpiration(v time.Time) *Credentials { + s.Expiration = &v + return s +} + +// SetSecretAccessKey sets the SecretAccessKey field's value. +func (s *Credentials) SetSecretAccessKey(v string) *Credentials { + s.SecretAccessKey = &v + return s +} + +// SetSessionToken sets the SessionToken field's value. +func (s *Credentials) SetSessionToken(v string) *Credentials { + s.SessionToken = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessageRequest +type DecodeAuthorizationMessageInput struct { + _ struct{} `type:"structure"` + + // The encoded message that was returned with the response. + // + // EncodedMessage is a required field + EncodedMessage *string `min:"1" type:"string" required:"true"` +} + +// String returns the string representation +func (s DecodeAuthorizationMessageInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DecodeAuthorizationMessageInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *DecodeAuthorizationMessageInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "DecodeAuthorizationMessageInput"} + if s.EncodedMessage == nil { + invalidParams.Add(request.NewErrParamRequired("EncodedMessage")) + } + if s.EncodedMessage != nil && len(*s.EncodedMessage) < 1 { + invalidParams.Add(request.NewErrParamMinLen("EncodedMessage", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetEncodedMessage sets the EncodedMessage field's value. +func (s *DecodeAuthorizationMessageInput) SetEncodedMessage(v string) *DecodeAuthorizationMessageInput { + s.EncodedMessage = &v + return s +} + +// A document that contains additional information about the authorization status +// of a request from an encoded message that is returned in response to an AWS +// request. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessageResponse +type DecodeAuthorizationMessageOutput struct { + _ struct{} `type:"structure"` + + // An XML document that contains the decoded message. + DecodedMessage *string `type:"string"` +} + +// String returns the string representation +func (s DecodeAuthorizationMessageOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s DecodeAuthorizationMessageOutput) GoString() string { + return s.String() +} + +// SetDecodedMessage sets the DecodedMessage field's value. +func (s *DecodeAuthorizationMessageOutput) SetDecodedMessage(v string) *DecodeAuthorizationMessageOutput { + s.DecodedMessage = &v + return s +} + +// Identifiers for the federated user that is associated with the credentials. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/FederatedUser +type FederatedUser struct { + _ struct{} `type:"structure"` + + // The ARN that specifies the federated user that is associated with the credentials. + // For more information about ARNs and how to use them in policies, see IAM + // Identifiers (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html) + // in Using IAM. + // + // Arn is a required field + Arn *string `min:"20" type:"string" required:"true"` + + // The string that identifies the federated user associated with the credentials, + // similar to the unique ID of an IAM user. + // + // FederatedUserId is a required field + FederatedUserId *string `min:"2" type:"string" required:"true"` +} + +// String returns the string representation +func (s FederatedUser) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s FederatedUser) GoString() string { + return s.String() +} + +// SetArn sets the Arn field's value. +func (s *FederatedUser) SetArn(v string) *FederatedUser { + s.Arn = &v + return s +} + +// SetFederatedUserId sets the FederatedUserId field's value. +func (s *FederatedUser) SetFederatedUserId(v string) *FederatedUser { + s.FederatedUserId = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentityRequest +type GetCallerIdentityInput struct { + _ struct{} `type:"structure"` +} + +// String returns the string representation +func (s GetCallerIdentityInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetCallerIdentityInput) GoString() string { + return s.String() +} + +// Contains the response to a successful GetCallerIdentity request, including +// information about the entity making the request. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentityResponse +type GetCallerIdentityOutput struct { + _ struct{} `type:"structure"` + + // The AWS account ID number of the account that owns or contains the calling + // entity. + Account *string `type:"string"` + + // The AWS ARN associated with the calling entity. + Arn *string `min:"20" type:"string"` + + // The unique identifier of the calling entity. The exact value depends on the + // type of entity making the call. The values returned are those listed in the + // aws:userid column in the Principal table (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#principaltable) + // found on the Policy Variables reference page in the IAM User Guide. + UserId *string `type:"string"` +} + +// String returns the string representation +func (s GetCallerIdentityOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetCallerIdentityOutput) GoString() string { + return s.String() +} + +// SetAccount sets the Account field's value. +func (s *GetCallerIdentityOutput) SetAccount(v string) *GetCallerIdentityOutput { + s.Account = &v + return s +} + +// SetArn sets the Arn field's value. +func (s *GetCallerIdentityOutput) SetArn(v string) *GetCallerIdentityOutput { + s.Arn = &v + return s +} + +// SetUserId sets the UserId field's value. +func (s *GetCallerIdentityOutput) SetUserId(v string) *GetCallerIdentityOutput { + s.UserId = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationTokenRequest +type GetFederationTokenInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, that the session should last. Acceptable durations + // for federation sessions range from 900 seconds (15 minutes) to 129600 seconds + // (36 hours), with 43200 seconds (12 hours) as the default. Sessions obtained + // using AWS account (root) credentials are restricted to a maximum of 3600 + // seconds (one hour). If the specified duration is longer than one hour, the + // session obtained by using AWS account (root) credentials defaults to one + // hour. + DurationSeconds *int64 `min:"900" type:"integer"` + + // The name of the federated user. The name is used as an identifier for the + // temporary security credentials (such as Bob). For example, you can reference + // the federated user name in a resource-based policy, such as in an Amazon + // S3 bucket policy. + // + // The regex used to validate this parameter is a string of characters consisting + // of upper- and lower-case alphanumeric characters with no spaces. You can + // also include underscores or any of the following characters: =,.@- + // + // Name is a required field + Name *string `min:"2" type:"string" required:"true"` + + // An IAM policy in JSON format that is passed with the GetFederationToken call + // and evaluated along with the policy or policies that are attached to the + // IAM user whose credentials are used to call GetFederationToken. The passed + // policy is used to scope down the permissions that are available to the IAM + // user, by allowing only a subset of the permissions that are granted to the + // IAM user. The passed policy cannot grant more permissions than those granted + // to the IAM user. The final permissions for the federated user are the most + // restrictive set based on the intersection of the passed policy and the IAM + // user policy. + // + // If you do not pass a policy, the resulting temporary security credentials + // have no effective permissions. The only exception is when the temporary security + // credentials are used to access a resource that has a resource-based policy + // that specifically allows the federated user to access the resource. + // + // The format for this parameter, as described by its regex pattern, is a string + // of characters up to 2048 characters in length. The characters can be any + // ASCII character from the space character to the end of the valid character + // list (\u0020-\u00FF). It can also include the tab (\u0009), linefeed (\u000A), + // and carriage return (\u000D) characters. + // + // 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. + // + // For more information about how permissions work, see Permissions for GetFederationToken + // (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_getfederationtoken.html). + Policy *string `min:"1" type:"string"` +} + +// String returns the string representation +func (s GetFederationTokenInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetFederationTokenInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetFederationTokenInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetFederationTokenInput"} + if s.DurationSeconds != nil && *s.DurationSeconds < 900 { + invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900)) + } + if s.Name == nil { + invalidParams.Add(request.NewErrParamRequired("Name")) + } + if s.Name != nil && len(*s.Name) < 2 { + invalidParams.Add(request.NewErrParamMinLen("Name", 2)) + } + if s.Policy != nil && len(*s.Policy) < 1 { + invalidParams.Add(request.NewErrParamMinLen("Policy", 1)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetDurationSeconds sets the DurationSeconds field's value. +func (s *GetFederationTokenInput) SetDurationSeconds(v int64) *GetFederationTokenInput { + s.DurationSeconds = &v + return s +} + +// SetName sets the Name field's value. +func (s *GetFederationTokenInput) SetName(v string) *GetFederationTokenInput { + s.Name = &v + return s +} + +// SetPolicy sets the Policy field's value. +func (s *GetFederationTokenInput) SetPolicy(v string) *GetFederationTokenInput { + s.Policy = &v + return s +} + +// Contains the response to a successful GetFederationToken request, including +// temporary AWS credentials that can be used to make AWS requests. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationTokenResponse +type GetFederationTokenOutput struct { + _ struct{} `type:"structure"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. We + // strongly recommend that you make no assumptions about the maximum size. As + // of this writing, the typical size is less than 4096 bytes, but that can vary. + // Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` + + // Identifiers for the federated user associated with the credentials (such + // as arn:aws:sts::123456789012:federated-user/Bob or 123456789012:Bob). You + // can use the federated user's ARN in your resource-based policies, such as + // an Amazon S3 bucket policy. + FederatedUser *FederatedUser `type:"structure"` + + // A percentage value indicating the size of the policy in packed form. The + // service rejects policies for which the packed size is greater than 100 percent + // of the allowed value. + PackedPolicySize *int64 `type:"integer"` +} + +// String returns the string representation +func (s GetFederationTokenOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetFederationTokenOutput) GoString() string { + return s.String() +} + +// SetCredentials sets the Credentials field's value. +func (s *GetFederationTokenOutput) SetCredentials(v *Credentials) *GetFederationTokenOutput { + s.Credentials = v + return s +} + +// SetFederatedUser sets the FederatedUser field's value. +func (s *GetFederationTokenOutput) SetFederatedUser(v *FederatedUser) *GetFederationTokenOutput { + s.FederatedUser = v + return s +} + +// SetPackedPolicySize sets the PackedPolicySize field's value. +func (s *GetFederationTokenOutput) SetPackedPolicySize(v int64) *GetFederationTokenOutput { + s.PackedPolicySize = &v + return s +} + +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionTokenRequest +type GetSessionTokenInput struct { + _ struct{} `type:"structure"` + + // The duration, in seconds, that the credentials should remain valid. Acceptable + // durations for IAM user sessions range from 900 seconds (15 minutes) to 129600 + // seconds (36 hours), with 43200 seconds (12 hours) as the default. Sessions + // for AWS account owners are restricted to a maximum of 3600 seconds (one hour). + // If the duration is longer than one hour, the session for AWS account owners + // defaults to one hour. + DurationSeconds *int64 `min:"900" type:"integer"` + + // The identification number of the MFA device that is associated with the IAM + // user who is making the GetSessionToken call. Specify this value if the IAM + // user has a policy 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). + // You can find the device for an IAM user by going to the AWS Management Console + // and viewing the user's security credentials. + // + // The regex used to validated this parameter is a string of characters consisting + // of upper- and lower-case alphanumeric characters with no spaces. You can + // also include underscores or any of the following characters: =,.@:/- + SerialNumber *string `min:"9" type:"string"` + + // The value provided by the MFA device, if MFA is required. If any policy requires + // the IAM user to submit an MFA code, specify this value. If MFA authentication + // is required, and the user does not provide a code when requesting a set of + // temporary security credentials, the user will receive an "access denied" + // response when requesting resources that require MFA authentication. + // + // The format for this parameter, as described by its regex pattern, is a sequence + // of six numeric digits. + TokenCode *string `min:"6" type:"string"` +} + +// String returns the string representation +func (s GetSessionTokenInput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetSessionTokenInput) GoString() string { + return s.String() +} + +// Validate inspects the fields of the type to determine if they are valid. +func (s *GetSessionTokenInput) Validate() error { + invalidParams := request.ErrInvalidParams{Context: "GetSessionTokenInput"} + if s.DurationSeconds != nil && *s.DurationSeconds < 900 { + invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900)) + } + if s.SerialNumber != nil && len(*s.SerialNumber) < 9 { + invalidParams.Add(request.NewErrParamMinLen("SerialNumber", 9)) + } + if s.TokenCode != nil && len(*s.TokenCode) < 6 { + invalidParams.Add(request.NewErrParamMinLen("TokenCode", 6)) + } + + if invalidParams.Len() > 0 { + return invalidParams + } + return nil +} + +// SetDurationSeconds sets the DurationSeconds field's value. +func (s *GetSessionTokenInput) SetDurationSeconds(v int64) *GetSessionTokenInput { + s.DurationSeconds = &v + return s +} + +// SetSerialNumber sets the SerialNumber field's value. +func (s *GetSessionTokenInput) SetSerialNumber(v string) *GetSessionTokenInput { + s.SerialNumber = &v + return s +} + +// SetTokenCode sets the TokenCode field's value. +func (s *GetSessionTokenInput) SetTokenCode(v string) *GetSessionTokenInput { + s.TokenCode = &v + return s +} + +// Contains the response to a successful GetSessionToken request, including +// temporary AWS credentials that can be used to make AWS requests. +// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionTokenResponse +type GetSessionTokenOutput struct { + _ struct{} `type:"structure"` + + // The temporary security credentials, which include an access key ID, a secret + // access key, and a security (or session) token. + // + // Note: The size of the security token that STS APIs return is not fixed. We + // strongly recommend that you make no assumptions about the maximum size. As + // of this writing, the typical size is less than 4096 bytes, but that can vary. + // Also, future updates to AWS might require larger sizes. + Credentials *Credentials `type:"structure"` +} + +// String returns the string representation +func (s GetSessionTokenOutput) String() string { + return awsutil.Prettify(s) +} + +// GoString returns the string representation +func (s GetSessionTokenOutput) GoString() string { + return s.String() +} + +// SetCredentials sets the Credentials field's value. +func (s *GetSessionTokenOutput) SetCredentials(v *Credentials) *GetSessionTokenOutput { + s.Credentials = v + return s +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go b/vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go new file mode 100644 index 0000000..4010cc7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go @@ -0,0 +1,12 @@ +package sts + +import "github.com/aws/aws-sdk-go/aws/request" + +func init() { + initRequest = func(r *request.Request) { + switch r.Operation.Name { + case opAssumeRoleWithSAML, opAssumeRoleWithWebIdentity: + r.Handlers.Sign.Clear() // these operations are unsigned + } + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/customizations_test.go b/vendor/github.com/aws/aws-sdk-go/service/sts/customizations_test.go new file mode 100644 index 0000000..18972b1 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/customizations_test.go @@ -0,0 +1,45 @@ +package sts_test + +import ( + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/awstesting/unit" + "github.com/aws/aws-sdk-go/service/sts" +) + +var svc = sts.New(unit.Session, &aws.Config{ + Region: aws.String("mock-region"), +}) + +func TestUnsignedRequest_AssumeRoleWithSAML(t *testing.T) { + req, _ := svc.AssumeRoleWithSAMLRequest(&sts.AssumeRoleWithSAMLInput{ + PrincipalArn: aws.String("ARN01234567890123456789"), + RoleArn: aws.String("ARN01234567890123456789"), + SAMLAssertion: aws.String("ASSERT"), + }) + + err := req.Sign() + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if e, a := "", req.HTTPRequest.Header.Get("Authorization"); e != a { + t.Errorf("expect %v, got %v", e, a) + } +} + +func TestUnsignedRequest_AssumeRoleWithWebIdentity(t *testing.T) { + req, _ := svc.AssumeRoleWithWebIdentityRequest(&sts.AssumeRoleWithWebIdentityInput{ + RoleArn: aws.String("ARN01234567890123456789"), + RoleSessionName: aws.String("SESSION"), + WebIdentityToken: aws.String("TOKEN"), + }) + + err := req.Sign() + if err != nil { + t.Errorf("expect no error, got %v", err) + } + if e, a := "", req.HTTPRequest.Header.Get("Authorization"); e != a { + t.Errorf("expect %v, got %v", e, a) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/doc.go b/vendor/github.com/aws/aws-sdk-go/service/sts/doc.go new file mode 100644 index 0000000..ef681ab --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/doc.go @@ -0,0 +1,72 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +// Package sts provides the client and types for making API +// requests to AWS Security Token Service. +// +// The AWS Security Token Service (STS) is a web service that enables you to +// request temporary, limited-privilege credentials for AWS Identity and Access +// Management (IAM) users or for users that you authenticate (federated users). +// This guide provides descriptions of the STS API. For more detailed information +// about using this service, go to Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html). +// +// As an alternative to using the API, you can use one of the AWS SDKs, which +// consist of libraries and sample code for various programming languages and +// platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs provide a convenient +// way to create programmatic access to STS. For example, the SDKs take care +// of cryptographically signing requests, managing errors, and retrying requests +// automatically. For information about the AWS SDKs, including how to download +// and install them, see the Tools for Amazon Web Services page (http://aws.amazon.com/tools/). +// +// For information about setting up signatures and authorization through the +// API, go to Signing AWS API Requests (http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html) +// in the AWS General Reference. For general information about the Query API, +// go to Making Query Requests (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html) +// in Using IAM. For information about using security tokens with other AWS +// products, go to AWS Services That Work with IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) +// in the IAM User Guide. +// +// If you're new to AWS and need additional technical information about a specific +// AWS product, you can find the product's technical documentation at http://aws.amazon.com/documentation/ +// (http://aws.amazon.com/documentation/). +// +// Endpoints +// +// The AWS Security Token Service (STS) has a default endpoint of https://sts.amazonaws.com +// that maps to the US East (N. Virginia) region. Additional regions are available +// and are activated by default. For more information, see Activating and Deactivating +// AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +// in the IAM User Guide. +// +// For information about STS endpoints, see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region) +// in the AWS General Reference. +// +// Recording API requests +// +// STS supports AWS CloudTrail, which is a service that records AWS calls for +// your AWS account and delivers log files to an Amazon S3 bucket. By using +// information collected by CloudTrail, you can determine what requests were +// successfully made to STS, who made the request, when it was made, and so +// on. To learn more about CloudTrail, including how to turn it on and find +// your log files, see the AWS CloudTrail User Guide (http://docs.aws.amazon.com/awscloudtrail/latest/userguide/what_is_cloud_trail_top_level.html). +// +// See https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15 for more information on this service. +// +// See sts package documentation for more information. +// https://docs.aws.amazon.com/sdk-for-go/api/service/sts/ +// +// Using the Client +// +// To contact AWS Security Token Service with the SDK use the New function to create +// a new service client. With that client you can make API requests to the service. +// These clients are safe to use concurrently. +// +// See the SDK's documentation for more information on how to use the SDK. +// https://docs.aws.amazon.com/sdk-for-go/api/ +// +// See aws.Config documentation for more information on configuring SDK clients. +// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config +// +// See the AWS Security Token Service client STS for more +// information on creating client for this service. +// https://docs.aws.amazon.com/sdk-for-go/api/service/sts/#New +package sts diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/errors.go b/vendor/github.com/aws/aws-sdk-go/service/sts/errors.go new file mode 100644 index 0000000..e24884e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/errors.go @@ -0,0 +1,73 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package sts + +const ( + + // ErrCodeExpiredTokenException for service response error code + // "ExpiredTokenException". + // + // The web identity token that was passed is expired or is not valid. Get a + // new identity token from the identity provider and then retry the request. + ErrCodeExpiredTokenException = "ExpiredTokenException" + + // ErrCodeIDPCommunicationErrorException for service response error code + // "IDPCommunicationError". + // + // The request could not be fulfilled because the non-AWS identity provider + // (IDP) that was asked to verify the incoming identity token could not be reached. + // This is often a transient error caused by network conditions. Retry the request + // a limited number of times so that you don't exceed the request rate. If the + // error persists, the non-AWS identity provider might be down or not responding. + ErrCodeIDPCommunicationErrorException = "IDPCommunicationError" + + // ErrCodeIDPRejectedClaimException for service response error code + // "IDPRejectedClaim". + // + // The identity provider (IdP) reported that authentication failed. This might + // be because the claim is invalid. + // + // If this error is returned for the AssumeRoleWithWebIdentity operation, it + // can also mean that the claim has expired or has been explicitly revoked. + ErrCodeIDPRejectedClaimException = "IDPRejectedClaim" + + // ErrCodeInvalidAuthorizationMessageException for service response error code + // "InvalidAuthorizationMessageException". + // + // The error returned if the message passed to DecodeAuthorizationMessage was + // invalid. This can happen if the token contains invalid characters, such as + // linebreaks. + ErrCodeInvalidAuthorizationMessageException = "InvalidAuthorizationMessageException" + + // ErrCodeInvalidIdentityTokenException for service response error code + // "InvalidIdentityToken". + // + // The web identity token that was passed could not be validated by AWS. Get + // a new identity token from the identity provider and then retry the request. + ErrCodeInvalidIdentityTokenException = "InvalidIdentityToken" + + // ErrCodeMalformedPolicyDocumentException for service response error code + // "MalformedPolicyDocument". + // + // The request was rejected because the policy document was malformed. The error + // message describes the specific error. + ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocument" + + // ErrCodePackedPolicyTooLargeException for service response error code + // "PackedPolicyTooLarge". + // + // The request was rejected because the policy document was too large. The error + // message describes how big the policy document is, in packed form, as a percentage + // of what the API allows. + ErrCodePackedPolicyTooLargeException = "PackedPolicyTooLarge" + + // ErrCodeRegionDisabledException for service response error code + // "RegionDisabledException". + // + // STS is not activated in the requested region for the account that is being + // asked to generate credentials. The account administrator must use the IAM + // console to activate STS in that region. For more information, see Activating + // and Deactivating AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) + // in the IAM User Guide. + ErrCodeRegionDisabledException = "RegionDisabledException" +) diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/examples_test.go b/vendor/github.com/aws/aws-sdk-go/service/sts/examples_test.go new file mode 100644 index 0000000..d61a993 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/examples_test.go @@ -0,0 +1,282 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package sts_test + +import ( + "fmt" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/sts" +) + +var _ time.Duration +var _ strings.Reader +var _ aws.Config + +func parseTime(layout, value string) *time.Time { + t, err := time.Parse(layout, value) + if err != nil { + panic(err) + } + return &t +} + +// To assume a role +// + +func ExampleSTS_AssumeRole_shared00() { + svc := sts.New(session.New()) + input := &sts.AssumeRoleInput{ + DurationSeconds: aws.Int64(3600), + ExternalId: aws.String("123ABC"), + Policy: aws.String("{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Stmt1\",\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"*\"}]}"), + RoleArn: aws.String("arn:aws:iam::123456789012:role/demo"), + RoleSessionName: aws.String("Bob"), + } + + result, err := svc.AssumeRole(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case sts.ErrCodeMalformedPolicyDocumentException: + fmt.Println(sts.ErrCodeMalformedPolicyDocumentException, aerr.Error()) + case sts.ErrCodePackedPolicyTooLargeException: + fmt.Println(sts.ErrCodePackedPolicyTooLargeException, aerr.Error()) + case sts.ErrCodeRegionDisabledException: + fmt.Println(sts.ErrCodeRegionDisabledException, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To assume a role as an OpenID Connect-federated user +// + +func ExampleSTS_AssumeRoleWithWebIdentity_shared00() { + svc := sts.New(session.New()) + input := &sts.AssumeRoleWithWebIdentityInput{ + DurationSeconds: aws.Int64(3600), + ProviderId: aws.String("www.amazon.com"), + RoleArn: aws.String("arn:aws:iam::123456789012:role/FederatedWebIdentityRole"), + RoleSessionName: aws.String("app1"), + WebIdentityToken: aws.String("Atza%7CIQEBLjAsAhRFiXuWpUXuRvQ9PZL3GMFcYevydwIUFAHZwXZXXXXXXXXJnrulxKDHwy87oGKPznh0D6bEQZTSCzyoCtL_8S07pLpr0zMbn6w1lfVZKNTBdDansFBmtGnIsIapjI6xKR02Yc_2bQ8LZbUXSGm6Ry6_BG7PrtLZtj_dfCTj92xNGed-CrKqjG7nPBjNIL016GGvuS5gSvPRUxWES3VYfm1wl7WTI7jn-Pcb6M-buCgHhFOzTQxod27L9CqnOLio7N3gZAGpsp6n1-AJBOCJckcyXe2c6uD0srOJeZlKUm2eTDVMf8IehDVI0r1QOnTV6KzzAI3OY87Vd_cVMQ"), + } + + result, err := svc.AssumeRoleWithWebIdentity(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case sts.ErrCodeMalformedPolicyDocumentException: + fmt.Println(sts.ErrCodeMalformedPolicyDocumentException, aerr.Error()) + case sts.ErrCodePackedPolicyTooLargeException: + fmt.Println(sts.ErrCodePackedPolicyTooLargeException, aerr.Error()) + case sts.ErrCodeIDPRejectedClaimException: + fmt.Println(sts.ErrCodeIDPRejectedClaimException, aerr.Error()) + case sts.ErrCodeIDPCommunicationErrorException: + fmt.Println(sts.ErrCodeIDPCommunicationErrorException, aerr.Error()) + case sts.ErrCodeInvalidIdentityTokenException: + fmt.Println(sts.ErrCodeInvalidIdentityTokenException, aerr.Error()) + case sts.ErrCodeExpiredTokenException: + fmt.Println(sts.ErrCodeExpiredTokenException, aerr.Error()) + case sts.ErrCodeRegionDisabledException: + fmt.Println(sts.ErrCodeRegionDisabledException, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To decode information about an authorization status of a request +// + +func ExampleSTS_DecodeAuthorizationMessage_shared00() { + svc := sts.New(session.New()) + input := &sts.DecodeAuthorizationMessageInput{ + EncodedMessage: aws.String(""), + } + + result, err := svc.DecodeAuthorizationMessage(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case sts.ErrCodeInvalidAuthorizationMessageException: + fmt.Println(sts.ErrCodeInvalidAuthorizationMessageException, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To get details about a calling IAM user +// +// This example shows a request and response made with the credentials for a user named +// Alice in the AWS account 123456789012. +func ExampleSTS_GetCallerIdentity_shared00() { + svc := sts.New(session.New()) + input := &sts.GetCallerIdentityInput{} + + result, err := svc.GetCallerIdentity(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To get details about a calling user federated with AssumeRole +// +// This example shows a request and response made with temporary credentials created +// by AssumeRole. The name of the assumed role is my-role-name, and the RoleSessionName +// is set to my-role-session-name. +func ExampleSTS_GetCallerIdentity_shared01() { + svc := sts.New(session.New()) + input := &sts.GetCallerIdentityInput{} + + result, err := svc.GetCallerIdentity(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To get details about a calling user federated with GetFederationToken +// +// This example shows a request and response made with temporary credentials created +// by using GetFederationToken. The Name parameter is set to my-federated-user-name. +func ExampleSTS_GetCallerIdentity_shared02() { + svc := sts.New(session.New()) + input := &sts.GetCallerIdentityInput{} + + result, err := svc.GetCallerIdentity(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To get temporary credentials for a role by using GetFederationToken +// + +func ExampleSTS_GetFederationToken_shared00() { + svc := sts.New(session.New()) + input := &sts.GetFederationTokenInput{ + DurationSeconds: aws.Int64(3600), + Name: aws.String("Bob"), + Policy: aws.String("{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Stmt1\",\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"*\"}]}"), + } + + result, err := svc.GetFederationToken(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case sts.ErrCodeMalformedPolicyDocumentException: + fmt.Println(sts.ErrCodeMalformedPolicyDocumentException, aerr.Error()) + case sts.ErrCodePackedPolicyTooLargeException: + fmt.Println(sts.ErrCodePackedPolicyTooLargeException, aerr.Error()) + case sts.ErrCodeRegionDisabledException: + fmt.Println(sts.ErrCodeRegionDisabledException, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} + +// To get temporary credentials for an IAM user or an AWS account +// + +func ExampleSTS_GetSessionToken_shared00() { + svc := sts.New(session.New()) + input := &sts.GetSessionTokenInput{ + DurationSeconds: aws.Int64(3600), + SerialNumber: aws.String("YourMFASerialNumber"), + TokenCode: aws.String("123456"), + } + + result, err := svc.GetSessionToken(input) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case sts.ErrCodeRegionDisabledException: + fmt.Println(sts.ErrCodeRegionDisabledException, aerr.Error()) + default: + fmt.Println(aerr.Error()) + } + } else { + // Print the error, cast err to awserr.Error to get the Code and + // Message from an error. + fmt.Println(err.Error()) + } + return + } + + fmt.Println(result) +} diff --git a/vendor/github.com/aws/aws-sdk-go/service/sts/service.go b/vendor/github.com/aws/aws-sdk-go/service/sts/service.go new file mode 100644 index 0000000..1ee5839 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/service/sts/service.go @@ -0,0 +1,93 @@ +// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. + +package sts + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/client" + "github.com/aws/aws-sdk-go/aws/client/metadata" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/signer/v4" + "github.com/aws/aws-sdk-go/private/protocol/query" +) + +// STS provides the API operation methods for making requests to +// AWS Security Token Service. See this package's package overview docs +// for details on the service. +// +// STS methods are safe to use concurrently. It is not safe to +// modify mutate any of the struct's properties though. +type STS struct { + *client.Client +} + +// Used for custom client initialization logic +var initClient func(*client.Client) + +// Used for custom request initialization logic +var initRequest func(*request.Request) + +// Service information constants +const ( + ServiceName = "sts" // Service endpoint prefix API calls made to. + EndpointsID = ServiceName // Service ID for Regions and Endpoints metadata. +) + +// New creates a new instance of the STS client with a session. +// If additional configuration is needed for the client instance use the optional +// aws.Config parameter to add your extra config. +// +// Example: +// // Create a STS client from just a session. +// svc := sts.New(mySession) +// +// // Create a STS client with additional configuration +// svc := sts.New(mySession, aws.NewConfig().WithRegion("us-west-2")) +func New(p client.ConfigProvider, cfgs ...*aws.Config) *STS { + c := p.ClientConfig(EndpointsID, cfgs...) + return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +// newClient creates, initializes and returns a new service client instance. +func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *STS { + svc := &STS{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: ServiceName, + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2011-06-15", + }, + handlers, + ), + } + + // Handlers + svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(query.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler) + + // Run custom client initialization if present + if initClient != nil { + initClient(svc.Client) + } + + return svc +} + +// newRequest creates a new request for a STS operation and runs any +// custom request initialization. +func (c *STS) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + // Run custom request initialization if present + if initRequest != nil { + initRequest(req) + } + + return req +} diff --git a/vendor/github.com/beevik/etree/.travis.yml b/vendor/github.com/beevik/etree/.travis.yml new file mode 100644 index 0000000..7caa247 --- /dev/null +++ b/vendor/github.com/beevik/etree/.travis.yml @@ -0,0 +1,16 @@ +language: go +sudo: false + +go: + - 1.4.2 + - 1.5.1 + - 1.6 + - tip + +matrix: + allow_failures: + - go: tip + +script: + - go vet ./... + - go test -v ./... diff --git a/vendor/github.com/beevik/etree/CONTRIBUTORS b/vendor/github.com/beevik/etree/CONTRIBUTORS new file mode 100644 index 0000000..084662c --- /dev/null +++ b/vendor/github.com/beevik/etree/CONTRIBUTORS @@ -0,0 +1,8 @@ +Brett Vickers (beevik) +Felix Geisendörfer (felixge) +Kamil Kisiel (kisielk) +Graham King (grahamking) +Matt Smith (ma314smith) +Michal Jemala (michaljemala) +Nicolas Piganeau (npiganeau) +Chris Brown (ccbrown) diff --git a/vendor/github.com/beevik/etree/LICENSE b/vendor/github.com/beevik/etree/LICENSE new file mode 100644 index 0000000..e14ad68 --- /dev/null +++ b/vendor/github.com/beevik/etree/LICENSE @@ -0,0 +1,24 @@ +Copyright 2015 Brett Vickers. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/beevik/etree/README.md b/vendor/github.com/beevik/etree/README.md new file mode 100644 index 0000000..2855843 --- /dev/null +++ b/vendor/github.com/beevik/etree/README.md @@ -0,0 +1,203 @@ +[![Build Status](https://travis-ci.org/beevik/etree.svg?branch=master)](https://travis-ci.org/beevik/etree) +[![GoDoc](https://godoc.org/github.com/beevik/etree?status.svg)](https://godoc.org/github.com/beevik/etree) + +etree +===== + +The etree package is a lightweight, pure go package that expresses XML in +the form of an element tree. Its design was inspired by the Python +[ElementTree](http://docs.python.org/2/library/xml.etree.elementtree.html) +module. Some of the package's features include: + +* Represents XML documents as trees of elements for easy traversal. +* Imports, serializes, modifies or creates XML documents from scratch. +* Writes and reads XML to/from files, byte slices, strings and io interfaces. +* Performs simple or complex searches with lightweight XPath-like query APIs. +* Auto-indents XML using spaces or tabs for better readability. +* Implemented in pure go; depends only on standard go libraries. +* Built on top of the go [encoding/xml](http://golang.org/pkg/encoding/xml) + package. + +### Creating an XML document + +The following example creates an XML document from scratch using the etree +package and outputs its indented contents to stdout. +```go +doc := etree.NewDocument() +doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`) +doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`) + +people := doc.CreateElement("People") +people.CreateComment("These are all known people") + +jon := people.CreateElement("Person") +jon.CreateAttr("name", "Jon") + +sally := people.CreateElement("Person") +sally.CreateAttr("name", "Sally") + +doc.Indent(2) +doc.WriteTo(os.Stdout) +``` + +Output: +```xml + + + + + + + +``` + +### Reading an XML file + +Suppose you have a file on disk called `bookstore.xml` containing the +following data: + +```xml + + + + Everyday Italian + Giada De Laurentiis + 2005 + 30.00 + + + + Harry Potter + J K. Rowling + 2005 + 29.99 + + + + XQuery Kick Start + James McGovern + Per Bothner + Kurt Cagle + James Linn + Vaidyanathan Nagarajan + 2003 + 49.99 + + + + Learning XML + Erik T. Ray + 2003 + 39.95 + + + +``` + +This code reads the file's contents into an etree document. +```go +doc := etree.NewDocument() +if err := doc.ReadFromFile("bookstore.xml"); err != nil { + panic(err) +} +``` + +You can also read XML from a string, a byte slice, or an `io.Reader`. + +### Processing elements and attributes + +This example illustrates several ways to access elements and attributes using +etree selection queries. +```go +root := doc.SelectElement("bookstore") +fmt.Println("ROOT element:", root.Tag) + +for _, book := range root.SelectElements("book") { + fmt.Println("CHILD element:", book.Tag) + if title := book.SelectElement("title"); title != nil { + lang := title.SelectAttrValue("lang", "unknown") + fmt.Printf(" TITLE: %s (%s)\n", title.Text(), lang) + } + for _, attr := range book.Attr { + fmt.Printf(" ATTR: %s=%s\n", attr.Key, attr.Value) + } +} +``` +Output: +``` +ROOT element: bookstore +CHILD element: book + TITLE: Everyday Italian (en) + ATTR: category=COOKING +CHILD element: book + TITLE: Harry Potter (en) + ATTR: category=CHILDREN +CHILD element: book + TITLE: XQuery Kick Start (en) + ATTR: category=WEB +CHILD element: book + TITLE: Learning XML (en) + ATTR: category=WEB +``` + +### Path queries + +This example uses etree's path functions to select all book titles that fall +into the category of 'WEB'. The double-slash prefix in the path causes the +search for book elements to occur recursively; book elements may appear at any +level of the XML hierarchy. +```go +for _, t := range doc.FindElements("//book[@category='WEB']/title") { + fmt.Println("Title:", t.Text()) +} +``` + +Output: +``` +Title: XQuery Kick Start +Title: Learning XML +``` + +This example finds the first book element under the root bookstore element and +outputs the tag and text of each of its child elements. +```go +for _, e := range doc.FindElements("./bookstore/book[1]/*") { + fmt.Printf("%s: %s\n", e.Tag, e.Text()) +} +``` + +Output: +``` +title: Everyday Italian +author: Giada De Laurentiis +year: 2005 +price: 30.00 +``` + +This example finds all books with a price of 49.99 and outputs their titles. +```go +path := etree.MustCompilePath("./bookstore/book[p:price='49.99']/title") +for _, e := range doc.FindElementsPath(path) { + fmt.Println(e.Text()) +} +``` + +Output: +``` +XQuery Kick Start +``` + +Note that this example uses the FindElementsPath function, which takes as an +argument a pre-compiled path object. Use precompiled paths when you plan to +search with the same path more than once. + +### Other features + +These are just a few examples of the things the etree package can do. See the +[documentation](http://godoc.org/github.com/beevik/etree) for a complete +description of its capabilities. + +### Contributing + +This project accepts contributions. Just fork the repo and submit a pull +request! diff --git a/vendor/github.com/beevik/etree/etree.go b/vendor/github.com/beevik/etree/etree.go new file mode 100644 index 0000000..36b279f --- /dev/null +++ b/vendor/github.com/beevik/etree/etree.go @@ -0,0 +1,943 @@ +// Copyright 2015 Brett Vickers. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package etree provides XML services through an Element Tree +// abstraction. +package etree + +import ( + "bufio" + "bytes" + "encoding/xml" + "errors" + "io" + "os" + "strings" +) + +const ( + // NoIndent is used with Indent to disable all indenting. + NoIndent = -1 +) + +// ErrXML is returned when XML parsing fails due to incorrect formatting. +var ErrXML = errors.New("etree: invalid XML format") + +// ReadSettings allow for changing the default behavior of the ReadFrom* +// methods. +type ReadSettings struct { + // CharsetReader to be passed to standard xml.Decoder. Default: nil. + CharsetReader func(charset string, input io.Reader) (io.Reader, error) + + // Permissive allows input containing common mistakes such as missing tags + // or attribute values. Default: false. + Permissive bool +} + +// newReadSettings creates a default ReadSettings record. +func newReadSettings() ReadSettings { + return ReadSettings{} +} + +// WriteSettings allow for changing the serialization behavior of the WriteTo* +// methods. +type WriteSettings struct { + // CanonicalEndTags forces the production of XML end tags, even for + // elements that have no child elements. Default: false. + CanonicalEndTags bool + + // CanonicalText forces the production of XML character references for + // text data characters &, <, and >. If false, XML character references + // are also produced for " and '. Default: false. + CanonicalText bool + + // CanonicalAttrVal forces the production of XML character references for + // attribute value characters &, < and ". If false, XML character + // references are also produced for > and '. Default: false. + CanonicalAttrVal bool +} + +// newWriteSettings creates a default WriteSettings record. +func newWriteSettings() WriteSettings { + return WriteSettings{ + CanonicalEndTags: false, + CanonicalText: false, + CanonicalAttrVal: false, + } +} + +// A Token is an empty interface that represents an Element, CharData, +// Comment, Directive, or ProcInst. +type Token interface { + Parent() *Element + dup(parent *Element) Token + setParent(parent *Element) + writeTo(w *bufio.Writer, s *WriteSettings) +} + +// A Document is a container holding a complete XML hierarchy. Its embedded +// element contains zero or more children, one of which is usually the root +// element. The embedded element may include other children such as +// processing instructions or BOM CharData tokens. +type Document struct { + Element + ReadSettings ReadSettings + WriteSettings WriteSettings +} + +// An Element represents an XML element, its attributes, and its child tokens. +type Element struct { + Space, Tag string // namespace and tag + Attr []Attr // key-value attribute pairs + Child []Token // child tokens (elements, comments, etc.) + parent *Element // parent element +} + +// An Attr represents a key-value attribute of an XML element. +type Attr struct { + Space, Key string // The attribute's namespace and key + Value string // The attribute value string +} + +// CharData represents character data within XML. +type CharData struct { + Data string + parent *Element + whitespace bool +} + +// A Comment represents an XML comment. +type Comment struct { + Data string + parent *Element +} + +// A Directive represents an XML directive. +type Directive struct { + Data string + parent *Element +} + +// A ProcInst represents an XML processing instruction. +type ProcInst struct { + Target string + Inst string + parent *Element +} + +// NewDocument creates an XML document without a root element. +func NewDocument() *Document { + return &Document{ + Element{Child: make([]Token, 0)}, + newReadSettings(), + newWriteSettings(), + } +} + +// Copy returns a recursive, deep copy of the document. +func (d *Document) Copy() *Document { + return &Document{*(d.dup(nil).(*Element)), d.ReadSettings, d.WriteSettings} +} + +// Root returns the root element of the document, or nil if there is no root +// element. +func (d *Document) Root() *Element { + for _, t := range d.Child { + if c, ok := t.(*Element); ok { + return c + } + } + return nil +} + +// SetRoot replaces the document's root element with e. If the document +// already has a root when this function is called, then the document's +// original root is unbound first. If the element e is bound to another +// document (or to another element within a document), then it is unbound +// first. +func (d *Document) SetRoot(e *Element) { + if e.parent != nil { + e.parent.RemoveChild(e) + } + e.setParent(&d.Element) + + for i, t := range d.Child { + if _, ok := t.(*Element); ok { + t.setParent(nil) + d.Child[i] = e + return + } + } + d.Child = append(d.Child, e) +} + +// ReadFrom reads XML from the reader r into the document d. It returns the +// number of bytes read and any error encountered. +func (d *Document) ReadFrom(r io.Reader) (n int64, err error) { + return d.Element.readFrom(r, d.ReadSettings) +} + +// ReadFromFile reads XML from the string s into the document d. +func (d *Document) ReadFromFile(filename string) error { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + _, err = d.ReadFrom(f) + return err +} + +// ReadFromBytes reads XML from the byte slice b into the document d. +func (d *Document) ReadFromBytes(b []byte) error { + _, err := d.ReadFrom(bytes.NewReader(b)) + return err +} + +// ReadFromString reads XML from the string s into the document d. +func (d *Document) ReadFromString(s string) error { + _, err := d.ReadFrom(strings.NewReader(s)) + return err +} + +// WriteTo serializes an XML document into the writer w. It +// returns the number of bytes written and any error encountered. +func (d *Document) WriteTo(w io.Writer) (n int64, err error) { + cw := newCountWriter(w) + b := bufio.NewWriter(cw) + for _, c := range d.Child { + c.writeTo(b, &d.WriteSettings) + } + err, n = b.Flush(), cw.bytes + return +} + +// WriteToFile serializes an XML document into the file named +// filename. +func (d *Document) WriteToFile(filename string) error { + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + _, err = d.WriteTo(f) + return err +} + +// WriteToBytes serializes the XML document into a slice of +// bytes. +func (d *Document) WriteToBytes() (b []byte, err error) { + var buf bytes.Buffer + if _, err = d.WriteTo(&buf); err != nil { + return + } + return buf.Bytes(), nil +} + +// WriteToString serializes the XML document into a string. +func (d *Document) WriteToString() (s string, err error) { + var b []byte + if b, err = d.WriteToBytes(); err != nil { + return + } + return string(b), nil +} + +type indentFunc func(depth int) string + +// Indent modifies the document's element tree by inserting CharData entities +// containing carriage returns and indentation. The amount of indentation per +// depth level is given as spaces. Pass etree.NoIndent for spaces if you want +// no indentation at all. +func (d *Document) Indent(spaces int) { + var indent indentFunc + switch { + case spaces < 0: + indent = func(depth int) string { return "" } + default: + indent = func(depth int) string { return crIndent(depth*spaces, crsp) } + } + d.Element.indent(0, indent) +} + +// IndentTabs modifies the document's element tree by inserting CharData +// entities containing carriage returns and tabs for indentation. One tab is +// used per indentation level. +func (d *Document) IndentTabs() { + indent := func(depth int) string { return crIndent(depth, crtab) } + d.Element.indent(0, indent) +} + +// NewElement creates an unparented element with the specified tag. The tag +// may be prefixed by a namespace and a colon. +func NewElement(tag string) *Element { + space, stag := spaceDecompose(tag) + return newElement(space, stag, nil) +} + +// newElement is a helper function that creates an element and binds it to +// a parent element if possible. +func newElement(space, tag string, parent *Element) *Element { + e := &Element{ + Space: space, + Tag: tag, + Attr: make([]Attr, 0), + Child: make([]Token, 0), + parent: parent, + } + if parent != nil { + parent.addChild(e) + } + return e +} + +// Copy creates a recursive, deep copy of the element and all its attributes +// and children. The returned element has no parent but can be parented to a +// another element using AddElement, or to a document using SetRoot. +func (e *Element) Copy() *Element { + var parent *Element + return e.dup(parent).(*Element) +} + +// Text returns the characters immediately following the element's +// opening tag. +func (e *Element) Text() string { + if len(e.Child) == 0 { + return "" + } + if cd, ok := e.Child[0].(*CharData); ok { + return cd.Data + } + return "" +} + +// SetText replaces an element's subsidiary CharData text with a new string. +func (e *Element) SetText(text string) { + if len(e.Child) > 0 { + if cd, ok := e.Child[0].(*CharData); ok { + cd.Data = text + return + } + } + cd := newCharData(text, false, e) + copy(e.Child[1:], e.Child[0:]) + e.Child[0] = cd +} + +// CreateElement creates an element with the specified tag and adds it as the +// last child element of the element e. The tag may be prefixed by a namespace +// and a colon. +func (e *Element) CreateElement(tag string) *Element { + space, stag := spaceDecompose(tag) + return newElement(space, stag, e) +} + +// AddChild adds the token t as the last child of element e. If token t was +// already the child of another element, it is first removed from its current +// parent element. +func (e *Element) AddChild(t Token) { + if t.Parent() != nil { + t.Parent().RemoveChild(t) + } + t.setParent(e) + e.addChild(t) +} + +// InsertChild inserts the token t before e's existing child token ex. If ex +// is nil (or if ex is not a child of e), then t is added to the end of e's +// child token list. If token t was already the child of another element, it +// is first removed from its current parent element. +func (e *Element) InsertChild(ex Token, t Token) { + if t.Parent() != nil { + t.Parent().RemoveChild(t) + } + t.setParent(e) + + for i, c := range e.Child { + if c == ex { + e.Child = append(e.Child, nil) + copy(e.Child[i+1:], e.Child[i:]) + e.Child[i] = t + return + } + } + e.addChild(t) +} + +// RemoveChild attempts to remove the token t from element e's list of +// children. If the token t is a child of e, then it is returned. Otherwise, +// nil is returned. +func (e *Element) RemoveChild(t Token) Token { + for i, c := range e.Child { + if c == t { + e.Child = append(e.Child[:i], e.Child[i+1:]...) + c.setParent(nil) + return t + } + } + return nil +} + +// ReadFrom reads XML from the reader r and stores the result as a new child +// of element e. +func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err error) { + r := newCountReader(ri) + dec := xml.NewDecoder(r) + dec.CharsetReader = settings.CharsetReader + dec.Strict = !settings.Permissive + var stack stack + stack.push(e) + for { + t, err := dec.RawToken() + switch { + case err == io.EOF: + return r.bytes, nil + case err != nil: + return r.bytes, err + case stack.empty(): + return r.bytes, ErrXML + } + + top := stack.peek().(*Element) + + switch t := t.(type) { + case xml.StartElement: + e := newElement(t.Name.Space, t.Name.Local, top) + for _, a := range t.Attr { + e.createAttr(a.Name.Space, a.Name.Local, a.Value) + } + stack.push(e) + case xml.EndElement: + stack.pop() + case xml.CharData: + data := string(t) + newCharData(data, isWhitespace(data), top) + case xml.Comment: + newComment(string(t), top) + case xml.Directive: + newDirective(string(t), top) + case xml.ProcInst: + newProcInst(t.Target, string(t.Inst), top) + } + } +} + +// SelectAttr finds an element attribute matching the requested key and +// returns it if found. The key may be prefixed by a namespace and a colon. +func (e *Element) SelectAttr(key string) *Attr { + space, skey := spaceDecompose(key) + for i, a := range e.Attr { + if spaceMatch(space, a.Space) && skey == a.Key { + return &e.Attr[i] + } + } + return nil +} + +// SelectAttrValue finds an element attribute matching the requested key and +// returns its value if found. The key may be prefixed by a namespace and a +// colon. If the key is not found, the dflt value is returned instead. +func (e *Element) SelectAttrValue(key, dflt string) string { + space, skey := spaceDecompose(key) + for _, a := range e.Attr { + if spaceMatch(space, a.Space) && skey == a.Key { + return a.Value + } + } + return dflt +} + +// ChildElements returns all elements that are children of element e. +func (e *Element) ChildElements() []*Element { + var elements []*Element + for _, t := range e.Child { + if c, ok := t.(*Element); ok { + elements = append(elements, c) + } + } + return elements +} + +// SelectElement returns the first child element with the given tag. The tag +// may be prefixed by a namespace and a colon. +func (e *Element) SelectElement(tag string) *Element { + space, stag := spaceDecompose(tag) + for _, t := range e.Child { + if c, ok := t.(*Element); ok && spaceMatch(space, c.Space) && stag == c.Tag { + return c + } + } + return nil +} + +// SelectElements returns a slice of all child elements with the given tag. +// The tag may be prefixed by a namespace and a colon. +func (e *Element) SelectElements(tag string) []*Element { + space, stag := spaceDecompose(tag) + var elements []*Element + for _, t := range e.Child { + if c, ok := t.(*Element); ok && spaceMatch(space, c.Space) && stag == c.Tag { + elements = append(elements, c) + } + } + return elements +} + +// FindElement returns the first element matched by the XPath-like path +// string. Panics if an invalid path string is supplied. +func (e *Element) FindElement(path string) *Element { + return e.FindElementPath(MustCompilePath(path)) +} + +// FindElementPath returns the first element matched by the XPath-like path +// string. +func (e *Element) FindElementPath(path Path) *Element { + p := newPather() + elements := p.traverse(e, path) + switch { + case len(elements) > 0: + return elements[0] + default: + return nil + } +} + +// FindElements returns a slice of elements matched by the XPath-like path +// string. Panics if an invalid path string is supplied. +func (e *Element) FindElements(path string) []*Element { + return e.FindElementsPath(MustCompilePath(path)) +} + +// FindElementsPath returns a slice of elements matched by the Path object. +func (e *Element) FindElementsPath(path Path) []*Element { + p := newPather() + return p.traverse(e, path) +} + +// indent recursively inserts proper indentation between an +// XML element's child tokens. +func (e *Element) indent(depth int, indent indentFunc) { + e.stripIndent() + n := len(e.Child) + if n == 0 { + return + } + + oldChild := e.Child + e.Child = make([]Token, 0, n*2+1) + isCharData, firstNonCharData := false, true + for _, c := range oldChild { + + // Insert CR+indent before child if it's not character data. + // Exceptions: when it's the first non-character-data child, or when + // the child is at root depth. + _, isCharData = c.(*CharData) + if !isCharData { + if !firstNonCharData || depth > 0 { + newCharData(indent(depth), true, e) + } + firstNonCharData = false + } + + e.addChild(c) + + // Recursively process child elements. + if ce, ok := c.(*Element); ok { + ce.indent(depth+1, indent) + } + } + + // Insert CR+indent before the last child. + if !isCharData { + if !firstNonCharData || depth > 0 { + newCharData(indent(depth-1), true, e) + } + } +} + +// stripIndent removes any previously inserted indentation. +func (e *Element) stripIndent() { + // Count the number of non-indent child tokens + n := len(e.Child) + for _, c := range e.Child { + if cd, ok := c.(*CharData); ok && cd.whitespace { + n-- + } + } + if n == len(e.Child) { + return + } + + // Strip out indent CharData + newChild := make([]Token, n) + j := 0 + for _, c := range e.Child { + if cd, ok := c.(*CharData); ok && cd.whitespace { + continue + } + newChild[j] = c + j++ + } + e.Child = newChild +} + +// dup duplicates the element. +func (e *Element) dup(parent *Element) Token { + ne := &Element{ + Space: e.Space, + Tag: e.Tag, + Attr: make([]Attr, len(e.Attr)), + Child: make([]Token, len(e.Child)), + parent: parent, + } + for i, t := range e.Child { + ne.Child[i] = t.dup(ne) + } + for i, a := range e.Attr { + ne.Attr[i] = a + } + return ne +} + +// Parent returns the element token's parent element, or nil if it has no +// parent. +func (e *Element) Parent() *Element { + return e.parent +} + +// setParent replaces the element token's parent. +func (e *Element) setParent(parent *Element) { + e.parent = parent +} + +// writeTo serializes the element to the writer w. +func (e *Element) writeTo(w *bufio.Writer, s *WriteSettings) { + w.WriteByte('<') + if e.Space != "" { + w.WriteString(e.Space) + w.WriteByte(':') + } + w.WriteString(e.Tag) + for _, a := range e.Attr { + w.WriteByte(' ') + a.writeTo(w, s) + } + if len(e.Child) > 0 { + w.WriteString(">") + for _, c := range e.Child { + c.writeTo(w, s) + } + w.Write([]byte{'<', '/'}) + if e.Space != "" { + w.WriteString(e.Space) + w.WriteByte(':') + } + w.WriteString(e.Tag) + w.WriteByte('>') + } else { + if s.CanonicalEndTags { + w.Write([]byte{'>', '<', '/'}) + if e.Space != "" { + w.WriteString(e.Space) + w.WriteByte(':') + } + w.WriteString(e.Tag) + w.WriteByte('>') + } else { + w.Write([]byte{'/', '>'}) + } + } +} + +// addChild adds a child token to the element e. +func (e *Element) addChild(t Token) { + e.Child = append(e.Child, t) +} + +// CreateAttr creates an attribute and adds it to element e. The key may be +// prefixed by a namespace and a colon. If an attribute with the key already +// exists, its value is replaced. +func (e *Element) CreateAttr(key, value string) *Attr { + space, skey := spaceDecompose(key) + return e.createAttr(space, skey, value) +} + +// createAttr is a helper function that creates attributes. +func (e *Element) createAttr(space, key, value string) *Attr { + for i, a := range e.Attr { + if space == a.Space && key == a.Key { + e.Attr[i].Value = value + return &e.Attr[i] + } + } + a := Attr{space, key, value} + e.Attr = append(e.Attr, a) + return &e.Attr[len(e.Attr)-1] +} + +// RemoveAttr removes and returns the first attribute of the element whose key +// matches the given key. The key may be prefixed by a namespace and a colon. +// If an equal attribute does not exist, nil is returned. +func (e *Element) RemoveAttr(key string) *Attr { + space, skey := spaceDecompose(key) + for i, a := range e.Attr { + if space == a.Space && skey == a.Key { + e.Attr = append(e.Attr[0:i], e.Attr[i+1:]...) + return &a + } + } + return nil +} + +var xmlReplacerNormal = strings.NewReplacer( + "&", "&", + "<", "<", + ">", ">", + "'", "'", + `"`, """, +) + +var xmlReplacerCanonicalText = strings.NewReplacer( + "&", "&", + "<", "<", + ">", ">", + "\r", " ", +) + +var xmlReplacerCanonicalAttrVal = strings.NewReplacer( + "&", "&", + "<", "<", + `"`, """, + "\t", " ", + "\n", " ", + "\r", " ", +) + +// writeTo serializes the attribute to the writer. +func (a *Attr) writeTo(w *bufio.Writer, s *WriteSettings) { + if a.Space != "" { + w.WriteString(a.Space) + w.WriteByte(':') + } + w.WriteString(a.Key) + w.WriteString(`="`) + var r *strings.Replacer + if s.CanonicalAttrVal { + r = xmlReplacerCanonicalAttrVal + } else { + r = xmlReplacerNormal + } + w.WriteString(r.Replace(a.Value)) + w.WriteByte('"') +} + +// NewCharData creates a parentless XML character data entity. +func NewCharData(data string) *CharData { + return newCharData(data, false, nil) +} + +// newCharData creates an XML character data entity and binds it to a parent +// element. If parent is nil, the CharData token remains unbound. +func newCharData(data string, whitespace bool, parent *Element) *CharData { + c := &CharData{ + Data: data, + whitespace: whitespace, + parent: parent, + } + if parent != nil { + parent.addChild(c) + } + return c +} + +// CreateCharData creates an XML character data entity and adds it as a child +// of element e. +func (e *Element) CreateCharData(data string) *CharData { + return newCharData(data, false, e) +} + +// dup duplicates the character data. +func (c *CharData) dup(parent *Element) Token { + return &CharData{ + Data: c.Data, + whitespace: c.whitespace, + parent: parent, + } +} + +// Parent returns the character data token's parent element, or nil if it has +// no parent. +func (c *CharData) Parent() *Element { + return c.parent +} + +// setParent replaces the character data token's parent. +func (c *CharData) setParent(parent *Element) { + c.parent = parent +} + +// writeTo serializes the character data entity to the writer. +func (c *CharData) writeTo(w *bufio.Writer, s *WriteSettings) { + var r *strings.Replacer + if s.CanonicalText { + r = xmlReplacerCanonicalText + } else { + r = xmlReplacerNormal + } + w.WriteString(r.Replace(c.Data)) +} + +// NewComment creates a parentless XML comment. +func NewComment(comment string) *Comment { + return newComment(comment, nil) +} + +// NewComment creates an XML comment and binds it to a parent element. If +// parent is nil, the Comment remains unbound. +func newComment(comment string, parent *Element) *Comment { + c := &Comment{ + Data: comment, + parent: parent, + } + if parent != nil { + parent.addChild(c) + } + return c +} + +// CreateComment creates an XML comment and adds it as a child of element e. +func (e *Element) CreateComment(comment string) *Comment { + return newComment(comment, e) +} + +// dup duplicates the comment. +func (c *Comment) dup(parent *Element) Token { + return &Comment{ + Data: c.Data, + parent: parent, + } +} + +// Parent returns comment token's parent element, or nil if it has no parent. +func (c *Comment) Parent() *Element { + return c.parent +} + +// setParent replaces the comment token's parent. +func (c *Comment) setParent(parent *Element) { + c.parent = parent +} + +// writeTo serialies the comment to the writer. +func (c *Comment) writeTo(w *bufio.Writer, s *WriteSettings) { + w.WriteString("") +} + +// NewDirective creates a parentless XML directive. +func NewDirective(data string) *Directive { + return newDirective(data, nil) +} + +// newDirective creates an XML directive and binds it to a parent element. If +// parent is nil, the Directive remains unbound. +func newDirective(data string, parent *Element) *Directive { + d := &Directive{ + Data: data, + parent: parent, + } + if parent != nil { + parent.addChild(d) + } + return d +} + +// CreateDirective creates an XML directive and adds it as the last child of +// element e. +func (e *Element) CreateDirective(data string) *Directive { + return newDirective(data, e) +} + +// dup duplicates the directive. +func (d *Directive) dup(parent *Element) Token { + return &Directive{ + Data: d.Data, + parent: parent, + } +} + +// Parent returns directive token's parent element, or nil if it has no +// parent. +func (d *Directive) Parent() *Element { + return d.parent +} + +// setParent replaces the directive token's parent. +func (d *Directive) setParent(parent *Element) { + d.parent = parent +} + +// writeTo serializes the XML directive to the writer. +func (d *Directive) writeTo(w *bufio.Writer, s *WriteSettings) { + w.WriteString("") +} + +// NewProcInst creates a parentless XML processing instruction. +func NewProcInst(target, inst string) *ProcInst { + return newProcInst(target, inst, nil) +} + +// newProcInst creates an XML processing instruction and binds it to a parent +// element. If parent is nil, the ProcInst remains unbound. +func newProcInst(target, inst string, parent *Element) *ProcInst { + p := &ProcInst{ + Target: target, + Inst: inst, + parent: parent, + } + if parent != nil { + parent.addChild(p) + } + return p +} + +// CreateProcInst creates a processing instruction and adds it as a child of +// element e. +func (e *Element) CreateProcInst(target, inst string) *ProcInst { + return newProcInst(target, inst, e) +} + +// dup duplicates the procinst. +func (p *ProcInst) dup(parent *Element) Token { + return &ProcInst{ + Target: p.Target, + Inst: p.Inst, + parent: parent, + } +} + +// Parent returns processing instruction token's parent element, or nil if it +// has no parent. +func (p *ProcInst) Parent() *Element { + return p.parent +} + +// setParent replaces the processing instruction token's parent. +func (p *ProcInst) setParent(parent *Element) { + p.parent = parent +} + +// writeTo serializes the processing instruction to the writer. +func (p *ProcInst) writeTo(w *bufio.Writer, s *WriteSettings) { + w.WriteString("") +} diff --git a/vendor/github.com/beevik/etree/etree_test.go b/vendor/github.com/beevik/etree/etree_test.go new file mode 100644 index 0000000..d3bd7aa --- /dev/null +++ b/vendor/github.com/beevik/etree/etree_test.go @@ -0,0 +1,426 @@ +// Copyright 2015 Brett Vickers. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package etree + +import ( + "io" + "testing" +) + +func checkEq(t *testing.T, got, want string) { + if got == want { + return + } + t.Errorf( + "etree: unexpected result.\nGot:\n%s\nWanted:\n%s\n", + got, want) +} + +func TestDocument(t *testing.T) { + + // Create a document + doc := NewDocument() + doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`) + doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`) + store := doc.CreateElement("store") + store.CreateAttr("xmlns:t", "urn:books-com:titles") + store.CreateDirective("Directive") + store.CreateComment("This is a comment") + book := store.CreateElement("book") + book.CreateAttr("lang", "fr") + book.CreateAttr("lang", "en") + title := book.CreateElement("t:title") + title.SetText("Nicholas Nickleby") + title.SetText("Great Expectations") + author := book.CreateElement("author") + author.CreateCharData("Charles Dickens") + doc.IndentTabs() + + // Serialize the document to a string + s, err := doc.WriteToString() + if err != nil { + t.Error("etree: failed to serialize document") + } + + // Make sure the serialized XML matches expectation. + expected := ` + + + + + + Great Expectations + Charles Dickens + + +` + checkEq(t, s, expected) + + // Test the structure of the XML + if doc.Root() != store { + t.Error("etree: root mismatch") + } + if len(store.ChildElements()) != 1 || len(store.Child) != 7 { + t.Error("etree: incorrect tree structure") + } + if len(book.ChildElements()) != 2 || len(book.Attr) != 1 || len(book.Child) != 5 { + t.Error("etree: incorrect tree structure") + } + if len(title.ChildElements()) != 0 || len(title.Child) != 1 || len(title.Attr) != 0 { + t.Error("etree: incorrect tree structure") + } + if len(author.ChildElements()) != 0 || len(author.Child) != 1 || len(author.Attr) != 0 { + t.Error("etree: incorrect tree structure") + } + if book.parent != store || store.parent != &doc.Element || doc.parent != nil { + t.Error("etree: incorrect tree structure") + } + if title.parent != book || author.parent != book { + t.Error("etree: incorrect tree structure") + } + + // Perform some basic queries on the document + elements := doc.SelectElements("store") + if len(elements) != 1 || elements[0] != store { + t.Error("etree: incorrect SelectElements result") + } + element := doc.SelectElement("store") + if element != store { + t.Error("etree: incorrect SelectElement result") + } + elements = store.SelectElements("book") + if len(elements) != 1 || elements[0] != book { + t.Error("etree: incorrect SelectElements result") + } + element = store.SelectElement("book") + if element != book { + t.Error("etree: incorrect SelectElement result") + } + attr := book.SelectAttr("lang") + if attr == nil || attr.Key != "lang" || attr.Value != "en" { + t.Error("etree: incorrect SelectAttr result") + } + if book.SelectAttrValue("lang", "unknown") != "en" { + t.Error("etree: incorrect SelectAttrValue result") + } + if book.SelectAttrValue("t:missing", "unknown") != "unknown" { + t.Error("etree: incorrect SelectAttrValue result") + } + attr = book.RemoveAttr("lang") + if attr.Value != "en" { + t.Error("etree: incorrect RemoveAttr result") + } + book.CreateAttr("lang", "de") + attr = book.RemoveAttr("lang") + if attr.Value != "de" { + t.Error("etree: incorrect RemoveAttr result") + } + element = book.SelectElement("t:title") + if element != title || element.Text() != "Great Expectations" || len(element.Attr) != 0 { + t.Error("etree: incorrect SelectElement result") + } + element = book.SelectElement("title") + if element != title { + t.Error("etree: incorrect SelectElement result") + } + element = book.SelectElement("p:title") + if element != nil { + t.Error("etree: incorrect SelectElement result") + } + element = book.RemoveChild(title).(*Element) + if element != title { + t.Error("etree: incorrect RemoveElement result") + } + element = book.SelectElement("title") + if element != nil { + t.Error("etree: incorrect SelectElement result") + } +} + +func TestDocumentRead_NonUTF8Encodings(t *testing.T) { + s := ` + + + Great Expectations + Charles Dickens + +` + + doc := NewDocument() + doc.ReadSettings.CharsetReader = func(label string, input io.Reader) (io.Reader, error) { + return input, nil + } + err := doc.ReadFromString(s) + if err != nil { + t.Fatal("etree: incorrect ReadFromString result") + } +} + +func TestDocumentRead_Permissive(t *testing.T) { + s := "" + + doc := NewDocument() + err := doc.ReadFromString(s) + if err == nil { + t.Fatal("etree: incorrect ReadFromString result") + } + + doc.ReadSettings.Permissive = true + err = doc.ReadFromString(s) + if err != nil { + t.Fatal("etree: incorrect ReadFromString result") + } +} + +func TestWriteSettings(t *testing.T) { + BOM := "\xef\xbb\xbf" + + doc := NewDocument() + doc.WriteSettings.CanonicalEndTags = true + doc.WriteSettings.CanonicalText = true + doc.WriteSettings.CanonicalAttrVal = true + doc.CreateCharData(BOM) + doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`) + + people := doc.CreateElement("People") + people.CreateComment("These are all known people") + + jon := people.CreateElement("Person") + jon.CreateAttr("name", "Jon O'Reilly") + jon.SetText("\r<'\">&") + + sally := people.CreateElement("Person") + sally.CreateAttr("name", "Sally") + sally.CreateAttr("escape", "\r\n\t<'\">&") + + doc.Indent(2) + s, err := doc.WriteToString() + if err != nil { + t.Error("etree: WriteSettings WriteTo produced incorrect result.") + } + + expected := BOM + ` + + + <'">& + + +` + checkEq(t, s, expected) +} + +func TestCopy(t *testing.T) { + s := ` + + Great Expectations + Charles Dickens + +` + + doc := NewDocument() + err := doc.ReadFromString(s) + if err != nil { + t.Fatal("etree: incorrect ReadFromString result") + } + + s1, err := doc.WriteToString() + if err != nil { + t.Error("etree: incorrect WriteToString result") + } + + doc2 := doc.Copy() + s2, err := doc2.WriteToString() + if err != nil { + t.Error("etree: incorrect Copy result") + } + + if s1 != s2 { + t.Error("etree: mismatched Copy result") + t.Error("wanted:\n" + s1) + t.Error("got:\n" + s2) + } + + e1 := doc.FindElement("./store/book/title") + e2 := doc2.FindElement("./store/book/title") + if e1 == nil || e2 == nil { + t.Error("etree: incorrect FindElement result") + } + if e1 == e2 { + t.Error("etree: incorrect FindElement result") + } + + e1.parent.RemoveChild(e1) + s1, _ = doc.WriteToString() + s2, _ = doc2.WriteToString() + if s1 == s2 { + t.Error("etree: incorrect result after RemoveElement") + } +} + +func TestInsertChild(t *testing.T) { + testdoc := ` + Great Expectations + Charles Dickens + +` + + doc := NewDocument() + err := doc.ReadFromString(testdoc) + if err != nil { + t.Fatal("etree ReadFromString: " + err.Error()) + } + + year := NewElement("year") + year.SetText("1861") + + book := doc.FindElement("//book") + book.InsertChild(book.SelectElement("t:title"), year) + + expected1 := ` + 1861 + Great Expectations + Charles Dickens + +` + doc.Indent(2) + s1, _ := doc.WriteToString() + checkEq(t, s1, expected1) + + book.RemoveChild(year) + book.InsertChild(book.SelectElement("author"), year) + + expected2 := ` + Great Expectations + 1861 + Charles Dickens + +` + doc.Indent(2) + s2, _ := doc.WriteToString() + checkEq(t, s2, expected2) + + book.RemoveChild(year) + book.InsertChild(book.SelectElement("UNKNOWN"), year) + + expected3 := ` + Great Expectations + Charles Dickens + 1861 + +` + doc.Indent(2) + s3, _ := doc.WriteToString() + checkEq(t, s3, expected3) + + book.RemoveChild(year) + book.InsertChild(nil, year) + + expected4 := ` + Great Expectations + Charles Dickens + 1861 + +` + doc.Indent(2) + s4, _ := doc.WriteToString() + checkEq(t, s4, expected4) +} + +func TestAddChild(t *testing.T) { + testdoc := ` + Great Expectations + Charles Dickens + +` + doc1 := NewDocument() + err := doc1.ReadFromString(testdoc) + if err != nil { + t.Fatal("etree ReadFromString: " + err.Error()) + } + + doc2 := NewDocument() + root := doc2.CreateElement("root") + + for _, e := range doc1.FindElements("//book/*") { + root.AddChild(e) + } + + expected1 := ` +` + doc1.Indent(2) + s1, _ := doc1.WriteToString() + checkEq(t, s1, expected1) + + expected2 := ` + Great Expectations + Charles Dickens + +` + doc2.Indent(2) + s2, _ := doc2.WriteToString() + checkEq(t, s2, expected2) +} + +func TestSetRoot(t *testing.T) { + testdoc := ` + + Great Expectations + Charles Dickens + +` + doc := NewDocument() + err := doc.ReadFromString(testdoc) + if err != nil { + t.Fatal("etree ReadFromString: " + err.Error()) + } + + origroot := doc.Root() + if origroot.Parent() != &doc.Element { + t.Error("Root incorrect") + } + + newroot := NewElement("root") + doc.SetRoot(newroot) + + if doc.Root() != newroot { + t.Error("doc.Root() != newroot") + } + if origroot.Parent() != nil { + t.Error("origroot.Parent() != nil") + } + + expected1 := ` + +` + doc.Indent(2) + s1, _ := doc.WriteToString() + checkEq(t, s1, expected1) + + doc.SetRoot(origroot) + doc.Indent(2) + expected2 := testdoc + s2, _ := doc.WriteToString() + checkEq(t, s2, expected2) + + doc2 := NewDocument() + doc2.CreateProcInst("test", `a="wow"`) + doc2.SetRoot(NewElement("root")) + doc2.Indent(2) + expected3 := expected1 + s3, _ := doc2.WriteToString() + checkEq(t, s3, expected3) + + doc2.SetRoot(doc.Root()) + doc2.Indent(2) + expected4 := testdoc + s4, _ := doc2.WriteToString() + checkEq(t, s4, expected4) + + expected5 := ` +` + doc.Indent(2) + s5, _ := doc.WriteToString() + checkEq(t, s5, expected5) +} diff --git a/vendor/github.com/beevik/etree/example_test.go b/vendor/github.com/beevik/etree/example_test.go new file mode 100644 index 0000000..bdfdf23 --- /dev/null +++ b/vendor/github.com/beevik/etree/example_test.go @@ -0,0 +1,62 @@ +// Copyright 2015 Brett Vickers. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package etree + +import "os" + +// Create an etree Document, add XML entities to it, and serialize it +// to stdout. +func ExampleDocument_creating() { + doc := NewDocument() + doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`) + doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`) + + people := doc.CreateElement("People") + people.CreateComment("These are all known people") + + jon := people.CreateElement("Person") + jon.CreateAttr("name", "Jon O'Reilly") + + sally := people.CreateElement("Person") + sally.CreateAttr("name", "Sally") + + doc.Indent(2) + doc.WriteTo(os.Stdout) + // Output: + // + // + // + // + // + // + // +} + +func ExampleDocument_reading() { + doc := NewDocument() + if err := doc.ReadFromFile("document.xml"); err != nil { + panic(err) + } +} + +func ExamplePath() { + xml := `Great Expectations + Charles DickensUlysses + James Joyce` + + doc := NewDocument() + doc.ReadFromString(xml) + for _, e := range doc.FindElements(".//book[author='Charles Dickens']") { + doc := NewDocument() + doc.SetRoot(e.Copy()) + doc.Indent(2) + doc.WriteTo(os.Stdout) + } + // Output: + // + // Great Expectations + // Charles Dickens + // +} diff --git a/vendor/github.com/beevik/etree/helpers.go b/vendor/github.com/beevik/etree/helpers.go new file mode 100644 index 0000000..4f8350e --- /dev/null +++ b/vendor/github.com/beevik/etree/helpers.go @@ -0,0 +1,188 @@ +// Copyright 2015 Brett Vickers. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package etree + +import ( + "io" + "strings" +) + +// A simple stack +type stack struct { + data []interface{} +} + +func (s *stack) empty() bool { + return len(s.data) == 0 +} + +func (s *stack) push(value interface{}) { + s.data = append(s.data, value) +} + +func (s *stack) pop() interface{} { + value := s.data[len(s.data)-1] + s.data[len(s.data)-1] = nil + s.data = s.data[:len(s.data)-1] + return value +} + +func (s *stack) peek() interface{} { + return s.data[len(s.data)-1] +} + +// A fifo is a simple first-in-first-out queue. +type fifo struct { + data []interface{} + head, tail int +} + +func (f *fifo) add(value interface{}) { + if f.len()+1 >= len(f.data) { + f.grow() + } + f.data[f.tail] = value + if f.tail++; f.tail == len(f.data) { + f.tail = 0 + } +} + +func (f *fifo) remove() interface{} { + value := f.data[f.head] + f.data[f.head] = nil + if f.head++; f.head == len(f.data) { + f.head = 0 + } + return value +} + +func (f *fifo) len() int { + if f.tail >= f.head { + return f.tail - f.head + } + return len(f.data) - f.head + f.tail +} + +func (f *fifo) grow() { + c := len(f.data) * 2 + if c == 0 { + c = 4 + } + buf, count := make([]interface{}, c), f.len() + if f.tail >= f.head { + copy(buf[0:count], f.data[f.head:f.tail]) + } else { + hindex := len(f.data) - f.head + copy(buf[0:hindex], f.data[f.head:]) + copy(buf[hindex:count], f.data[:f.tail]) + } + f.data, f.head, f.tail = buf, 0, count +} + +// countReader implements a proxy reader that counts the number of +// bytes read from its encapsulated reader. +type countReader struct { + r io.Reader + bytes int64 +} + +func newCountReader(r io.Reader) *countReader { + return &countReader{r: r} +} + +func (cr *countReader) Read(p []byte) (n int, err error) { + b, err := cr.r.Read(p) + cr.bytes += int64(b) + return b, err +} + +// countWriter implements a proxy writer that counts the number of +// bytes written by its encapsulated writer. +type countWriter struct { + w io.Writer + bytes int64 +} + +func newCountWriter(w io.Writer) *countWriter { + return &countWriter{w: w} +} + +func (cw *countWriter) Write(p []byte) (n int, err error) { + b, err := cw.w.Write(p) + cw.bytes += int64(b) + return b, err +} + +// isWhitespace returns true if the byte slice contains only +// whitespace characters. +func isWhitespace(s string) bool { + for i := 0; i < len(s); i++ { + if c := s[i]; c != ' ' && c != '\t' && c != '\n' && c != '\r' { + return false + } + } + return true +} + +// spaceMatch returns true if namespace a is the empty string +// or if namespace a equals namespace b. +func spaceMatch(a, b string) bool { + switch { + case a == "": + return true + default: + return a == b + } +} + +// spaceDecompose breaks a namespace:tag identifier at the ':' +// and returns the two parts. +func spaceDecompose(str string) (space, key string) { + colon := strings.IndexByte(str, ':') + if colon == -1 { + return "", str + } + return str[:colon], str[colon+1:] +} + +// Strings used by crIndent +const ( + crsp = "\n " + crtab = "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" +) + +// crIndent returns a carriage return followed by n copies of the +// first non-CR character in the source string. +func crIndent(n int, source string) string { + switch { + case n < 0: + return source[:1] + case n < len(source): + return source[:n+1] + default: + return source + strings.Repeat(source[1:2], n-len(source)+1) + } +} + +// nextIndex returns the index of the next occurrence of sep in s, +// starting from offset. It returns -1 if the sep string is not found. +func nextIndex(s, sep string, offset int) int { + switch i := strings.Index(s[offset:], sep); i { + case -1: + return -1 + default: + return offset + i + } +} + +// isInteger returns true if the string s contains an integer. +func isInteger(s string) bool { + for i := 0; i < len(s); i++ { + if (s[i] < '0' || s[i] > '9') && !(i == 0 && s[i] == '-') { + return false + } + } + return true +} diff --git a/vendor/github.com/beevik/etree/path.go b/vendor/github.com/beevik/etree/path.go new file mode 100644 index 0000000..9cf245e --- /dev/null +++ b/vendor/github.com/beevik/etree/path.go @@ -0,0 +1,516 @@ +// Copyright 2015 Brett Vickers. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package etree + +import ( + "strconv" + "strings" +) + +/* +A Path is an object that represents an optimized version of an +XPath-like search string. Although path strings are XPath-like, +only the following limited syntax is supported: + + . Selects the current element + .. Selects the parent of the current element + * Selects all child elements + // Selects all descendants of the current element + tag Selects all child elements with the given tag + [#] Selects the element of the given index (1-based, + negative starts from the end) + [@attrib] Selects all elements with the given attribute + [@attrib='val'] Selects all elements with the given attribute set to val + [tag] Selects all elements with a child element named tag + [tag='val'] Selects all elements with a child element named tag + and text matching val + [text()] Selects all elements with non-empty text + [text()='val'] Selects all elements whose text matches val + +Examples: + +Select the title elements of all descendant book elements having a +'category' attribute of 'WEB': + //book[@category='WEB']/title + +Select the first book element with a title child containing the text +'Great Expectations': + .//book[title='Great Expectations'][1] + +Starting from the current element, select all children of book elements +with an attribute 'language' set to 'english': + ./book/*[@language='english'] + +Starting from the current element, select all children of book elements +containing the text 'special': + ./book/*[text()='special'] + +Select all descendant book elements whose title element has an attribute +'language' set to 'french': + //book/title[@language='french']/.. + +*/ +type Path struct { + segments []segment +} + +// ErrPath is returned by path functions when an invalid etree path is provided. +type ErrPath string + +// Error returns the string describing a path error. +func (err ErrPath) Error() string { + return "etree: " + string(err) +} + +// CompilePath creates an optimized version of an XPath-like string that +// can be used to query elements in an element tree. +func CompilePath(path string) (Path, error) { + var comp compiler + segments := comp.parsePath(path) + if comp.err != ErrPath("") { + return Path{nil}, comp.err + } + return Path{segments}, nil +} + +// MustCompilePath creates an optimized version of an XPath-like string that +// can be used to query elements in an element tree. Panics if an error +// occurs. Use this function to create Paths when you know the path is +// valid (i.e., if it's hard-coded). +func MustCompilePath(path string) Path { + p, err := CompilePath(path) + if err != nil { + panic(err) + } + return p +} + +// A segment is a portion of a path between "/" characters. +// It contains one selector and zero or more [filters]. +type segment struct { + sel selector + filters []filter +} + +func (seg *segment) apply(e *Element, p *pather) { + seg.sel.apply(e, p) + for _, f := range seg.filters { + f.apply(p) + } +} + +// A selector selects XML elements for consideration by the +// path traversal. +type selector interface { + apply(e *Element, p *pather) +} + +// A filter pares down a list of candidate XML elements based +// on a path filter in [brackets]. +type filter interface { + apply(p *pather) +} + +// A pather is helper object that traverses an element tree using +// a Path object. It collects and deduplicates all elements matching +// the path query. +type pather struct { + queue fifo + results []*Element + inResults map[*Element]bool + candidates []*Element + scratch []*Element // used by filters +} + +// A node represents an element and the remaining path segments that +// should be applied against it by the pather. +type node struct { + e *Element + segments []segment +} + +func newPather() *pather { + return &pather{ + results: make([]*Element, 0), + inResults: make(map[*Element]bool), + candidates: make([]*Element, 0), + scratch: make([]*Element, 0), + } +} + +// traverse follows the path from the element e, collecting +// and then returning all elements that match the path's selectors +// and filters. +func (p *pather) traverse(e *Element, path Path) []*Element { + for p.queue.add(node{e, path.segments}); p.queue.len() > 0; { + p.eval(p.queue.remove().(node)) + } + return p.results +} + +// eval evalutes the current path node by applying the remaining +// path's selector rules against the node's element. +func (p *pather) eval(n node) { + p.candidates = p.candidates[0:0] + seg, remain := n.segments[0], n.segments[1:] + seg.apply(n.e, p) + + if len(remain) == 0 { + for _, c := range p.candidates { + if in := p.inResults[c]; !in { + p.inResults[c] = true + p.results = append(p.results, c) + } + } + } else { + for _, c := range p.candidates { + p.queue.add(node{c, remain}) + } + } +} + +// A compiler generates a compiled path from a path string. +type compiler struct { + err ErrPath +} + +// parsePath parses an XPath-like string describing a path +// through an element tree and returns a slice of segment +// descriptors. +func (c *compiler) parsePath(path string) []segment { + // If path starts or ends with //, fix it + if strings.HasPrefix(path, "//") { + path = "." + path + } + if strings.HasSuffix(path, "//") { + path = path + "*" + } + + // Paths cannot be absolute + if strings.HasPrefix(path, "/") { + c.err = ErrPath("paths cannot be absolute.") + return nil + } + + // Split path into segment objects + var segments []segment + for _, s := range splitPath(path) { + segments = append(segments, c.parseSegment(s)) + if c.err != ErrPath("") { + break + } + } + return segments +} + +func splitPath(path string) []string { + pieces := make([]string, 0) + start := 0 + inquote := false + for i := 0; i+1 <= len(path); i++ { + if path[i] == '\'' { + inquote = !inquote + } else if path[i] == '/' && !inquote { + pieces = append(pieces, path[start:i]) + start = i + 1 + } + } + return append(pieces, path[start:]) +} + +// parseSegment parses a path segment between / characters. +func (c *compiler) parseSegment(path string) segment { + pieces := strings.Split(path, "[") + seg := segment{ + sel: c.parseSelector(pieces[0]), + filters: make([]filter, 0), + } + for i := 1; i < len(pieces); i++ { + fpath := pieces[i] + if fpath[len(fpath)-1] != ']' { + c.err = ErrPath("path has invalid filter [brackets].") + break + } + seg.filters = append(seg.filters, c.parseFilter(fpath[:len(fpath)-1])) + } + return seg +} + +// parseSelector parses a selector at the start of a path segment. +func (c *compiler) parseSelector(path string) selector { + switch path { + case ".": + return new(selectSelf) + case "..": + return new(selectParent) + case "*": + return new(selectChildren) + case "": + return new(selectDescendants) + default: + return newSelectChildrenByTag(path) + } +} + +// parseFilter parses a path filter contained within [brackets]. +func (c *compiler) parseFilter(path string) filter { + if len(path) == 0 { + c.err = ErrPath("path contains an empty filter expression.") + return nil + } + + // Filter contains [@attr='val'], [text()='val'], or [tag='val']? + eqindex := strings.Index(path, "='") + if eqindex >= 0 { + rindex := nextIndex(path, "'", eqindex+2) + if rindex != len(path)-1 { + c.err = ErrPath("path has mismatched filter quotes.") + return nil + } + switch { + case path[0] == '@': + return newFilterAttrVal(path[1:eqindex], path[eqindex+2:rindex]) + case strings.HasPrefix(path, "text()"): + return newFilterTextVal(path[eqindex+2 : rindex]) + default: + return newFilterChildText(path[:eqindex], path[eqindex+2:rindex]) + } + } + + // Filter contains [@attr], [N], [tag] or [text()] + switch { + case path[0] == '@': + return newFilterAttr(path[1:]) + case path == "text()": + return newFilterText() + case isInteger(path): + pos, _ := strconv.Atoi(path) + switch { + case pos > 0: + return newFilterPos(pos - 1) + default: + return newFilterPos(pos) + } + default: + return newFilterChild(path) + } +} + +// selectSelf selects the current element into the candidate list. +type selectSelf struct{} + +func (s *selectSelf) apply(e *Element, p *pather) { + p.candidates = append(p.candidates, e) +} + +// selectParent selects the element's parent into the candidate list. +type selectParent struct{} + +func (s *selectParent) apply(e *Element, p *pather) { + if e.parent != nil { + p.candidates = append(p.candidates, e.parent) + } +} + +// selectChildren selects the element's child elements into the +// candidate list. +type selectChildren struct{} + +func (s *selectChildren) apply(e *Element, p *pather) { + for _, c := range e.Child { + if c, ok := c.(*Element); ok { + p.candidates = append(p.candidates, c) + } + } +} + +// selectDescendants selects all descendant child elements +// of the element into the candidate list. +type selectDescendants struct{} + +func (s *selectDescendants) apply(e *Element, p *pather) { + var queue fifo + for queue.add(e); queue.len() > 0; { + e := queue.remove().(*Element) + p.candidates = append(p.candidates, e) + for _, c := range e.Child { + if c, ok := c.(*Element); ok { + queue.add(c) + } + } + } +} + +// selectChildrenByTag selects into the candidate list all child +// elements of the element having the specified tag. +type selectChildrenByTag struct { + space, tag string +} + +func newSelectChildrenByTag(path string) *selectChildrenByTag { + s, l := spaceDecompose(path) + return &selectChildrenByTag{s, l} +} + +func (s *selectChildrenByTag) apply(e *Element, p *pather) { + for _, c := range e.Child { + if c, ok := c.(*Element); ok && spaceMatch(s.space, c.Space) && s.tag == c.Tag { + p.candidates = append(p.candidates, c) + } + } +} + +// filterPos filters the candidate list, keeping only the +// candidate at the specified index. +type filterPos struct { + index int +} + +func newFilterPos(pos int) *filterPos { + return &filterPos{pos} +} + +func (f *filterPos) apply(p *pather) { + if f.index >= 0 { + if f.index < len(p.candidates) { + p.scratch = append(p.scratch, p.candidates[f.index]) + } + } else { + if -f.index <= len(p.candidates) { + p.scratch = append(p.scratch, p.candidates[len(p.candidates)+f.index]) + } + } + p.candidates, p.scratch = p.scratch, p.candidates[0:0] +} + +// filterAttr filters the candidate list for elements having +// the specified attribute. +type filterAttr struct { + space, key string +} + +func newFilterAttr(str string) *filterAttr { + s, l := spaceDecompose(str) + return &filterAttr{s, l} +} + +func (f *filterAttr) apply(p *pather) { + for _, c := range p.candidates { + for _, a := range c.Attr { + if spaceMatch(f.space, a.Space) && f.key == a.Key { + p.scratch = append(p.scratch, c) + break + } + } + } + p.candidates, p.scratch = p.scratch, p.candidates[0:0] +} + +// filterAttrVal filters the candidate list for elements having +// the specified attribute with the specified value. +type filterAttrVal struct { + space, key, val string +} + +func newFilterAttrVal(str, value string) *filterAttrVal { + s, l := spaceDecompose(str) + return &filterAttrVal{s, l, value} +} + +func (f *filterAttrVal) apply(p *pather) { + for _, c := range p.candidates { + for _, a := range c.Attr { + if spaceMatch(f.space, a.Space) && f.key == a.Key && f.val == a.Value { + p.scratch = append(p.scratch, c) + break + } + } + } + p.candidates, p.scratch = p.scratch, p.candidates[0:0] +} + +// filterText filters the candidate list for elements having text. +type filterText struct{} + +func newFilterText() *filterText { + return &filterText{} +} + +func (f *filterText) apply(p *pather) { + for _, c := range p.candidates { + if c.Text() != "" { + p.scratch = append(p.scratch, c) + } + } + p.candidates, p.scratch = p.scratch, p.candidates[0:0] +} + +// filterTextVal filters the candidate list for elements having +// text equal to the specified value. +type filterTextVal struct { + val string +} + +func newFilterTextVal(value string) *filterTextVal { + return &filterTextVal{value} +} + +func (f *filterTextVal) apply(p *pather) { + for _, c := range p.candidates { + if c.Text() == f.val { + p.scratch = append(p.scratch, c) + } + } + p.candidates, p.scratch = p.scratch, p.candidates[0:0] +} + +// filterChild filters the candidate list for elements having +// a child element with the specified tag. +type filterChild struct { + space, tag string +} + +func newFilterChild(str string) *filterChild { + s, l := spaceDecompose(str) + return &filterChild{s, l} +} + +func (f *filterChild) apply(p *pather) { + for _, c := range p.candidates { + for _, cc := range c.Child { + if cc, ok := cc.(*Element); ok && + spaceMatch(f.space, cc.Space) && + f.tag == cc.Tag { + p.scratch = append(p.scratch, c) + } + } + } + p.candidates, p.scratch = p.scratch, p.candidates[0:0] +} + +// filterChildText filters the candidate list for elements having +// a child element with the specified tag and text. +type filterChildText struct { + space, tag, text string +} + +func newFilterChildText(str, text string) *filterChildText { + s, l := spaceDecompose(str) + return &filterChildText{s, l, text} +} + +func (f *filterChildText) apply(p *pather) { + for _, c := range p.candidates { + for _, cc := range c.Child { + if cc, ok := cc.(*Element); ok && + spaceMatch(f.space, cc.Space) && + f.tag == cc.Tag && + f.text == cc.Text() { + p.scratch = append(p.scratch, c) + } + } + } + p.candidates, p.scratch = p.scratch, p.candidates[0:0] +} diff --git a/vendor/github.com/beevik/etree/path_test.go b/vendor/github.com/beevik/etree/path_test.go new file mode 100644 index 0000000..ce6338c --- /dev/null +++ b/vendor/github.com/beevik/etree/path_test.go @@ -0,0 +1,173 @@ +// Copyright 2015 Brett Vickers. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package etree + +import "testing" + +var testXML = ` + + + + + + + Everyday Italian + Giada De Laurentiis + 2005 + 30.00 + Clarkson Potter + + + + Harry Potter + J K. Rowling + 2005 + 29.99 + + + + + + XQuery Kick Start + James McGovern + Per Bothner + Kurt Cagle + James Linn + Vaidyanathan Nagarajan + 2003 + 49.99 + + + + + + + Learning XML + Erik T. Ray + 2003 + 39.95 + + + +` + +type test struct { + path string + result interface{} +} + +type errorResult string + +var tests = []test{ + + // basic queries + {"./bookstore/book/title", []string{"Everyday Italian", "Harry Potter", "XQuery Kick Start", "Learning XML"}}, + {"./bookstore/book/author", []string{"Giada De Laurentiis", "J K. Rowling", "James McGovern", "Per Bothner", "Kurt Cagle", "James Linn", "Vaidyanathan Nagarajan", "Erik T. Ray"}}, + {"./bookstore/book/year", []string{"2005", "2005", "2003", "2003"}}, + {"./bookstore/book/p:price", []string{"30.00", "29.99", "49.99", "39.95"}}, + {"./bookstore/book/isbn", nil}, + + // descendant queries + {"//title", []string{"Everyday Italian", "Harry Potter", "XQuery Kick Start", "Learning XML"}}, + {"//book/title", []string{"Everyday Italian", "Harry Potter", "XQuery Kick Start", "Learning XML"}}, + {".//title", []string{"Everyday Italian", "Harry Potter", "XQuery Kick Start", "Learning XML"}}, + {".//bookstore//title", []string{"Everyday Italian", "Harry Potter", "XQuery Kick Start", "Learning XML"}}, + {".//book/title", []string{"Everyday Italian", "Harry Potter", "XQuery Kick Start", "Learning XML"}}, + {".//p:price/.", []string{"30.00", "29.99", "49.99", "39.95"}}, + {".//price", []string{"30.00", "29.99", "49.99", "39.95"}}, + + // positional queries + {"./bookstore/book[1]/title", "Everyday Italian"}, + {"./bookstore/book[4]/title", "Learning XML"}, + {"./bookstore/book[5]/title", nil}, + {"./bookstore/book[3]/author[0]", "James McGovern"}, + {"./bookstore/book[3]/author[1]", "James McGovern"}, + {"./bookstore/book[3]/author[3]/./.", "Kurt Cagle"}, + {"./bookstore/book[3]/author[6]", nil}, + {"./bookstore/book[-1]/title", "Learning XML"}, + {"./bookstore/book[-4]/title", "Everyday Italian"}, + {"./bookstore/book[-5]/title", nil}, + + // text queries + {"./bookstore/book[author='James McGovern']/title", "XQuery Kick Start"}, + {"./bookstore/book[author='Per Bothner']/title", "XQuery Kick Start"}, + {"./bookstore/book[author='Kurt Cagle']/title", "XQuery Kick Start"}, + {"./bookstore/book[author='James Linn']/title", "XQuery Kick Start"}, + {"./bookstore/book[author='Vaidyanathan Nagarajan']/title", "XQuery Kick Start"}, + {"//book[p:price='29.99']/title", "Harry Potter"}, + {"//book[price='29.99']/title", "Harry Potter"}, + {"//book/price[text()='29.99']", "29.99"}, + {"//book/author[text()='Kurt Cagle']", "Kurt Cagle"}, + {"//book/editor[text()]", []string{"Clarkson Potter", "\n\t\t"}}, + + // attribute queries + {"./bookstore/book[@category='WEB']/title", []string{"XQuery Kick Start", "Learning XML"}}, + {"./bookstore/book[@path='/books/xml']/title", []string{"Learning XML"}}, + {"./bookstore/book[@category='COOKING']/title[@lang='en']", "Everyday Italian"}, + {"./bookstore/book/title[@lang='en'][@sku='150']", "Harry Potter"}, + {"./bookstore/book/title[@lang='fr']", nil}, + + // parent queries + {"./bookstore/book[@category='COOKING']/title/../../book[4]/title", "Learning XML"}, + + // bad paths + {"/bookstore", errorResult("etree: paths cannot be absolute.")}, + {"./bookstore/book[]", errorResult("etree: path contains an empty filter expression.")}, + {"./bookstore/book[@category='WEB'", errorResult("etree: path has invalid filter [brackets].")}, + {"./bookstore/book[@category='WEB]", errorResult("etree: path has mismatched filter quotes.")}, + {"./bookstore/book[author]a", errorResult("etree: path has invalid filter [brackets].")}, +} + +func TestPath(t *testing.T) { + doc := NewDocument() + err := doc.ReadFromString(testXML) + if err != nil { + t.Error(err) + } + + for _, test := range tests { + path, err := CompilePath(test.path) + if err != nil { + if r, ok := test.result.(errorResult); !ok || err.Error() != string(r) { + fail(t, test) + } + continue + } + + // Test both FindElementsPath and FindElementPath + element := doc.FindElementPath(path) + elements := doc.FindElementsPath(path) + + switch s := test.result.(type) { + case errorResult: + fail(t, test) + case nil: + if element != nil || len(elements) != 0 { + fail(t, test) + } + case string: + if element == nil || element.Text() != s || + len(elements) != 1 || elements[0].Text() != s { + fail(t, test) + } + case []string: + if element == nil || element.Text() != s[0] || len(elements) != len(s) { + fail(t, test) + continue + } + for i := 0; i < len(elements); i++ { + if elements[i].Text() != s[i] { + fail(t, test) + break + } + } + } + + } +} + +func fail(t *testing.T, test test) { + t.Errorf("etree: failed test '%s'\n", test.path) +} diff --git a/vendor/github.com/beorn7/perks/.gitignore b/vendor/github.com/beorn7/perks/.gitignore new file mode 100644 index 0000000..1bd9209 --- /dev/null +++ b/vendor/github.com/beorn7/perks/.gitignore @@ -0,0 +1,2 @@ +*.test +*.prof diff --git a/vendor/github.com/beorn7/perks/LICENSE b/vendor/github.com/beorn7/perks/LICENSE new file mode 100644 index 0000000..339177b --- /dev/null +++ b/vendor/github.com/beorn7/perks/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2013 Blake Mizerany + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/beorn7/perks/README.md b/vendor/github.com/beorn7/perks/README.md new file mode 100644 index 0000000..fc05777 --- /dev/null +++ b/vendor/github.com/beorn7/perks/README.md @@ -0,0 +1,31 @@ +# Perks for Go (golang.org) + +Perks contains the Go package quantile that computes approximate quantiles over +an unbounded data stream within low memory and CPU bounds. + +For more information and examples, see: +http://godoc.org/github.com/bmizerany/perks + +A very special thank you and shout out to Graham Cormode (Rutgers University), +Flip Korn (AT&T Labs–Research), S. Muthukrishnan (Rutgers University), and +Divesh Srivastava (AT&T Labs–Research) for their research and publication of +[Effective Computation of Biased Quantiles over Data Streams](http://www.cs.rutgers.edu/~muthu/bquant.pdf) + +Thank you, also: +* Armon Dadgar (@armon) +* Andrew Gerrand (@nf) +* Brad Fitzpatrick (@bradfitz) +* Keith Rarick (@kr) + +FAQ: + +Q: Why not move the quantile package into the project root? +A: I want to add more packages to perks later. + +Copyright (C) 2013 Blake Mizerany + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/beorn7/perks/quantile/bench_test.go b/vendor/github.com/beorn7/perks/quantile/bench_test.go new file mode 100644 index 0000000..0bd0e4e --- /dev/null +++ b/vendor/github.com/beorn7/perks/quantile/bench_test.go @@ -0,0 +1,63 @@ +package quantile + +import ( + "testing" +) + +func BenchmarkInsertTargeted(b *testing.B) { + b.ReportAllocs() + + s := NewTargeted(Targets) + b.ResetTimer() + for i := float64(0); i < float64(b.N); i++ { + s.Insert(i) + } +} + +func BenchmarkInsertTargetedSmallEpsilon(b *testing.B) { + s := NewTargeted(TargetsSmallEpsilon) + b.ResetTimer() + for i := float64(0); i < float64(b.N); i++ { + s.Insert(i) + } +} + +func BenchmarkInsertBiased(b *testing.B) { + s := NewLowBiased(0.01) + b.ResetTimer() + for i := float64(0); i < float64(b.N); i++ { + s.Insert(i) + } +} + +func BenchmarkInsertBiasedSmallEpsilon(b *testing.B) { + s := NewLowBiased(0.0001) + b.ResetTimer() + for i := float64(0); i < float64(b.N); i++ { + s.Insert(i) + } +} + +func BenchmarkQuery(b *testing.B) { + s := NewTargeted(Targets) + for i := float64(0); i < 1e6; i++ { + s.Insert(i) + } + b.ResetTimer() + n := float64(b.N) + for i := float64(0); i < n; i++ { + s.Query(i / n) + } +} + +func BenchmarkQuerySmallEpsilon(b *testing.B) { + s := NewTargeted(TargetsSmallEpsilon) + for i := float64(0); i < 1e6; i++ { + s.Insert(i) + } + b.ResetTimer() + n := float64(b.N) + for i := float64(0); i < n; i++ { + s.Query(i / n) + } +} diff --git a/vendor/github.com/beorn7/perks/quantile/example_test.go b/vendor/github.com/beorn7/perks/quantile/example_test.go new file mode 100644 index 0000000..ab3293a --- /dev/null +++ b/vendor/github.com/beorn7/perks/quantile/example_test.go @@ -0,0 +1,121 @@ +// +build go1.1 + +package quantile_test + +import ( + "bufio" + "fmt" + "log" + "os" + "strconv" + "time" + + "github.com/beorn7/perks/quantile" +) + +func Example_simple() { + ch := make(chan float64) + go sendFloats(ch) + + // Compute the 50th, 90th, and 99th percentile. + q := quantile.NewTargeted(map[float64]float64{ + 0.50: 0.005, + 0.90: 0.001, + 0.99: 0.0001, + }) + for v := range ch { + q.Insert(v) + } + + fmt.Println("perc50:", q.Query(0.50)) + fmt.Println("perc90:", q.Query(0.90)) + fmt.Println("perc99:", q.Query(0.99)) + fmt.Println("count:", q.Count()) + // Output: + // perc50: 5 + // perc90: 16 + // perc99: 223 + // count: 2388 +} + +func Example_mergeMultipleStreams() { + // Scenario: + // We have multiple database shards. On each shard, there is a process + // collecting query response times from the database logs and inserting + // them into a Stream (created via NewTargeted(0.90)), much like the + // Simple example. These processes expose a network interface for us to + // ask them to serialize and send us the results of their + // Stream.Samples so we may Merge and Query them. + // + // NOTES: + // * These sample sets are small, allowing us to get them + // across the network much faster than sending the entire list of data + // points. + // + // * For this to work correctly, we must supply the same quantiles + // a priori the process collecting the samples supplied to NewTargeted, + // even if we do not plan to query them all here. + ch := make(chan quantile.Samples) + getDBQuerySamples(ch) + q := quantile.NewTargeted(map[float64]float64{0.90: 0.001}) + for samples := range ch { + q.Merge(samples) + } + fmt.Println("perc90:", q.Query(0.90)) +} + +func Example_window() { + // Scenario: We want the 90th, 95th, and 99th percentiles for each + // minute. + + ch := make(chan float64) + go sendStreamValues(ch) + + tick := time.NewTicker(1 * time.Minute) + q := quantile.NewTargeted(map[float64]float64{ + 0.90: 0.001, + 0.95: 0.0005, + 0.99: 0.0001, + }) + for { + select { + case t := <-tick.C: + flushToDB(t, q.Samples()) + q.Reset() + case v := <-ch: + q.Insert(v) + } + } +} + +func sendStreamValues(ch chan float64) { + // Use your imagination +} + +func flushToDB(t time.Time, samples quantile.Samples) { + // Use your imagination +} + +// This is a stub for the above example. In reality this would hit the remote +// servers via http or something like it. +func getDBQuerySamples(ch chan quantile.Samples) {} + +func sendFloats(ch chan<- float64) { + f, err := os.Open("exampledata.txt") + if err != nil { + log.Fatal(err) + } + sc := bufio.NewScanner(f) + for sc.Scan() { + b := sc.Bytes() + v, err := strconv.ParseFloat(string(b), 64) + if err != nil { + log.Fatal(err) + } + ch <- v + } + if sc.Err() != nil { + log.Fatal(sc.Err()) + } + close(ch) +} diff --git a/vendor/github.com/beorn7/perks/quantile/exampledata.txt b/vendor/github.com/beorn7/perks/quantile/exampledata.txt new file mode 100644 index 0000000..1602287 --- /dev/null +++ b/vendor/github.com/beorn7/perks/quantile/exampledata.txt @@ -0,0 +1,2388 @@ +8 +5 +26 +12 +5 +235 +13 +6 +28 +30 +3 +3 +3 +3 +5 +2 +33 +7 +2 +4 +7 +12 +14 +5 +8 +3 +10 +4 +5 +3 +6 +6 +209 +20 +3 +10 +14 +3 +4 +6 +8 +5 +11 +7 +3 +2 +3 +3 +212 +5 +222 +4 +10 +10 +5 +6 +3 +8 +3 +10 +254 +220 +2 +3 +5 +24 +5 +4 +222 +7 +3 +3 +223 +8 +15 +12 +14 +14 +3 +2 +2 +3 +13 +3 +11 +4 +4 +6 +5 +7 +13 +5 +3 +5 +2 +5 +3 +5 +2 +7 +15 +17 +14 +3 +6 +6 +3 +17 +5 +4 +7 +6 +4 +4 +8 +6 +8 +3 +9 +3 +6 +3 +4 +5 +3 +3 +660 +4 +6 +10 +3 +6 +3 +2 +5 +13 +2 +4 +4 +10 +4 +8 +4 +3 +7 +9 +9 +3 +10 +37 +3 +13 +4 +12 +3 +6 +10 +8 +5 +21 +2 +3 +8 +3 +2 +3 +3 +4 +12 +2 +4 +8 +8 +4 +3 +2 +20 +1 +6 +32 +2 +11 +6 +18 +3 +8 +11 +3 +212 +3 +4 +2 +6 +7 +12 +11 +3 +2 +16 +10 +6 +4 +6 +3 +2 +7 +3 +2 +2 +2 +2 +5 +6 +4 +3 +10 +3 +4 +6 +5 +3 +4 +4 +5 +6 +4 +3 +4 +4 +5 +7 +5 +5 +3 +2 +7 +2 +4 +12 +4 +5 +6 +2 +4 +4 +8 +4 +15 +13 +7 +16 +5 +3 +23 +5 +5 +7 +3 +2 +9 +8 +7 +5 +8 +11 +4 +10 +76 +4 +47 +4 +3 +2 +7 +4 +2 +3 +37 +10 +4 +2 +20 +5 +4 +4 +10 +10 +4 +3 +7 +23 +240 +7 +13 +5 +5 +3 +3 +2 +5 +4 +2 +8 +7 +19 +2 +23 +8 +7 +2 +5 +3 +8 +3 +8 +13 +5 +5 +5 +2 +3 +23 +4 +9 +8 +4 +3 +3 +5 +220 +2 +3 +4 +6 +14 +3 +53 +6 +2 +5 +18 +6 +3 +219 +6 +5 +2 +5 +3 +6 +5 +15 +4 +3 +17 +3 +2 +4 +7 +2 +3 +3 +4 +4 +3 +2 +664 +6 +3 +23 +5 +5 +16 +5 +8 +2 +4 +2 +24 +12 +3 +2 +3 +5 +8 +3 +5 +4 +3 +14 +3 +5 +8 +2 +3 +7 +9 +4 +2 +3 +6 +8 +4 +3 +4 +6 +5 +3 +3 +6 +3 +19 +4 +4 +6 +3 +6 +3 +5 +22 +5 +4 +4 +3 +8 +11 +4 +9 +7 +6 +13 +4 +4 +4 +6 +17 +9 +3 +3 +3 +4 +3 +221 +5 +11 +3 +4 +2 +12 +6 +3 +5 +7 +5 +7 +4 +9 +7 +14 +37 +19 +217 +16 +3 +5 +2 +2 +7 +19 +7 +6 +7 +4 +24 +5 +11 +4 +7 +7 +9 +13 +3 +4 +3 +6 +28 +4 +4 +5 +5 +2 +5 +6 +4 +4 +6 +10 +5 +4 +3 +2 +3 +3 +6 +5 +5 +4 +3 +2 +3 +7 +4 +6 +18 +16 +8 +16 +4 +5 +8 +6 +9 +13 +1545 +6 +215 +6 +5 +6 +3 +45 +31 +5 +2 +2 +4 +3 +3 +2 +5 +4 +3 +5 +7 +7 +4 +5 +8 +5 +4 +749 +2 +31 +9 +11 +2 +11 +5 +4 +4 +7 +9 +11 +4 +5 +4 +7 +3 +4 +6 +2 +15 +3 +4 +3 +4 +3 +5 +2 +13 +5 +5 +3 +3 +23 +4 +4 +5 +7 +4 +13 +2 +4 +3 +4 +2 +6 +2 +7 +3 +5 +5 +3 +29 +5 +4 +4 +3 +10 +2 +3 +79 +16 +6 +6 +7 +7 +3 +5 +5 +7 +4 +3 +7 +9 +5 +6 +5 +9 +6 +3 +6 +4 +17 +2 +10 +9 +3 +6 +2 +3 +21 +22 +5 +11 +4 +2 +17 +2 +224 +2 +14 +3 +4 +4 +2 +4 +4 +4 +4 +5 +3 +4 +4 +10 +2 +6 +3 +3 +5 +7 +2 +7 +5 +6 +3 +218 +2 +2 +5 +2 +6 +3 +5 +222 +14 +6 +33 +3 +2 +5 +3 +3 +3 +9 +5 +3 +3 +2 +7 +4 +3 +4 +3 +5 +6 +5 +26 +4 +13 +9 +7 +3 +221 +3 +3 +4 +4 +4 +4 +2 +18 +5 +3 +7 +9 +6 +8 +3 +10 +3 +11 +9 +5 +4 +17 +5 +5 +6 +6 +3 +2 +4 +12 +17 +6 +7 +218 +4 +2 +4 +10 +3 +5 +15 +3 +9 +4 +3 +3 +6 +29 +3 +3 +4 +5 +5 +3 +8 +5 +6 +6 +7 +5 +3 +5 +3 +29 +2 +31 +5 +15 +24 +16 +5 +207 +4 +3 +3 +2 +15 +4 +4 +13 +5 +5 +4 +6 +10 +2 +7 +8 +4 +6 +20 +5 +3 +4 +3 +12 +12 +5 +17 +7 +3 +3 +3 +6 +10 +3 +5 +25 +80 +4 +9 +3 +2 +11 +3 +3 +2 +3 +8 +7 +5 +5 +19 +5 +3 +3 +12 +11 +2 +6 +5 +5 +5 +3 +3 +3 +4 +209 +14 +3 +2 +5 +19 +4 +4 +3 +4 +14 +5 +6 +4 +13 +9 +7 +4 +7 +10 +2 +9 +5 +7 +2 +8 +4 +6 +5 +5 +222 +8 +7 +12 +5 +216 +3 +4 +4 +6 +3 +14 +8 +7 +13 +4 +3 +3 +3 +3 +17 +5 +4 +3 +33 +6 +6 +33 +7 +5 +3 +8 +7 +5 +2 +9 +4 +2 +233 +24 +7 +4 +8 +10 +3 +4 +15 +2 +16 +3 +3 +13 +12 +7 +5 +4 +207 +4 +2 +4 +27 +15 +2 +5 +2 +25 +6 +5 +5 +6 +13 +6 +18 +6 +4 +12 +225 +10 +7 +5 +2 +2 +11 +4 +14 +21 +8 +10 +3 +5 +4 +232 +2 +5 +5 +3 +7 +17 +11 +6 +6 +23 +4 +6 +3 +5 +4 +2 +17 +3 +6 +5 +8 +3 +2 +2 +14 +9 +4 +4 +2 +5 +5 +3 +7 +6 +12 +6 +10 +3 +6 +2 +2 +19 +5 +4 +4 +9 +2 +4 +13 +3 +5 +6 +3 +6 +5 +4 +9 +6 +3 +5 +7 +3 +6 +6 +4 +3 +10 +6 +3 +221 +3 +5 +3 +6 +4 +8 +5 +3 +6 +4 +4 +2 +54 +5 +6 +11 +3 +3 +4 +4 +4 +3 +7 +3 +11 +11 +7 +10 +6 +13 +223 +213 +15 +231 +7 +3 +7 +228 +2 +3 +4 +4 +5 +6 +7 +4 +13 +3 +4 +5 +3 +6 +4 +6 +7 +2 +4 +3 +4 +3 +3 +6 +3 +7 +3 +5 +18 +5 +6 +8 +10 +3 +3 +3 +2 +4 +2 +4 +4 +5 +6 +6 +4 +10 +13 +3 +12 +5 +12 +16 +8 +4 +19 +11 +2 +4 +5 +6 +8 +5 +6 +4 +18 +10 +4 +2 +216 +6 +6 +6 +2 +4 +12 +8 +3 +11 +5 +6 +14 +5 +3 +13 +4 +5 +4 +5 +3 +28 +6 +3 +7 +219 +3 +9 +7 +3 +10 +6 +3 +4 +19 +5 +7 +11 +6 +15 +19 +4 +13 +11 +3 +7 +5 +10 +2 +8 +11 +2 +6 +4 +6 +24 +6 +3 +3 +3 +3 +6 +18 +4 +11 +4 +2 +5 +10 +8 +3 +9 +5 +3 +4 +5 +6 +2 +5 +7 +4 +4 +14 +6 +4 +4 +5 +5 +7 +2 +4 +3 +7 +3 +3 +6 +4 +5 +4 +4 +4 +3 +3 +3 +3 +8 +14 +2 +3 +5 +3 +2 +4 +5 +3 +7 +3 +3 +18 +3 +4 +4 +5 +7 +3 +3 +3 +13 +5 +4 +8 +211 +5 +5 +3 +5 +2 +5 +4 +2 +655 +6 +3 +5 +11 +2 +5 +3 +12 +9 +15 +11 +5 +12 +217 +2 +6 +17 +3 +3 +207 +5 +5 +4 +5 +9 +3 +2 +8 +5 +4 +3 +2 +5 +12 +4 +14 +5 +4 +2 +13 +5 +8 +4 +225 +4 +3 +4 +5 +4 +3 +3 +6 +23 +9 +2 +6 +7 +233 +4 +4 +6 +18 +3 +4 +6 +3 +4 +4 +2 +3 +7 +4 +13 +227 +4 +3 +5 +4 +2 +12 +9 +17 +3 +7 +14 +6 +4 +5 +21 +4 +8 +9 +2 +9 +25 +16 +3 +6 +4 +7 +8 +5 +2 +3 +5 +4 +3 +3 +5 +3 +3 +3 +2 +3 +19 +2 +4 +3 +4 +2 +3 +4 +4 +2 +4 +3 +3 +3 +2 +6 +3 +17 +5 +6 +4 +3 +13 +5 +3 +3 +3 +4 +9 +4 +2 +14 +12 +4 +5 +24 +4 +3 +37 +12 +11 +21 +3 +4 +3 +13 +4 +2 +3 +15 +4 +11 +4 +4 +3 +8 +3 +4 +4 +12 +8 +5 +3 +3 +4 +2 +220 +3 +5 +223 +3 +3 +3 +10 +3 +15 +4 +241 +9 +7 +3 +6 +6 +23 +4 +13 +7 +3 +4 +7 +4 +9 +3 +3 +4 +10 +5 +5 +1 +5 +24 +2 +4 +5 +5 +6 +14 +3 +8 +2 +3 +5 +13 +13 +3 +5 +2 +3 +15 +3 +4 +2 +10 +4 +4 +4 +5 +5 +3 +5 +3 +4 +7 +4 +27 +3 +6 +4 +15 +3 +5 +6 +6 +5 +4 +8 +3 +9 +2 +6 +3 +4 +3 +7 +4 +18 +3 +11 +3 +3 +8 +9 +7 +24 +3 +219 +7 +10 +4 +5 +9 +12 +2 +5 +4 +4 +4 +3 +3 +19 +5 +8 +16 +8 +6 +22 +3 +23 +3 +242 +9 +4 +3 +3 +5 +7 +3 +3 +5 +8 +3 +7 +5 +14 +8 +10 +3 +4 +3 +7 +4 +6 +7 +4 +10 +4 +3 +11 +3 +7 +10 +3 +13 +6 +8 +12 +10 +5 +7 +9 +3 +4 +7 +7 +10 +8 +30 +9 +19 +4 +3 +19 +15 +4 +13 +3 +215 +223 +4 +7 +4 +8 +17 +16 +3 +7 +6 +5 +5 +4 +12 +3 +7 +4 +4 +13 +4 +5 +2 +5 +6 +5 +6 +6 +7 +10 +18 +23 +9 +3 +3 +6 +5 +2 +4 +2 +7 +3 +3 +2 +5 +5 +14 +10 +224 +6 +3 +4 +3 +7 +5 +9 +3 +6 +4 +2 +5 +11 +4 +3 +3 +2 +8 +4 +7 +4 +10 +7 +3 +3 +18 +18 +17 +3 +3 +3 +4 +5 +3 +3 +4 +12 +7 +3 +11 +13 +5 +4 +7 +13 +5 +4 +11 +3 +12 +3 +6 +4 +4 +21 +4 +6 +9 +5 +3 +10 +8 +4 +6 +4 +4 +6 +5 +4 +8 +6 +4 +6 +4 +4 +5 +9 +6 +3 +4 +2 +9 +3 +18 +2 +4 +3 +13 +3 +6 +6 +8 +7 +9 +3 +2 +16 +3 +4 +6 +3 +2 +33 +22 +14 +4 +9 +12 +4 +5 +6 +3 +23 +9 +4 +3 +5 +5 +3 +4 +5 +3 +5 +3 +10 +4 +5 +5 +8 +4 +4 +6 +8 +5 +4 +3 +4 +6 +3 +3 +3 +5 +9 +12 +6 +5 +9 +3 +5 +3 +2 +2 +2 +18 +3 +2 +21 +2 +5 +4 +6 +4 +5 +10 +3 +9 +3 +2 +10 +7 +3 +6 +6 +4 +4 +8 +12 +7 +3 +7 +3 +3 +9 +3 +4 +5 +4 +4 +5 +5 +10 +15 +4 +4 +14 +6 +227 +3 +14 +5 +216 +22 +5 +4 +2 +2 +6 +3 +4 +2 +9 +9 +4 +3 +28 +13 +11 +4 +5 +3 +3 +2 +3 +3 +5 +3 +4 +3 +5 +23 +26 +3 +4 +5 +6 +4 +6 +3 +5 +5 +3 +4 +3 +2 +2 +2 +7 +14 +3 +6 +7 +17 +2 +2 +15 +14 +16 +4 +6 +7 +13 +6 +4 +5 +6 +16 +3 +3 +28 +3 +6 +15 +3 +9 +2 +4 +6 +3 +3 +22 +4 +12 +6 +7 +2 +5 +4 +10 +3 +16 +6 +9 +2 +5 +12 +7 +5 +5 +5 +5 +2 +11 +9 +17 +4 +3 +11 +7 +3 +5 +15 +4 +3 +4 +211 +8 +7 +5 +4 +7 +6 +7 +6 +3 +6 +5 +6 +5 +3 +4 +4 +26 +4 +6 +10 +4 +4 +3 +2 +3 +3 +4 +5 +9 +3 +9 +4 +4 +5 +5 +8 +2 +4 +2 +3 +8 +4 +11 +19 +5 +8 +6 +3 +5 +6 +12 +3 +2 +4 +16 +12 +3 +4 +4 +8 +6 +5 +6 +6 +219 +8 +222 +6 +16 +3 +13 +19 +5 +4 +3 +11 +6 +10 +4 +7 +7 +12 +5 +3 +3 +5 +6 +10 +3 +8 +2 +5 +4 +7 +2 +4 +4 +2 +12 +9 +6 +4 +2 +40 +2 +4 +10 +4 +223 +4 +2 +20 +6 +7 +24 +5 +4 +5 +2 +20 +16 +6 +5 +13 +2 +3 +3 +19 +3 +2 +4 +5 +6 +7 +11 +12 +5 +6 +7 +7 +3 +5 +3 +5 +3 +14 +3 +4 +4 +2 +11 +1 +7 +3 +9 +6 +11 +12 +5 +8 +6 +221 +4 +2 +12 +4 +3 +15 +4 +5 +226 +7 +218 +7 +5 +4 +5 +18 +4 +5 +9 +4 +4 +2 +9 +18 +18 +9 +5 +6 +6 +3 +3 +7 +3 +5 +4 +4 +4 +12 +3 +6 +31 +5 +4 +7 +3 +6 +5 +6 +5 +11 +2 +2 +11 +11 +6 +7 +5 +8 +7 +10 +5 +23 +7 +4 +3 +5 +34 +2 +5 +23 +7 +3 +6 +8 +4 +4 +4 +2 +5 +3 +8 +5 +4 +8 +25 +2 +3 +17 +8 +3 +4 +8 +7 +3 +15 +6 +5 +7 +21 +9 +5 +6 +6 +5 +3 +2 +3 +10 +3 +6 +3 +14 +7 +4 +4 +8 +7 +8 +2 +6 +12 +4 +213 +6 +5 +21 +8 +2 +5 +23 +3 +11 +2 +3 +6 +25 +2 +3 +6 +7 +6 +6 +4 +4 +6 +3 +17 +9 +7 +6 +4 +3 +10 +7 +2 +3 +3 +3 +11 +8 +3 +7 +6 +4 +14 +36 +3 +4 +3 +3 +22 +13 +21 +4 +2 +7 +4 +4 +17 +15 +3 +7 +11 +2 +4 +7 +6 +209 +6 +3 +2 +2 +24 +4 +9 +4 +3 +3 +3 +29 +2 +2 +4 +3 +3 +5 +4 +6 +3 +3 +2 +4 diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go new file mode 100644 index 0000000..f4cabd6 --- /dev/null +++ b/vendor/github.com/beorn7/perks/quantile/stream.go @@ -0,0 +1,292 @@ +// Package quantile computes approximate quantiles over an unbounded data +// stream within low memory and CPU bounds. +// +// A small amount of accuracy is traded to achieve the above properties. +// +// Multiple streams can be merged before calling Query to generate a single set +// of results. This is meaningful when the streams represent the same type of +// data. See Merge and Samples. +// +// For more detailed information about the algorithm used, see: +// +// Effective Computation of Biased Quantiles over Data Streams +// +// http://www.cs.rutgers.edu/~muthu/bquant.pdf +package quantile + +import ( + "math" + "sort" +) + +// Sample holds an observed value and meta information for compression. JSON +// tags have been added for convenience. +type Sample struct { + Value float64 `json:",string"` + Width float64 `json:",string"` + Delta float64 `json:",string"` +} + +// Samples represents a slice of samples. It implements sort.Interface. +type Samples []Sample + +func (a Samples) Len() int { return len(a) } +func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value } +func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +type invariant func(s *stream, r float64) float64 + +// NewLowBiased returns an initialized Stream for low-biased quantiles +// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but +// error guarantees can still be given even for the lower ranks of the data +// distribution. +// +// The provided epsilon is a relative error, i.e. the true quantile of a value +// returned by a query is guaranteed to be within (1±Epsilon)*Quantile. +// +// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error +// properties. +func NewLowBiased(epsilon float64) *Stream { + ƒ := func(s *stream, r float64) float64 { + return 2 * epsilon * r + } + return newStream(ƒ) +} + +// NewHighBiased returns an initialized Stream for high-biased quantiles +// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but +// error guarantees can still be given even for the higher ranks of the data +// distribution. +// +// The provided epsilon is a relative error, i.e. the true quantile of a value +// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile). +// +// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error +// properties. +func NewHighBiased(epsilon float64) *Stream { + ƒ := func(s *stream, r float64) float64 { + return 2 * epsilon * (s.n - r) + } + return newStream(ƒ) +} + +// NewTargeted returns an initialized Stream concerned with a particular set of +// quantile values that are supplied a priori. Knowing these a priori reduces +// space and computation time. The targets map maps the desired quantiles to +// their absolute errors, i.e. the true quantile of a value returned by a query +// is guaranteed to be within (Quantile±Epsilon). +// +// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties. +func NewTargeted(targets map[float64]float64) *Stream { + ƒ := func(s *stream, r float64) float64 { + var m = math.MaxFloat64 + var f float64 + for quantile, epsilon := range targets { + if quantile*s.n <= r { + f = (2 * epsilon * r) / quantile + } else { + f = (2 * epsilon * (s.n - r)) / (1 - quantile) + } + if f < m { + m = f + } + } + return m + } + return newStream(ƒ) +} + +// Stream computes quantiles for a stream of float64s. It is not thread-safe by +// design. Take care when using across multiple goroutines. +type Stream struct { + *stream + b Samples + sorted bool +} + +func newStream(ƒ invariant) *Stream { + x := &stream{ƒ: ƒ} + return &Stream{x, make(Samples, 0, 500), true} +} + +// Insert inserts v into the stream. +func (s *Stream) Insert(v float64) { + s.insert(Sample{Value: v, Width: 1}) +} + +func (s *Stream) insert(sample Sample) { + s.b = append(s.b, sample) + s.sorted = false + if len(s.b) == cap(s.b) { + s.flush() + } +} + +// Query returns the computed qth percentiles value. If s was created with +// NewTargeted, and q is not in the set of quantiles provided a priori, Query +// will return an unspecified result. +func (s *Stream) Query(q float64) float64 { + if !s.flushed() { + // Fast path when there hasn't been enough data for a flush; + // this also yields better accuracy for small sets of data. + l := len(s.b) + if l == 0 { + return 0 + } + i := int(math.Ceil(float64(l) * q)) + if i > 0 { + i -= 1 + } + s.maybeSort() + return s.b[i].Value + } + s.flush() + return s.stream.query(q) +} + +// Merge merges samples into the underlying streams samples. This is handy when +// merging multiple streams from separate threads, database shards, etc. +// +// ATTENTION: This method is broken and does not yield correct results. The +// underlying algorithm is not capable of merging streams correctly. +func (s *Stream) Merge(samples Samples) { + sort.Sort(samples) + s.stream.merge(samples) +} + +// Reset reinitializes and clears the list reusing the samples buffer memory. +func (s *Stream) Reset() { + s.stream.reset() + s.b = s.b[:0] +} + +// Samples returns stream samples held by s. +func (s *Stream) Samples() Samples { + if !s.flushed() { + return s.b + } + s.flush() + return s.stream.samples() +} + +// Count returns the total number of samples observed in the stream +// since initialization. +func (s *Stream) Count() int { + return len(s.b) + s.stream.count() +} + +func (s *Stream) flush() { + s.maybeSort() + s.stream.merge(s.b) + s.b = s.b[:0] +} + +func (s *Stream) maybeSort() { + if !s.sorted { + s.sorted = true + sort.Sort(s.b) + } +} + +func (s *Stream) flushed() bool { + return len(s.stream.l) > 0 +} + +type stream struct { + n float64 + l []Sample + ƒ invariant +} + +func (s *stream) reset() { + s.l = s.l[:0] + s.n = 0 +} + +func (s *stream) insert(v float64) { + s.merge(Samples{{v, 1, 0}}) +} + +func (s *stream) merge(samples Samples) { + // TODO(beorn7): This tries to merge not only individual samples, but + // whole summaries. The paper doesn't mention merging summaries at + // all. Unittests show that the merging is inaccurate. Find out how to + // do merges properly. + var r float64 + i := 0 + for _, sample := range samples { + for ; i < len(s.l); i++ { + c := s.l[i] + if c.Value > sample.Value { + // Insert at position i. + s.l = append(s.l, Sample{}) + copy(s.l[i+1:], s.l[i:]) + s.l[i] = Sample{ + sample.Value, + sample.Width, + math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1), + // TODO(beorn7): How to calculate delta correctly? + } + i++ + goto inserted + } + r += c.Width + } + s.l = append(s.l, Sample{sample.Value, sample.Width, 0}) + i++ + inserted: + s.n += sample.Width + r += sample.Width + } + s.compress() +} + +func (s *stream) count() int { + return int(s.n) +} + +func (s *stream) query(q float64) float64 { + t := math.Ceil(q * s.n) + t += math.Ceil(s.ƒ(s, t) / 2) + p := s.l[0] + var r float64 + for _, c := range s.l[1:] { + r += p.Width + if r+c.Width+c.Delta > t { + return p.Value + } + p = c + } + return p.Value +} + +func (s *stream) compress() { + if len(s.l) < 2 { + return + } + x := s.l[len(s.l)-1] + xi := len(s.l) - 1 + r := s.n - 1 - x.Width + + for i := len(s.l) - 2; i >= 0; i-- { + c := s.l[i] + if c.Width+x.Width+x.Delta <= s.ƒ(s, r) { + x.Width += c.Width + s.l[xi] = x + // Remove element at i. + copy(s.l[i:], s.l[i+1:]) + s.l = s.l[:len(s.l)-1] + xi -= 1 + } else { + x = c + xi = i + } + r -= c.Width + } +} + +func (s *stream) samples() Samples { + samples := make(Samples, len(s.l)) + copy(samples, s.l) + return samples +} diff --git a/vendor/github.com/beorn7/perks/quantile/stream_test.go b/vendor/github.com/beorn7/perks/quantile/stream_test.go new file mode 100644 index 0000000..8551950 --- /dev/null +++ b/vendor/github.com/beorn7/perks/quantile/stream_test.go @@ -0,0 +1,215 @@ +package quantile + +import ( + "math" + "math/rand" + "sort" + "testing" +) + +var ( + Targets = map[float64]float64{ + 0.01: 0.001, + 0.10: 0.01, + 0.50: 0.05, + 0.90: 0.01, + 0.99: 0.001, + } + TargetsSmallEpsilon = map[float64]float64{ + 0.01: 0.0001, + 0.10: 0.001, + 0.50: 0.005, + 0.90: 0.001, + 0.99: 0.0001, + } + LowQuantiles = []float64{0.01, 0.1, 0.5} + HighQuantiles = []float64{0.99, 0.9, 0.5} +) + +const RelativeEpsilon = 0.01 + +func verifyPercsWithAbsoluteEpsilon(t *testing.T, a []float64, s *Stream) { + sort.Float64s(a) + for quantile, epsilon := range Targets { + n := float64(len(a)) + k := int(quantile * n) + if k < 1 { + k = 1 + } + lower := int((quantile - epsilon) * n) + if lower < 1 { + lower = 1 + } + upper := int(math.Ceil((quantile + epsilon) * n)) + if upper > len(a) { + upper = len(a) + } + w, min, max := a[k-1], a[lower-1], a[upper-1] + if g := s.Query(quantile); g < min || g > max { + t.Errorf("q=%f: want %v [%f,%f], got %v", quantile, w, min, max, g) + } + } +} + +func verifyLowPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { + sort.Float64s(a) + for _, qu := range LowQuantiles { + n := float64(len(a)) + k := int(qu * n) + + lowerRank := int((1 - RelativeEpsilon) * qu * n) + upperRank := int(math.Ceil((1 + RelativeEpsilon) * qu * n)) + w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] + if g := s.Query(qu); g < min || g > max { + t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) + } + } +} + +func verifyHighPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { + sort.Float64s(a) + for _, qu := range HighQuantiles { + n := float64(len(a)) + k := int(qu * n) + + lowerRank := int((1 - (1+RelativeEpsilon)*(1-qu)) * n) + upperRank := int(math.Ceil((1 - (1-RelativeEpsilon)*(1-qu)) * n)) + w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] + if g := s.Query(qu); g < min || g > max { + t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) + } + } +} + +func populateStream(s *Stream) []float64 { + a := make([]float64, 0, 1e5+100) + for i := 0; i < cap(a); i++ { + v := rand.NormFloat64() + // Add 5% asymmetric outliers. + if i%20 == 0 { + v = v*v + 1 + } + s.Insert(v) + a = append(a, v) + } + return a +} + +func TestTargetedQuery(t *testing.T) { + rand.Seed(42) + s := NewTargeted(Targets) + a := populateStream(s) + verifyPercsWithAbsoluteEpsilon(t, a, s) +} + +func TestTargetedQuerySmallSampleSize(t *testing.T) { + rand.Seed(42) + s := NewTargeted(TargetsSmallEpsilon) + a := []float64{1, 2, 3, 4, 5} + for _, v := range a { + s.Insert(v) + } + verifyPercsWithAbsoluteEpsilon(t, a, s) + // If not yet flushed, results should be precise: + if !s.flushed() { + for φ, want := range map[float64]float64{ + 0.01: 1, + 0.10: 1, + 0.50: 3, + 0.90: 5, + 0.99: 5, + } { + if got := s.Query(φ); got != want { + t.Errorf("want %f for φ=%f, got %f", want, φ, got) + } + } + } +} + +func TestLowBiasedQuery(t *testing.T) { + rand.Seed(42) + s := NewLowBiased(RelativeEpsilon) + a := populateStream(s) + verifyLowPercsWithRelativeEpsilon(t, a, s) +} + +func TestHighBiasedQuery(t *testing.T) { + rand.Seed(42) + s := NewHighBiased(RelativeEpsilon) + a := populateStream(s) + verifyHighPercsWithRelativeEpsilon(t, a, s) +} + +// BrokenTestTargetedMerge is broken, see Merge doc comment. +func BrokenTestTargetedMerge(t *testing.T) { + rand.Seed(42) + s1 := NewTargeted(Targets) + s2 := NewTargeted(Targets) + a := populateStream(s1) + a = append(a, populateStream(s2)...) + s1.Merge(s2.Samples()) + verifyPercsWithAbsoluteEpsilon(t, a, s1) +} + +// BrokenTestLowBiasedMerge is broken, see Merge doc comment. +func BrokenTestLowBiasedMerge(t *testing.T) { + rand.Seed(42) + s1 := NewLowBiased(RelativeEpsilon) + s2 := NewLowBiased(RelativeEpsilon) + a := populateStream(s1) + a = append(a, populateStream(s2)...) + s1.Merge(s2.Samples()) + verifyLowPercsWithRelativeEpsilon(t, a, s2) +} + +// BrokenTestHighBiasedMerge is broken, see Merge doc comment. +func BrokenTestHighBiasedMerge(t *testing.T) { + rand.Seed(42) + s1 := NewHighBiased(RelativeEpsilon) + s2 := NewHighBiased(RelativeEpsilon) + a := populateStream(s1) + a = append(a, populateStream(s2)...) + s1.Merge(s2.Samples()) + verifyHighPercsWithRelativeEpsilon(t, a, s2) +} + +func TestUncompressed(t *testing.T) { + q := NewTargeted(Targets) + for i := 100; i > 0; i-- { + q.Insert(float64(i)) + } + if g := q.Count(); g != 100 { + t.Errorf("want count 100, got %d", g) + } + // Before compression, Query should have 100% accuracy. + for quantile := range Targets { + w := quantile * 100 + if g := q.Query(quantile); g != w { + t.Errorf("want %f, got %f", w, g) + } + } +} + +func TestUncompressedSamples(t *testing.T) { + q := NewTargeted(map[float64]float64{0.99: 0.001}) + for i := 1; i <= 100; i++ { + q.Insert(float64(i)) + } + if g := q.Samples().Len(); g != 100 { + t.Errorf("want count 100, got %d", g) + } +} + +func TestUncompressedOne(t *testing.T) { + q := NewTargeted(map[float64]float64{0.99: 0.01}) + q.Insert(3.14) + if g := q.Query(0.90); g != 3.14 { + t.Error("want PI, got", g) + } +} + +func TestDefaults(t *testing.T) { + if g := NewTargeted(map[float64]float64{0.99: 0.001}).Query(0.99); g != 0 { + t.Errorf("want 0, got %f", g) + } +} diff --git a/vendor/github.com/boltdb/bolt/.gitignore b/vendor/github.com/boltdb/bolt/.gitignore new file mode 100644 index 0000000..c7bd2b7 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/.gitignore @@ -0,0 +1,4 @@ +*.prof +*.test +*.swp +/bin/ diff --git a/vendor/github.com/boltdb/bolt/LICENSE b/vendor/github.com/boltdb/bolt/LICENSE new file mode 100644 index 0000000..004e77f --- /dev/null +++ b/vendor/github.com/boltdb/bolt/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Ben Johnson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/boltdb/bolt/Makefile b/vendor/github.com/boltdb/bolt/Makefile new file mode 100644 index 0000000..e035e63 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/Makefile @@ -0,0 +1,18 @@ +BRANCH=`git rev-parse --abbrev-ref HEAD` +COMMIT=`git rev-parse --short HEAD` +GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" + +default: build + +race: + @go test -v -race -test.run="TestSimulate_(100op|1000op)" + +# go get github.com/kisielk/errcheck +errcheck: + @errcheck -ignorepkg=bytes -ignore=os:Remove github.com/boltdb/bolt + +test: + @go test -v -cover . + @go test -v ./cmd/bolt + +.PHONY: fmt test diff --git a/vendor/github.com/boltdb/bolt/README.md b/vendor/github.com/boltdb/bolt/README.md new file mode 100644 index 0000000..7d43a15 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/README.md @@ -0,0 +1,916 @@ +Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.2.1-green.svg) +==== + +Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas] +[LMDB project][lmdb]. The goal of the project is to provide a simple, +fast, and reliable database for projects that don't require a full database +server such as Postgres or MySQL. + +Since Bolt is meant to be used as such a low-level piece of functionality, +simplicity is key. The API will be small and only focus on getting values +and setting values. That's it. + +[hyc_symas]: https://twitter.com/hyc_symas +[lmdb]: http://symas.com/mdb/ + +## Project Status + +Bolt is stable, the API is fixed, and the file format is fixed. Full unit +test coverage and randomized black box testing are used to ensure database +consistency and thread safety. Bolt is currently used in high-load production +environments serving databases as large as 1TB. Many companies such as +Shopify and Heroku use Bolt-backed services every day. + +## Table of Contents + +- [Getting Started](#getting-started) + - [Installing](#installing) + - [Opening a database](#opening-a-database) + - [Transactions](#transactions) + - [Read-write transactions](#read-write-transactions) + - [Read-only transactions](#read-only-transactions) + - [Batch read-write transactions](#batch-read-write-transactions) + - [Managing transactions manually](#managing-transactions-manually) + - [Using buckets](#using-buckets) + - [Using key/value pairs](#using-keyvalue-pairs) + - [Autoincrementing integer for the bucket](#autoincrementing-integer-for-the-bucket) + - [Iterating over keys](#iterating-over-keys) + - [Prefix scans](#prefix-scans) + - [Range scans](#range-scans) + - [ForEach()](#foreach) + - [Nested buckets](#nested-buckets) + - [Database backups](#database-backups) + - [Statistics](#statistics) + - [Read-Only Mode](#read-only-mode) + - [Mobile Use (iOS/Android)](#mobile-use-iosandroid) +- [Resources](#resources) +- [Comparison with other databases](#comparison-with-other-databases) + - [Postgres, MySQL, & other relational databases](#postgres-mysql--other-relational-databases) + - [LevelDB, RocksDB](#leveldb-rocksdb) + - [LMDB](#lmdb) +- [Caveats & Limitations](#caveats--limitations) +- [Reading the Source](#reading-the-source) +- [Other Projects Using Bolt](#other-projects-using-bolt) + +## Getting Started + +### Installing + +To start using Bolt, install Go and run `go get`: + +```sh +$ go get github.com/boltdb/bolt/... +``` + +This will retrieve the library and install the `bolt` command line utility into +your `$GOBIN` path. + + +### Opening a database + +The top-level object in Bolt is a `DB`. It is represented as a single file on +your disk and represents a consistent snapshot of your data. + +To open your database, simply use the `bolt.Open()` function: + +```go +package main + +import ( + "log" + + "github.com/boltdb/bolt" +) + +func main() { + // Open the my.db data file in your current directory. + // It will be created if it doesn't exist. + db, err := bolt.Open("my.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + defer db.Close() + + ... +} +``` + +Please note that Bolt obtains a file lock on the data file so multiple processes +cannot open the same database at the same time. Opening an already open Bolt +database will cause it to hang until the other process closes it. To prevent +an indefinite wait you can pass a timeout option to the `Open()` function: + +```go +db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second}) +``` + + +### Transactions + +Bolt allows only one read-write transaction at a time but allows as many +read-only transactions as you want at a time. Each transaction has a consistent +view of the data as it existed when the transaction started. + +Individual transactions and all objects created from them (e.g. buckets, keys) +are not thread safe. To work with data in multiple goroutines you must start +a transaction for each one or use locking to ensure only one goroutine accesses +a transaction at a time. Creating transaction from the `DB` is thread safe. + +Read-only transactions and read-write transactions should not depend on one +another and generally shouldn't be opened simultaneously in the same goroutine. +This can cause a deadlock as the read-write transaction needs to periodically +re-map the data file but it cannot do so while a read-only transaction is open. + + +#### Read-write transactions + +To start a read-write transaction, you can use the `DB.Update()` function: + +```go +err := db.Update(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +Inside the closure, you have a consistent view of the database. You commit the +transaction by returning `nil` at the end. You can also rollback the transaction +at any point by returning an error. All database operations are allowed inside +a read-write transaction. + +Always check the return error as it will report any disk failures that can cause +your transaction to not complete. If you return an error within your closure +it will be passed through. + + +#### Read-only transactions + +To start a read-only transaction, you can use the `DB.View()` function: + +```go +err := db.View(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +You also get a consistent view of the database within this closure, however, +no mutating operations are allowed within a read-only transaction. You can only +retrieve buckets, retrieve values, and copy the database within a read-only +transaction. + + +#### Batch read-write transactions + +Each `DB.Update()` waits for disk to commit the writes. This overhead +can be minimized by combining multiple updates with the `DB.Batch()` +function: + +```go +err := db.Batch(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +Concurrent Batch calls are opportunistically combined into larger +transactions. Batch is only useful when there are multiple goroutines +calling it. + +The trade-off is that `Batch` can call the given +function multiple times, if parts of the transaction fail. The +function must be idempotent and side effects must take effect only +after a successful return from `DB.Batch()`. + +For example: don't display messages from inside the function, instead +set variables in the enclosing scope: + +```go +var id uint64 +err := db.Batch(func(tx *bolt.Tx) error { + // Find last key in bucket, decode as bigendian uint64, increment + // by one, encode back to []byte, and add new key. + ... + id = newValue + return nil +}) +if err != nil { + return ... +} +fmt.Println("Allocated ID %d", id) +``` + + +#### Managing transactions manually + +The `DB.View()` and `DB.Update()` functions are wrappers around the `DB.Begin()` +function. These helper functions will start the transaction, execute a function, +and then safely close your transaction if an error is returned. This is the +recommended way to use Bolt transactions. + +However, sometimes you may want to manually start and end your transactions. +You can use the `DB.Begin()` function directly but **please** be sure to close +the transaction. + +```go +// Start a writable transaction. +tx, err := db.Begin(true) +if err != nil { + return err +} +defer tx.Rollback() + +// Use the transaction... +_, err := tx.CreateBucket([]byte("MyBucket")) +if err != nil { + return err +} + +// Commit the transaction and check for error. +if err := tx.Commit(); err != nil { + return err +} +``` + +The first argument to `DB.Begin()` is a boolean stating if the transaction +should be writable. + + +### Using buckets + +Buckets are collections of key/value pairs within the database. All keys in a +bucket must be unique. You can create a bucket using the `DB.CreateBucket()` +function: + +```go +db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("MyBucket")) + if err != nil { + return fmt.Errorf("create bucket: %s", err) + } + return nil +}) +``` + +You can also create a bucket only if it doesn't exist by using the +`Tx.CreateBucketIfNotExists()` function. It's a common pattern to call this +function for all your top-level buckets after you open your database so you can +guarantee that they exist for future transactions. + +To delete a bucket, simply call the `Tx.DeleteBucket()` function. + + +### Using key/value pairs + +To save a key/value pair to a bucket, use the `Bucket.Put()` function: + +```go +db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("MyBucket")) + err := b.Put([]byte("answer"), []byte("42")) + return err +}) +``` + +This will set the value of the `"answer"` key to `"42"` in the `MyBucket` +bucket. To retrieve this value, we can use the `Bucket.Get()` function: + +```go +db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("MyBucket")) + v := b.Get([]byte("answer")) + fmt.Printf("The answer is: %s\n", v) + return nil +}) +``` + +The `Get()` function does not return an error because its operation is +guaranteed to work (unless there is some kind of system failure). If the key +exists then it will return its byte slice value. If it doesn't exist then it +will return `nil`. It's important to note that you can have a zero-length value +set to a key which is different than the key not existing. + +Use the `Bucket.Delete()` function to delete a key from the bucket. + +Please note that values returned from `Get()` are only valid while the +transaction is open. If you need to use a value outside of the transaction +then you must use `copy()` to copy it to another byte slice. + + +### Autoincrementing integer for the bucket +By using the `NextSequence()` function, you can let Bolt determine a sequence +which can be used as the unique identifier for your key/value pairs. See the +example below. + +```go +// CreateUser saves u to the store. The new user ID is set on u once the data is persisted. +func (s *Store) CreateUser(u *User) error { + return s.db.Update(func(tx *bolt.Tx) error { + // Retrieve the users bucket. + // This should be created when the DB is first opened. + b := tx.Bucket([]byte("users")) + + // Generate ID for the user. + // This returns an error only if the Tx is closed or not writeable. + // That can't happen in an Update() call so I ignore the error check. + id, _ := b.NextSequence() + u.ID = int(id) + + // Marshal user data into bytes. + buf, err := json.Marshal(u) + if err != nil { + return err + } + + // Persist bytes to users bucket. + return b.Put(itob(u.ID), buf) + }) +} + +// itob returns an 8-byte big endian representation of v. +func itob(v int) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(v)) + return b +} + +type User struct { + ID int + ... +} +``` + +### Iterating over keys + +Bolt stores its keys in byte-sorted order within a bucket. This makes sequential +iteration over these keys extremely fast. To iterate over keys we'll use a +`Cursor`: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + b := tx.Bucket([]byte("MyBucket")) + + c := b.Cursor() + + for k, v := c.First(); k != nil; k, v = c.Next() { + fmt.Printf("key=%s, value=%s\n", k, v) + } + + return nil +}) +``` + +The cursor allows you to move to a specific point in the list of keys and move +forward or backward through the keys one at a time. + +The following functions are available on the cursor: + +``` +First() Move to the first key. +Last() Move to the last key. +Seek() Move to a specific key. +Next() Move to the next key. +Prev() Move to the previous key. +``` + +Each of those functions has a return signature of `(key []byte, value []byte)`. +When you have iterated to the end of the cursor then `Next()` will return a +`nil` key. You must seek to a position using `First()`, `Last()`, or `Seek()` +before calling `Next()` or `Prev()`. If you do not seek to a position then +these functions will return a `nil` key. + +During iteration, if the key is non-`nil` but the value is `nil`, that means +the key refers to a bucket rather than a value. Use `Bucket.Bucket()` to +access the sub-bucket. + + +#### Prefix scans + +To iterate over a key prefix, you can combine `Seek()` and `bytes.HasPrefix()`: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + c := tx.Bucket([]byte("MyBucket")).Cursor() + + prefix := []byte("1234") + for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { + fmt.Printf("key=%s, value=%s\n", k, v) + } + + return nil +}) +``` + +#### Range scans + +Another common use case is scanning over a range such as a time range. If you +use a sortable time encoding such as RFC3339 then you can query a specific +date range like this: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume our events bucket exists and has RFC3339 encoded time keys. + c := tx.Bucket([]byte("Events")).Cursor() + + // Our time range spans the 90's decade. + min := []byte("1990-01-01T00:00:00Z") + max := []byte("2000-01-01T00:00:00Z") + + // Iterate over the 90's. + for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; k, v = c.Next() { + fmt.Printf("%s: %s\n", k, v) + } + + return nil +}) +``` + +Note that, while RFC3339 is sortable, the Golang implementation of RFC3339Nano does not use a fixed number of digits after the decimal point and is therefore not sortable. + + +#### ForEach() + +You can also use the function `ForEach()` if you know you'll be iterating over +all the keys in a bucket: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + b := tx.Bucket([]byte("MyBucket")) + + b.ForEach(func(k, v []byte) error { + fmt.Printf("key=%s, value=%s\n", k, v) + return nil + }) + return nil +}) +``` + +Please note that keys and values in `ForEach()` are only valid while +the transaction is open. If you need to use a key or value outside of +the transaction, you must use `copy()` to copy it to another byte +slice. + +### Nested buckets + +You can also store a bucket in a key to create nested buckets. The API is the +same as the bucket management API on the `DB` object: + +```go +func (*Bucket) CreateBucket(key []byte) (*Bucket, error) +func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) +func (*Bucket) DeleteBucket(key []byte) error +``` + +Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings. + +```go + +// createUser creates a new user in the given account. +func createUser(accountID int, u *User) error { + // Start the transaction. + tx, err := db.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + // Retrieve the root bucket for the account. + // Assume this has already been created when the account was set up. + root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10))) + + // Setup the users bucket. + bkt, err := root.CreateBucketIfNotExists([]byte("USERS")) + if err != nil { + return err + } + + // Generate an ID for the new user. + userID, err := bkt.NextSequence() + if err != nil { + return err + } + u.ID = userID + + // Marshal and save the encoded user. + if buf, err := json.Marshal(u); err != nil { + return err + } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil { + return err + } + + // Commit the transaction. + if err := tx.Commit(); err != nil { + return err + } + + return nil +} + +``` + + + + +### Database backups + +Bolt is a single file so it's easy to backup. You can use the `Tx.WriteTo()` +function to write a consistent view of the database to a writer. If you call +this from a read-only transaction, it will perform a hot backup and not block +your other database reads and writes. + +By default, it will use a regular file handle which will utilize the operating +system's page cache. See the [`Tx`](https://godoc.org/github.com/boltdb/bolt#Tx) +documentation for information about optimizing for larger-than-RAM datasets. + +One common use case is to backup over HTTP so you can use tools like `cURL` to +do database backups: + +```go +func BackupHandleFunc(w http.ResponseWriter, req *http.Request) { + err := db.View(func(tx *bolt.Tx) error { + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", `attachment; filename="my.db"`) + w.Header().Set("Content-Length", strconv.Itoa(int(tx.Size()))) + _, err := tx.WriteTo(w) + return err + }) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} +``` + +Then you can backup using this command: + +```sh +$ curl http://localhost/backup > my.db +``` + +Or you can open your browser to `http://localhost/backup` and it will download +automatically. + +If you want to backup to another file you can use the `Tx.CopyFile()` helper +function. + + +### Statistics + +The database keeps a running count of many of the internal operations it +performs so you can better understand what's going on. By grabbing a snapshot +of these stats at two points in time we can see what operations were performed +in that time range. + +For example, we could start a goroutine to log stats every 10 seconds: + +```go +go func() { + // Grab the initial stats. + prev := db.Stats() + + for { + // Wait for 10s. + time.Sleep(10 * time.Second) + + // Grab the current stats and diff them. + stats := db.Stats() + diff := stats.Sub(&prev) + + // Encode stats to JSON and print to STDERR. + json.NewEncoder(os.Stderr).Encode(diff) + + // Save stats for the next loop. + prev = stats + } +}() +``` + +It's also useful to pipe these stats to a service such as statsd for monitoring +or to provide an HTTP endpoint that will perform a fixed-length sample. + + +### Read-Only Mode + +Sometimes it is useful to create a shared, read-only Bolt database. To this, +set the `Options.ReadOnly` flag when opening your database. Read-only mode +uses a shared lock to allow multiple processes to read from the database but +it will block any processes from opening the database in read-write mode. + +```go +db, err := bolt.Open("my.db", 0666, &bolt.Options{ReadOnly: true}) +if err != nil { + log.Fatal(err) +} +``` + +### Mobile Use (iOS/Android) + +Bolt is able to run on mobile devices by leveraging the binding feature of the +[gomobile](https://github.com/golang/mobile) tool. Create a struct that will +contain your database logic and a reference to a `*bolt.DB` with a initializing +constructor that takes in a filepath where the database file will be stored. +Neither Android nor iOS require extra permissions or cleanup from using this method. + +```go +func NewBoltDB(filepath string) *BoltDB { + db, err := bolt.Open(filepath+"/demo.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + + return &BoltDB{db} +} + +type BoltDB struct { + db *bolt.DB + ... +} + +func (b *BoltDB) Path() string { + return b.db.Path() +} + +func (b *BoltDB) Close() { + b.db.Close() +} +``` + +Database logic should be defined as methods on this wrapper struct. + +To initialize this struct from the native language (both platforms now sync +their local storage to the cloud. These snippets disable that functionality for the +database file): + +#### Android + +```java +String path; +if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.LOLLIPOP){ + path = getNoBackupFilesDir().getAbsolutePath(); +} else{ + path = getFilesDir().getAbsolutePath(); +} +Boltmobiledemo.BoltDB boltDB = Boltmobiledemo.NewBoltDB(path) +``` + +#### iOS + +```objc +- (void)demo { + NSString* path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, + NSUserDomainMask, + YES) objectAtIndex:0]; + GoBoltmobiledemoBoltDB * demo = GoBoltmobiledemoNewBoltDB(path); + [self addSkipBackupAttributeToItemAtPath:demo.path]; + //Some DB Logic would go here + [demo close]; +} + +- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString +{ + NSURL* URL= [NSURL fileURLWithPath: filePathString]; + assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]); + + NSError *error = nil; + BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES] + forKey: NSURLIsExcludedFromBackupKey error: &error]; + if(!success){ + NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error); + } + return success; +} + +``` + +## Resources + +For more information on getting started with Bolt, check out the following articles: + +* [Intro to BoltDB: Painless Performant Persistence](http://npf.io/2014/07/intro-to-boltdb-painless-performant-persistence/) by [Nate Finch](https://github.com/natefinch). +* [Bolt -- an embedded key/value database for Go](https://www.progville.com/go/bolt-embedded-db-golang/) by Progville + + +## Comparison with other databases + +### Postgres, MySQL, & other relational databases + +Relational databases structure data into rows and are only accessible through +the use of SQL. This approach provides flexibility in how you store and query +your data but also incurs overhead in parsing and planning SQL statements. Bolt +accesses all data by a byte slice key. This makes Bolt fast to read and write +data by key but provides no built-in support for joining values together. + +Most relational databases (with the exception of SQLite) are standalone servers +that run separately from your application. This gives your systems +flexibility to connect multiple application servers to a single database +server but also adds overhead in serializing and transporting data over the +network. Bolt runs as a library included in your application so all data access +has to go through your application's process. This brings data closer to your +application but limits multi-process access to the data. + + +### LevelDB, RocksDB + +LevelDB and its derivatives (RocksDB, HyperLevelDB) are similar to Bolt in that +they are libraries bundled into the application, however, their underlying +structure is a log-structured merge-tree (LSM tree). An LSM tree optimizes +random writes by using a write ahead log and multi-tiered, sorted files called +SSTables. Bolt uses a B+tree internally and only a single file. Both approaches +have trade-offs. + +If you require a high random write throughput (>10,000 w/sec) or you need to use +spinning disks then LevelDB could be a good choice. If your application is +read-heavy or does a lot of range scans then Bolt could be a good choice. + +One other important consideration is that LevelDB does not have transactions. +It supports batch writing of key/values pairs and it supports read snapshots +but it will not give you the ability to do a compare-and-swap operation safely. +Bolt supports fully serializable ACID transactions. + + +### LMDB + +Bolt was originally a port of LMDB so it is architecturally similar. Both use +a B+tree, have ACID semantics with fully serializable transactions, and support +lock-free MVCC using a single writer and multiple readers. + +The two projects have somewhat diverged. LMDB heavily focuses on raw performance +while Bolt has focused on simplicity and ease of use. For example, LMDB allows +several unsafe actions such as direct writes for the sake of performance. Bolt +opts to disallow actions which can leave the database in a corrupted state. The +only exception to this in Bolt is `DB.NoSync`. + +There are also a few differences in API. LMDB requires a maximum mmap size when +opening an `mdb_env` whereas Bolt will handle incremental mmap resizing +automatically. LMDB overloads the getter and setter functions with multiple +flags whereas Bolt splits these specialized cases into their own functions. + + +## Caveats & Limitations + +It's important to pick the right tool for the job and Bolt is no exception. +Here are a few things to note when evaluating and using Bolt: + +* Bolt is good for read intensive workloads. Sequential write performance is + also fast but random writes can be slow. You can use `DB.Batch()` or add a + write-ahead log to help mitigate this issue. + +* Bolt uses a B+tree internally so there can be a lot of random page access. + SSDs provide a significant performance boost over spinning disks. + +* Try to avoid long running read transactions. Bolt uses copy-on-write so + old pages cannot be reclaimed while an old transaction is using them. + +* Byte slices returned from Bolt are only valid during a transaction. Once the + transaction has been committed or rolled back then the memory they point to + can be reused by a new page or can be unmapped from virtual memory and you'll + see an `unexpected fault address` panic when accessing it. + +* Bolt uses an exclusive write lock on the database file so it cannot be + shared by multiple processes. + +* Be careful when using `Bucket.FillPercent`. Setting a high fill percent for + buckets that have random inserts will cause your database to have very poor + page utilization. + +* Use larger buckets in general. Smaller buckets causes poor page utilization + once they become larger than the page size (typically 4KB). + +* Bulk loading a lot of random writes into a new bucket can be slow as the + page will not split until the transaction is committed. Randomly inserting + more than 100,000 key/value pairs into a single new bucket in a single + transaction is not advised. + +* Bolt uses a memory-mapped file so the underlying operating system handles the + caching of the data. Typically, the OS will cache as much of the file as it + can in memory and will release memory as needed to other processes. This means + that Bolt can show very high memory usage when working with large databases. + However, this is expected and the OS will release memory as needed. Bolt can + handle databases much larger than the available physical RAM, provided its + memory-map fits in the process virtual address space. It may be problematic + on 32-bits systems. + +* The data structures in the Bolt database are memory mapped so the data file + will be endian specific. This means that you cannot copy a Bolt file from a + little endian machine to a big endian machine and have it work. For most + users this is not a concern since most modern CPUs are little endian. + +* Because of the way pages are laid out on disk, Bolt cannot truncate data files + and return free pages back to the disk. Instead, Bolt maintains a free list + of unused pages within its data file. These free pages can be reused by later + transactions. This works well for many use cases as databases generally tend + to grow. However, it's important to note that deleting large chunks of data + will not allow you to reclaim that space on disk. + + For more information on page allocation, [see this comment][page-allocation]. + +[page-allocation]: https://github.com/boltdb/bolt/issues/308#issuecomment-74811638 + + +## Reading the Source + +Bolt is a relatively small code base (<3KLOC) for an embedded, serializable, +transactional key/value database so it can be a good starting point for people +interested in how databases work. + +The best places to start are the main entry points into Bolt: + +- `Open()` - Initializes the reference to the database. It's responsible for + creating the database if it doesn't exist, obtaining an exclusive lock on the + file, reading the meta pages, & memory-mapping the file. + +- `DB.Begin()` - Starts a read-only or read-write transaction depending on the + value of the `writable` argument. This requires briefly obtaining the "meta" + lock to keep track of open transactions. Only one read-write transaction can + exist at a time so the "rwlock" is acquired during the life of a read-write + transaction. + +- `Bucket.Put()` - Writes a key/value pair into a bucket. After validating the + arguments, a cursor is used to traverse the B+tree to the page and position + where they key & value will be written. Once the position is found, the bucket + materializes the underlying page and the page's parent pages into memory as + "nodes". These nodes are where mutations occur during read-write transactions. + These changes get flushed to disk during commit. + +- `Bucket.Get()` - Retrieves a key/value pair from a bucket. This uses a cursor + to move to the page & position of a key/value pair. During a read-only + transaction, the key and value data is returned as a direct reference to the + underlying mmap file so there's no allocation overhead. For read-write + transactions, this data may reference the mmap file or one of the in-memory + node values. + +- `Cursor` - This object is simply for traversing the B+tree of on-disk pages + or in-memory nodes. It can seek to a specific key, move to the first or last + value, or it can move forward or backward. The cursor handles the movement up + and down the B+tree transparently to the end user. + +- `Tx.Commit()` - Converts the in-memory dirty nodes and the list of free pages + into pages to be written to disk. Writing to disk then occurs in two phases. + First, the dirty pages are written to disk and an `fsync()` occurs. Second, a + new meta page with an incremented transaction ID is written and another + `fsync()` occurs. This two phase write ensures that partially written data + pages are ignored in the event of a crash since the meta page pointing to them + is never written. Partially written meta pages are invalidated because they + are written with a checksum. + +If you have additional notes that could be helpful for others, please submit +them via pull request. + + +## Other Projects Using Bolt + +Below is a list of public, open source projects that use Bolt: + +* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. +* [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. +* [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside. +* [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. +* [Skybox Analytics](https://github.com/skybox/skybox) - A standalone funnel analysis tool for web analytics. +* [Scuttlebutt](https://github.com/benbjohnson/scuttlebutt) - Uses Bolt to store and process all Twitter mentions of GitHub projects. +* [Wiki](https://github.com/peterhellberg/wiki) - A tiny wiki using Goji, BoltDB and Blackfriday. +* [ChainStore](https://github.com/pressly/chainstore) - Simple key-value interface to a variety of storage engines organized as a chain of operations. +* [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite. +* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin". +* [event-shuttle](https://github.com/sclasen/event-shuttle) - A Unix system service to collect and reliably deliver messages to Kafka. +* [ipxed](https://github.com/kelseyhightower/ipxed) - Web interface and api for ipxed. +* [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt. +* [photosite/session](https://godoc.org/bitbucket.org/kardianos/photosite/session) - Sessions for a photo viewing site. +* [LedisDB](https://github.com/siddontang/ledisdb) - A high performance NoSQL, using Bolt as optional storage. +* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters. +* [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. +* [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. +* [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server. +* [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. +* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics. +* [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data. +* [Prometheus Annotation Server](https://github.com/oliver006/prom_annotation_server) - Annotation server for PromDash & Prometheus service monitoring system. +* [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware. +* [Kala](https://github.com/ajvb/kala) - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs. +* [drive](https://github.com/odeke-em/drive) - drive is an unofficial Google Drive command line client for \*NIX operating systems. +* [stow](https://github.com/djherbis/stow) - a persistence manager for objects + backed by boltdb. +* [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining + simple tx and key scans. +* [mbuckets](https://github.com/abhigupta912/mbuckets) - A Bolt wrapper that allows easy operations on multi level (nested) buckets. +* [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service +* [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service. +* [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. +* [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores. +* [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB. +* [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB. +* [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings. +* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend. +* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. +* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter. +* [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development. +* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains +* [bolter](https://github.com/hasit/bolter) - Command-line app for viewing BoltDB file in your terminal. +* [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet. +* [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency. +* [Ironsmith](https://github.com/timshannon/ironsmith) - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies +* [BoltHold](https://github.com/timshannon/bolthold) - An embeddable NoSQL store for Go types built on BoltDB +* [Ponzu CMS](https://ponzu-cms.org) - Headless CMS + automatic JSON API with auto-HTTPS, HTTP/2 Server Push, and flexible server framework. + +If you are using Bolt in a project please send a pull request to add it to the list. diff --git a/vendor/github.com/boltdb/bolt/appveyor.yml b/vendor/github.com/boltdb/bolt/appveyor.yml new file mode 100644 index 0000000..6e26e94 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/appveyor.yml @@ -0,0 +1,18 @@ +version: "{build}" + +os: Windows Server 2012 R2 + +clone_folder: c:\gopath\src\github.com\boltdb\bolt + +environment: + GOPATH: c:\gopath + +install: + - echo %PATH% + - echo %GOPATH% + - go version + - go env + - go get -v -t ./... + +build_script: + - go test -v ./... diff --git a/vendor/github.com/boltdb/bolt/bolt_386.go b/vendor/github.com/boltdb/bolt/bolt_386.go new file mode 100644 index 0000000..820d533 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_386.go @@ -0,0 +1,10 @@ +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x7FFFFFFF // 2GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_amd64.go b/vendor/github.com/boltdb/bolt/bolt_amd64.go new file mode 100644 index 0000000..98fafdb --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_amd64.go @@ -0,0 +1,10 @@ +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_arm.go b/vendor/github.com/boltdb/bolt/bolt_arm.go new file mode 100644 index 0000000..7e5cb4b --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_arm.go @@ -0,0 +1,28 @@ +package bolt + +import "unsafe" + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x7FFFFFFF // 2GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned bool + +func init() { + // Simple check to see whether this arch handles unaligned load/stores + // correctly. + + // ARM9 and older devices require load/stores to be from/to aligned + // addresses. If not, the lower 2 bits are cleared and that address is + // read in a jumbled up order. + + // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html + + raw := [6]byte{0xfe, 0xef, 0x11, 0x22, 0x22, 0x11} + val := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&raw)) + 2)) + + brokenUnaligned = val != 0x11222211 +} diff --git a/vendor/github.com/boltdb/bolt/bolt_arm64.go b/vendor/github.com/boltdb/bolt/bolt_arm64.go new file mode 100644 index 0000000..b26d84f --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_arm64.go @@ -0,0 +1,12 @@ +// +build arm64 + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_linux.go b/vendor/github.com/boltdb/bolt/bolt_linux.go new file mode 100644 index 0000000..2b67666 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_linux.go @@ -0,0 +1,10 @@ +package bolt + +import ( + "syscall" +) + +// fdatasync flushes written data to a file descriptor. +func fdatasync(db *DB) error { + return syscall.Fdatasync(int(db.file.Fd())) +} diff --git a/vendor/github.com/boltdb/bolt/bolt_openbsd.go b/vendor/github.com/boltdb/bolt/bolt_openbsd.go new file mode 100644 index 0000000..7058c3d --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_openbsd.go @@ -0,0 +1,27 @@ +package bolt + +import ( + "syscall" + "unsafe" +) + +const ( + msAsync = 1 << iota // perform asynchronous writes + msSync // perform synchronous writes + msInvalidate // invalidate cached data +) + +func msync(db *DB) error { + _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate) + if errno != 0 { + return errno + } + return nil +} + +func fdatasync(db *DB) error { + if db.data != nil { + return msync(db) + } + return db.file.Sync() +} diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc.go b/vendor/github.com/boltdb/bolt/bolt_ppc.go new file mode 100644 index 0000000..645ddc3 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_ppc.go @@ -0,0 +1,9 @@ +// +build ppc + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x7FFFFFFF // 2GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0xFFFFFFF diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64.go b/vendor/github.com/boltdb/bolt/bolt_ppc64.go new file mode 100644 index 0000000..9331d97 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64.go @@ -0,0 +1,12 @@ +// +build ppc64 + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go new file mode 100644 index 0000000..8c143bc --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go @@ -0,0 +1,12 @@ +// +build ppc64le + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_s390x.go b/vendor/github.com/boltdb/bolt/bolt_s390x.go new file mode 100644 index 0000000..d7c39af --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_s390x.go @@ -0,0 +1,12 @@ +// +build s390x + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_unix.go b/vendor/github.com/boltdb/bolt/bolt_unix.go new file mode 100644 index 0000000..cad62dd --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_unix.go @@ -0,0 +1,89 @@ +// +build !windows,!plan9,!solaris + +package bolt + +import ( + "fmt" + "os" + "syscall" + "time" + "unsafe" +) + +// flock acquires an advisory lock on a file descriptor. +func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { + var t time.Time + for { + // If we're beyond our timeout then return an error. + // This can only occur after we've attempted a flock once. + if t.IsZero() { + t = time.Now() + } else if timeout > 0 && time.Since(t) > timeout { + return ErrTimeout + } + flag := syscall.LOCK_SH + if exclusive { + flag = syscall.LOCK_EX + } + + // Otherwise attempt to obtain an exclusive lock. + err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB) + if err == nil { + return nil + } else if err != syscall.EWOULDBLOCK { + return err + } + + // Wait for a bit and try again. + time.Sleep(50 * time.Millisecond) + } +} + +// funlock releases an advisory lock on a file descriptor. +func funlock(db *DB) error { + return syscall.Flock(int(db.file.Fd()), syscall.LOCK_UN) +} + +// mmap memory maps a DB's data file. +func mmap(db *DB, sz int) error { + // Map the data file to memory. + b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) + if err != nil { + return err + } + + // Advise the kernel that the mmap is accessed randomly. + if err := madvise(b, syscall.MADV_RANDOM); err != nil { + return fmt.Errorf("madvise: %s", err) + } + + // Save the original byte slice and convert to a byte array pointer. + db.dataref = b + db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) + db.datasz = sz + return nil +} + +// munmap unmaps a DB's data file from memory. +func munmap(db *DB) error { + // Ignore the unmap if we have no mapped data. + if db.dataref == nil { + return nil + } + + // Unmap using the original byte slice. + err := syscall.Munmap(db.dataref) + db.dataref = nil + db.data = nil + db.datasz = 0 + return err +} + +// NOTE: This function is copied from stdlib because it is not available on darwin. +func madvise(b []byte, advice int) (err error) { + _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice)) + if e1 != 0 { + err = e1 + } + return +} diff --git a/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go b/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go new file mode 100644 index 0000000..307bf2b --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go @@ -0,0 +1,90 @@ +package bolt + +import ( + "fmt" + "os" + "syscall" + "time" + "unsafe" + + "golang.org/x/sys/unix" +) + +// flock acquires an advisory lock on a file descriptor. +func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { + var t time.Time + for { + // If we're beyond our timeout then return an error. + // This can only occur after we've attempted a flock once. + if t.IsZero() { + t = time.Now() + } else if timeout > 0 && time.Since(t) > timeout { + return ErrTimeout + } + var lock syscall.Flock_t + lock.Start = 0 + lock.Len = 0 + lock.Pid = 0 + lock.Whence = 0 + lock.Pid = 0 + if exclusive { + lock.Type = syscall.F_WRLCK + } else { + lock.Type = syscall.F_RDLCK + } + err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock) + if err == nil { + return nil + } else if err != syscall.EAGAIN { + return err + } + + // Wait for a bit and try again. + time.Sleep(50 * time.Millisecond) + } +} + +// funlock releases an advisory lock on a file descriptor. +func funlock(db *DB) error { + var lock syscall.Flock_t + lock.Start = 0 + lock.Len = 0 + lock.Type = syscall.F_UNLCK + lock.Whence = 0 + return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock) +} + +// mmap memory maps a DB's data file. +func mmap(db *DB, sz int) error { + // Map the data file to memory. + b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) + if err != nil { + return err + } + + // Advise the kernel that the mmap is accessed randomly. + if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { + return fmt.Errorf("madvise: %s", err) + } + + // Save the original byte slice and convert to a byte array pointer. + db.dataref = b + db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) + db.datasz = sz + return nil +} + +// munmap unmaps a DB's data file from memory. +func munmap(db *DB) error { + // Ignore the unmap if we have no mapped data. + if db.dataref == nil { + return nil + } + + // Unmap using the original byte slice. + err := unix.Munmap(db.dataref) + db.dataref = nil + db.data = nil + db.datasz = 0 + return err +} diff --git a/vendor/github.com/boltdb/bolt/bolt_windows.go b/vendor/github.com/boltdb/bolt/bolt_windows.go new file mode 100644 index 0000000..b00fb07 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_windows.go @@ -0,0 +1,144 @@ +package bolt + +import ( + "fmt" + "os" + "syscall" + "time" + "unsafe" +) + +// LockFileEx code derived from golang build filemutex_windows.go @ v1.5.1 +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procLockFileEx = modkernel32.NewProc("LockFileEx") + procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") +) + +const ( + lockExt = ".lock" + + // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx + flagLockExclusive = 2 + flagLockFailImmediately = 1 + + // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx + errLockViolation syscall.Errno = 0x21 +) + +func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { + r, _, err := procLockFileEx.Call(uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol))) + if r == 0 { + return err + } + return nil +} + +func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { + r, _, err := procUnlockFileEx.Call(uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0) + if r == 0 { + return err + } + return nil +} + +// fdatasync flushes written data to a file descriptor. +func fdatasync(db *DB) error { + return db.file.Sync() +} + +// flock acquires an advisory lock on a file descriptor. +func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { + // Create a separate lock file on windows because a process + // cannot share an exclusive lock on the same file. This is + // needed during Tx.WriteTo(). + f, err := os.OpenFile(db.path+lockExt, os.O_CREATE, mode) + if err != nil { + return err + } + db.lockfile = f + + var t time.Time + for { + // If we're beyond our timeout then return an error. + // This can only occur after we've attempted a flock once. + if t.IsZero() { + t = time.Now() + } else if timeout > 0 && time.Since(t) > timeout { + return ErrTimeout + } + + var flag uint32 = flagLockFailImmediately + if exclusive { + flag |= flagLockExclusive + } + + err := lockFileEx(syscall.Handle(db.lockfile.Fd()), flag, 0, 1, 0, &syscall.Overlapped{}) + if err == nil { + return nil + } else if err != errLockViolation { + return err + } + + // Wait for a bit and try again. + time.Sleep(50 * time.Millisecond) + } +} + +// funlock releases an advisory lock on a file descriptor. +func funlock(db *DB) error { + err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{}) + db.lockfile.Close() + os.Remove(db.path + lockExt) + return err +} + +// mmap memory maps a DB's data file. +// Based on: https://github.com/edsrzf/mmap-go +func mmap(db *DB, sz int) error { + if !db.readOnly { + // Truncate the database to the size of the mmap. + if err := db.file.Truncate(int64(sz)); err != nil { + return fmt.Errorf("truncate: %s", err) + } + } + + // Open a file mapping handle. + sizelo := uint32(sz >> 32) + sizehi := uint32(sz) & 0xffffffff + h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil) + if h == 0 { + return os.NewSyscallError("CreateFileMapping", errno) + } + + // Create the memory map. + addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz)) + if addr == 0 { + return os.NewSyscallError("MapViewOfFile", errno) + } + + // Close mapping handle. + if err := syscall.CloseHandle(syscall.Handle(h)); err != nil { + return os.NewSyscallError("CloseHandle", err) + } + + // Convert to a byte array. + db.data = ((*[maxMapSize]byte)(unsafe.Pointer(addr))) + db.datasz = sz + + return nil +} + +// munmap unmaps a pointer from a file. +// Based on: https://github.com/edsrzf/mmap-go +func munmap(db *DB) error { + if db.data == nil { + return nil + } + + addr := (uintptr)(unsafe.Pointer(&db.data[0])) + if err := syscall.UnmapViewOfFile(addr); err != nil { + return os.NewSyscallError("UnmapViewOfFile", err) + } + return nil +} diff --git a/vendor/github.com/boltdb/bolt/boltsync_unix.go b/vendor/github.com/boltdb/bolt/boltsync_unix.go new file mode 100644 index 0000000..f504425 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/boltsync_unix.go @@ -0,0 +1,8 @@ +// +build !windows,!plan9,!linux,!openbsd + +package bolt + +// fdatasync flushes written data to a file descriptor. +func fdatasync(db *DB) error { + return db.file.Sync() +} diff --git a/vendor/github.com/boltdb/bolt/bucket.go b/vendor/github.com/boltdb/bolt/bucket.go new file mode 100644 index 0000000..0c5bf27 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bucket.go @@ -0,0 +1,777 @@ +package bolt + +import ( + "bytes" + "fmt" + "unsafe" +) + +const ( + // MaxKeySize is the maximum length of a key, in bytes. + MaxKeySize = 32768 + + // MaxValueSize is the maximum length of a value, in bytes. + MaxValueSize = (1 << 31) - 2 +) + +const ( + maxUint = ^uint(0) + minUint = 0 + maxInt = int(^uint(0) >> 1) + minInt = -maxInt - 1 +) + +const bucketHeaderSize = int(unsafe.Sizeof(bucket{})) + +const ( + minFillPercent = 0.1 + maxFillPercent = 1.0 +) + +// DefaultFillPercent is the percentage that split pages are filled. +// This value can be changed by setting Bucket.FillPercent. +const DefaultFillPercent = 0.5 + +// Bucket represents a collection of key/value pairs inside the database. +type Bucket struct { + *bucket + tx *Tx // the associated transaction + buckets map[string]*Bucket // subbucket cache + page *page // inline page reference + rootNode *node // materialized node for the root page. + nodes map[pgid]*node // node cache + + // Sets the threshold for filling nodes when they split. By default, + // the bucket will fill to 50% but it can be useful to increase this + // amount if you know that your write workloads are mostly append-only. + // + // This is non-persisted across transactions so it must be set in every Tx. + FillPercent float64 +} + +// bucket represents the on-file representation of a bucket. +// This is stored as the "value" of a bucket key. If the bucket is small enough, +// then its root page can be stored inline in the "value", after the bucket +// header. In the case of inline buckets, the "root" will be 0. +type bucket struct { + root pgid // page id of the bucket's root-level page + sequence uint64 // monotonically incrementing, used by NextSequence() +} + +// newBucket returns a new bucket associated with a transaction. +func newBucket(tx *Tx) Bucket { + var b = Bucket{tx: tx, FillPercent: DefaultFillPercent} + if tx.writable { + b.buckets = make(map[string]*Bucket) + b.nodes = make(map[pgid]*node) + } + return b +} + +// Tx returns the tx of the bucket. +func (b *Bucket) Tx() *Tx { + return b.tx +} + +// Root returns the root of the bucket. +func (b *Bucket) Root() pgid { + return b.root +} + +// Writable returns whether the bucket is writable. +func (b *Bucket) Writable() bool { + return b.tx.writable +} + +// Cursor creates a cursor associated with the bucket. +// The cursor is only valid as long as the transaction is open. +// Do not use a cursor after the transaction is closed. +func (b *Bucket) Cursor() *Cursor { + // Update transaction statistics. + b.tx.stats.CursorCount++ + + // Allocate and return a cursor. + return &Cursor{ + bucket: b, + stack: make([]elemRef, 0), + } +} + +// Bucket retrieves a nested bucket by name. +// Returns nil if the bucket does not exist. +// The bucket instance is only valid for the lifetime of the transaction. +func (b *Bucket) Bucket(name []byte) *Bucket { + if b.buckets != nil { + if child := b.buckets[string(name)]; child != nil { + return child + } + } + + // Move cursor to key. + c := b.Cursor() + k, v, flags := c.seek(name) + + // Return nil if the key doesn't exist or it is not a bucket. + if !bytes.Equal(name, k) || (flags&bucketLeafFlag) == 0 { + return nil + } + + // Otherwise create a bucket and cache it. + var child = b.openBucket(v) + if b.buckets != nil { + b.buckets[string(name)] = child + } + + return child +} + +// Helper method that re-interprets a sub-bucket value +// from a parent into a Bucket +func (b *Bucket) openBucket(value []byte) *Bucket { + var child = newBucket(b.tx) + + // If unaligned load/stores are broken on this arch and value is + // unaligned simply clone to an aligned byte array. + unaligned := brokenUnaligned && uintptr(unsafe.Pointer(&value[0]))&3 != 0 + + if unaligned { + value = cloneBytes(value) + } + + // If this is a writable transaction then we need to copy the bucket entry. + // Read-only transactions can point directly at the mmap entry. + if b.tx.writable && !unaligned { + child.bucket = &bucket{} + *child.bucket = *(*bucket)(unsafe.Pointer(&value[0])) + } else { + child.bucket = (*bucket)(unsafe.Pointer(&value[0])) + } + + // Save a reference to the inline page if the bucket is inline. + if child.root == 0 { + child.page = (*page)(unsafe.Pointer(&value[bucketHeaderSize])) + } + + return &child +} + +// CreateBucket creates a new bucket at the given key and returns the new bucket. +// Returns an error if the key already exists, if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { + if b.tx.db == nil { + return nil, ErrTxClosed + } else if !b.tx.writable { + return nil, ErrTxNotWritable + } else if len(key) == 0 { + return nil, ErrBucketNameRequired + } + + // Move cursor to correct position. + c := b.Cursor() + k, _, flags := c.seek(key) + + // Return an error if there is an existing key. + if bytes.Equal(key, k) { + if (flags & bucketLeafFlag) != 0 { + return nil, ErrBucketExists + } + return nil, ErrIncompatibleValue + } + + // Create empty, inline bucket. + var bucket = Bucket{ + bucket: &bucket{}, + rootNode: &node{isLeaf: true}, + FillPercent: DefaultFillPercent, + } + var value = bucket.write() + + // Insert into node. + key = cloneBytes(key) + c.node().put(key, key, value, 0, bucketLeafFlag) + + // Since subbuckets are not allowed on inline buckets, we need to + // dereference the inline page, if it exists. This will cause the bucket + // to be treated as a regular, non-inline bucket for the rest of the tx. + b.page = nil + + return b.Bucket(key), nil +} + +// CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it. +// Returns an error if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) { + child, err := b.CreateBucket(key) + if err == ErrBucketExists { + return b.Bucket(key), nil + } else if err != nil { + return nil, err + } + return child, nil +} + +// DeleteBucket deletes a bucket at the given key. +// Returns an error if the bucket does not exists, or if the key represents a non-bucket value. +func (b *Bucket) DeleteBucket(key []byte) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Move cursor to correct position. + c := b.Cursor() + k, _, flags := c.seek(key) + + // Return an error if bucket doesn't exist or is not a bucket. + if !bytes.Equal(key, k) { + return ErrBucketNotFound + } else if (flags & bucketLeafFlag) == 0 { + return ErrIncompatibleValue + } + + // Recursively delete all child buckets. + child := b.Bucket(key) + err := child.ForEach(func(k, v []byte) error { + if v == nil { + if err := child.DeleteBucket(k); err != nil { + return fmt.Errorf("delete bucket: %s", err) + } + } + return nil + }) + if err != nil { + return err + } + + // Remove cached copy. + delete(b.buckets, string(key)) + + // Release all bucket pages to freelist. + child.nodes = nil + child.rootNode = nil + child.free() + + // Delete the node if we have a matching key. + c.node().del(key) + + return nil +} + +// Get retrieves the value for a key in the bucket. +// Returns a nil value if the key does not exist or if the key is a nested bucket. +// The returned value is only valid for the life of the transaction. +func (b *Bucket) Get(key []byte) []byte { + k, v, flags := b.Cursor().seek(key) + + // Return nil if this is a bucket. + if (flags & bucketLeafFlag) != 0 { + return nil + } + + // If our target node isn't the same key as what's passed in then return nil. + if !bytes.Equal(key, k) { + return nil + } + return v +} + +// Put sets the value for a key in the bucket. +// If the key exist then its previous value will be overwritten. +// Supplied value must remain valid for the life of the transaction. +// Returns an error if the bucket was created from a read-only transaction, if the key is blank, if the key is too large, or if the value is too large. +func (b *Bucket) Put(key []byte, value []byte) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } else if len(key) == 0 { + return ErrKeyRequired + } else if len(key) > MaxKeySize { + return ErrKeyTooLarge + } else if int64(len(value)) > MaxValueSize { + return ErrValueTooLarge + } + + // Move cursor to correct position. + c := b.Cursor() + k, _, flags := c.seek(key) + + // Return an error if there is an existing key with a bucket value. + if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 { + return ErrIncompatibleValue + } + + // Insert into node. + key = cloneBytes(key) + c.node().put(key, key, value, 0, 0) + + return nil +} + +// Delete removes a key from the bucket. +// If the key does not exist then nothing is done and a nil error is returned. +// Returns an error if the bucket was created from a read-only transaction. +func (b *Bucket) Delete(key []byte) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Move cursor to correct position. + c := b.Cursor() + _, _, flags := c.seek(key) + + // Return an error if there is already existing bucket value. + if (flags & bucketLeafFlag) != 0 { + return ErrIncompatibleValue + } + + // Delete the node if we have a matching key. + c.node().del(key) + + return nil +} + +// Sequence returns the current integer for the bucket without incrementing it. +func (b *Bucket) Sequence() uint64 { return b.bucket.sequence } + +// SetSequence updates the sequence number for the bucket. +func (b *Bucket) SetSequence(v uint64) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Materialize the root node if it hasn't been already so that the + // bucket will be saved during commit. + if b.rootNode == nil { + _ = b.node(b.root, nil) + } + + // Increment and return the sequence. + b.bucket.sequence = v + return nil +} + +// NextSequence returns an autoincrementing integer for the bucket. +func (b *Bucket) NextSequence() (uint64, error) { + if b.tx.db == nil { + return 0, ErrTxClosed + } else if !b.Writable() { + return 0, ErrTxNotWritable + } + + // Materialize the root node if it hasn't been already so that the + // bucket will be saved during commit. + if b.rootNode == nil { + _ = b.node(b.root, nil) + } + + // Increment and return the sequence. + b.bucket.sequence++ + return b.bucket.sequence, nil +} + +// ForEach executes a function for each key/value pair in a bucket. +// If the provided function returns an error then the iteration is stopped and +// the error is returned to the caller. The provided function must not modify +// the bucket; this will result in undefined behavior. +func (b *Bucket) ForEach(fn func(k, v []byte) error) error { + if b.tx.db == nil { + return ErrTxClosed + } + c := b.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + if err := fn(k, v); err != nil { + return err + } + } + return nil +} + +// Stat returns stats on a bucket. +func (b *Bucket) Stats() BucketStats { + var s, subStats BucketStats + pageSize := b.tx.db.pageSize + s.BucketN += 1 + if b.root == 0 { + s.InlineBucketN += 1 + } + b.forEachPage(func(p *page, depth int) { + if (p.flags & leafPageFlag) != 0 { + s.KeyN += int(p.count) + + // used totals the used bytes for the page + used := pageHeaderSize + + if p.count != 0 { + // If page has any elements, add all element headers. + used += leafPageElementSize * int(p.count-1) + + // Add all element key, value sizes. + // The computation takes advantage of the fact that the position + // of the last element's key/value equals to the total of the sizes + // of all previous elements' keys and values. + // It also includes the last element's header. + lastElement := p.leafPageElement(p.count - 1) + used += int(lastElement.pos + lastElement.ksize + lastElement.vsize) + } + + if b.root == 0 { + // For inlined bucket just update the inline stats + s.InlineBucketInuse += used + } else { + // For non-inlined bucket update all the leaf stats + s.LeafPageN++ + s.LeafInuse += used + s.LeafOverflowN += int(p.overflow) + + // Collect stats from sub-buckets. + // Do that by iterating over all element headers + // looking for the ones with the bucketLeafFlag. + for i := uint16(0); i < p.count; i++ { + e := p.leafPageElement(i) + if (e.flags & bucketLeafFlag) != 0 { + // For any bucket element, open the element value + // and recursively call Stats on the contained bucket. + subStats.Add(b.openBucket(e.value()).Stats()) + } + } + } + } else if (p.flags & branchPageFlag) != 0 { + s.BranchPageN++ + lastElement := p.branchPageElement(p.count - 1) + + // used totals the used bytes for the page + // Add header and all element headers. + used := pageHeaderSize + (branchPageElementSize * int(p.count-1)) + + // Add size of all keys and values. + // Again, use the fact that last element's position equals to + // the total of key, value sizes of all previous elements. + used += int(lastElement.pos + lastElement.ksize) + s.BranchInuse += used + s.BranchOverflowN += int(p.overflow) + } + + // Keep track of maximum page depth. + if depth+1 > s.Depth { + s.Depth = (depth + 1) + } + }) + + // Alloc stats can be computed from page counts and pageSize. + s.BranchAlloc = (s.BranchPageN + s.BranchOverflowN) * pageSize + s.LeafAlloc = (s.LeafPageN + s.LeafOverflowN) * pageSize + + // Add the max depth of sub-buckets to get total nested depth. + s.Depth += subStats.Depth + // Add the stats for all sub-buckets + s.Add(subStats) + return s +} + +// forEachPage iterates over every page in a bucket, including inline pages. +func (b *Bucket) forEachPage(fn func(*page, int)) { + // If we have an inline page then just use that. + if b.page != nil { + fn(b.page, 0) + return + } + + // Otherwise traverse the page hierarchy. + b.tx.forEachPage(b.root, 0, fn) +} + +// forEachPageNode iterates over every page (or node) in a bucket. +// This also includes inline pages. +func (b *Bucket) forEachPageNode(fn func(*page, *node, int)) { + // If we have an inline page or root node then just use that. + if b.page != nil { + fn(b.page, nil, 0) + return + } + b._forEachPageNode(b.root, 0, fn) +} + +func (b *Bucket) _forEachPageNode(pgid pgid, depth int, fn func(*page, *node, int)) { + var p, n = b.pageNode(pgid) + + // Execute function. + fn(p, n, depth) + + // Recursively loop over children. + if p != nil { + if (p.flags & branchPageFlag) != 0 { + for i := 0; i < int(p.count); i++ { + elem := p.branchPageElement(uint16(i)) + b._forEachPageNode(elem.pgid, depth+1, fn) + } + } + } else { + if !n.isLeaf { + for _, inode := range n.inodes { + b._forEachPageNode(inode.pgid, depth+1, fn) + } + } + } +} + +// spill writes all the nodes for this bucket to dirty pages. +func (b *Bucket) spill() error { + // Spill all child buckets first. + for name, child := range b.buckets { + // If the child bucket is small enough and it has no child buckets then + // write it inline into the parent bucket's page. Otherwise spill it + // like a normal bucket and make the parent value a pointer to the page. + var value []byte + if child.inlineable() { + child.free() + value = child.write() + } else { + if err := child.spill(); err != nil { + return err + } + + // Update the child bucket header in this bucket. + value = make([]byte, unsafe.Sizeof(bucket{})) + var bucket = (*bucket)(unsafe.Pointer(&value[0])) + *bucket = *child.bucket + } + + // Skip writing the bucket if there are no materialized nodes. + if child.rootNode == nil { + continue + } + + // Update parent node. + var c = b.Cursor() + k, _, flags := c.seek([]byte(name)) + if !bytes.Equal([]byte(name), k) { + panic(fmt.Sprintf("misplaced bucket header: %x -> %x", []byte(name), k)) + } + if flags&bucketLeafFlag == 0 { + panic(fmt.Sprintf("unexpected bucket header flag: %x", flags)) + } + c.node().put([]byte(name), []byte(name), value, 0, bucketLeafFlag) + } + + // Ignore if there's not a materialized root node. + if b.rootNode == nil { + return nil + } + + // Spill nodes. + if err := b.rootNode.spill(); err != nil { + return err + } + b.rootNode = b.rootNode.root() + + // Update the root node for this bucket. + if b.rootNode.pgid >= b.tx.meta.pgid { + panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", b.rootNode.pgid, b.tx.meta.pgid)) + } + b.root = b.rootNode.pgid + + return nil +} + +// inlineable returns true if a bucket is small enough to be written inline +// and if it contains no subbuckets. Otherwise returns false. +func (b *Bucket) inlineable() bool { + var n = b.rootNode + + // Bucket must only contain a single leaf node. + if n == nil || !n.isLeaf { + return false + } + + // Bucket is not inlineable if it contains subbuckets or if it goes beyond + // our threshold for inline bucket size. + var size = pageHeaderSize + for _, inode := range n.inodes { + size += leafPageElementSize + len(inode.key) + len(inode.value) + + if inode.flags&bucketLeafFlag != 0 { + return false + } else if size > b.maxInlineBucketSize() { + return false + } + } + + return true +} + +// Returns the maximum total size of a bucket to make it a candidate for inlining. +func (b *Bucket) maxInlineBucketSize() int { + return b.tx.db.pageSize / 4 +} + +// write allocates and writes a bucket to a byte slice. +func (b *Bucket) write() []byte { + // Allocate the appropriate size. + var n = b.rootNode + var value = make([]byte, bucketHeaderSize+n.size()) + + // Write a bucket header. + var bucket = (*bucket)(unsafe.Pointer(&value[0])) + *bucket = *b.bucket + + // Convert byte slice to a fake page and write the root node. + var p = (*page)(unsafe.Pointer(&value[bucketHeaderSize])) + n.write(p) + + return value +} + +// rebalance attempts to balance all nodes. +func (b *Bucket) rebalance() { + for _, n := range b.nodes { + n.rebalance() + } + for _, child := range b.buckets { + child.rebalance() + } +} + +// node creates a node from a page and associates it with a given parent. +func (b *Bucket) node(pgid pgid, parent *node) *node { + _assert(b.nodes != nil, "nodes map expected") + + // Retrieve node if it's already been created. + if n := b.nodes[pgid]; n != nil { + return n + } + + // Otherwise create a node and cache it. + n := &node{bucket: b, parent: parent} + if parent == nil { + b.rootNode = n + } else { + parent.children = append(parent.children, n) + } + + // Use the inline page if this is an inline bucket. + var p = b.page + if p == nil { + p = b.tx.page(pgid) + } + + // Read the page into the node and cache it. + n.read(p) + b.nodes[pgid] = n + + // Update statistics. + b.tx.stats.NodeCount++ + + return n +} + +// free recursively frees all pages in the bucket. +func (b *Bucket) free() { + if b.root == 0 { + return + } + + var tx = b.tx + b.forEachPageNode(func(p *page, n *node, _ int) { + if p != nil { + tx.db.freelist.free(tx.meta.txid, p) + } else { + n.free() + } + }) + b.root = 0 +} + +// dereference removes all references to the old mmap. +func (b *Bucket) dereference() { + if b.rootNode != nil { + b.rootNode.root().dereference() + } + + for _, child := range b.buckets { + child.dereference() + } +} + +// pageNode returns the in-memory node, if it exists. +// Otherwise returns the underlying page. +func (b *Bucket) pageNode(id pgid) (*page, *node) { + // Inline buckets have a fake page embedded in their value so treat them + // differently. We'll return the rootNode (if available) or the fake page. + if b.root == 0 { + if id != 0 { + panic(fmt.Sprintf("inline bucket non-zero page access(2): %d != 0", id)) + } + if b.rootNode != nil { + return nil, b.rootNode + } + return b.page, nil + } + + // Check the node cache for non-inline buckets. + if b.nodes != nil { + if n := b.nodes[id]; n != nil { + return nil, n + } + } + + // Finally lookup the page from the transaction if no node is materialized. + return b.tx.page(id), nil +} + +// BucketStats records statistics about resources used by a bucket. +type BucketStats struct { + // Page count statistics. + BranchPageN int // number of logical branch pages + BranchOverflowN int // number of physical branch overflow pages + LeafPageN int // number of logical leaf pages + LeafOverflowN int // number of physical leaf overflow pages + + // Tree statistics. + KeyN int // number of keys/value pairs + Depth int // number of levels in B+tree + + // Page size utilization. + BranchAlloc int // bytes allocated for physical branch pages + BranchInuse int // bytes actually used for branch data + LeafAlloc int // bytes allocated for physical leaf pages + LeafInuse int // bytes actually used for leaf data + + // Bucket statistics + BucketN int // total number of buckets including the top bucket + InlineBucketN int // total number on inlined buckets + InlineBucketInuse int // bytes used for inlined buckets (also accounted for in LeafInuse) +} + +func (s *BucketStats) Add(other BucketStats) { + s.BranchPageN += other.BranchPageN + s.BranchOverflowN += other.BranchOverflowN + s.LeafPageN += other.LeafPageN + s.LeafOverflowN += other.LeafOverflowN + s.KeyN += other.KeyN + if s.Depth < other.Depth { + s.Depth = other.Depth + } + s.BranchAlloc += other.BranchAlloc + s.BranchInuse += other.BranchInuse + s.LeafAlloc += other.LeafAlloc + s.LeafInuse += other.LeafInuse + + s.BucketN += other.BucketN + s.InlineBucketN += other.InlineBucketN + s.InlineBucketInuse += other.InlineBucketInuse +} + +// cloneBytes returns a copy of a given slice. +func cloneBytes(v []byte) []byte { + var clone = make([]byte, len(v)) + copy(clone, v) + return clone +} diff --git a/vendor/github.com/boltdb/bolt/bucket_test.go b/vendor/github.com/boltdb/bolt/bucket_test.go new file mode 100644 index 0000000..cddbe27 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bucket_test.go @@ -0,0 +1,1909 @@ +package bolt_test + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "log" + "math/rand" + "os" + "strconv" + "strings" + "testing" + "testing/quick" + + "github.com/boltdb/bolt" +) + +// Ensure that a bucket that gets a non-existent key returns nil. +func TestBucket_Get_NonExistent(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); v != nil { + t.Fatal("expected nil value") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can read a value that is not flushed yet. +func TestBucket_Get_FromNode(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket retrieved via Get() returns a nil. +func TestBucket_Get_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + + if tx.Bucket([]byte("widgets")).Get([]byte("foo")) != nil { + t.Fatal("expected nil value") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a slice returned from a bucket has a capacity equal to its length. +// This also allows slices to be appended to since it will require a realloc by Go. +// +// https://github.com/boltdb/bolt/issues/544 +func TestBucket_Get_Capacity(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Write key to a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("bucket")) + if err != nil { + return err + } + return b.Put([]byte("key"), []byte("val")) + }); err != nil { + t.Fatal(err) + } + + // Retrieve value and attempt to append to it. + if err := db.Update(func(tx *bolt.Tx) error { + k, v := tx.Bucket([]byte("bucket")).Cursor().First() + + // Verify capacity. + if len(k) != cap(k) { + t.Fatalf("unexpected key slice capacity: %d", cap(k)) + } else if len(v) != cap(v) { + t.Fatalf("unexpected value slice capacity: %d", cap(v)) + } + + // Ensure slice can be appended to without a segfault. + k = append(k, []byte("123")...) + v = append(v, []byte("123")...) + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can write a key/value. +func TestBucket_Put(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + v := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + if !bytes.Equal([]byte("bar"), v) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can rewrite a key in the same transaction. +func TestBucket_Put_Repeat(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("baz")); err != nil { + t.Fatal(err) + } + + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + if !bytes.Equal([]byte("baz"), value) { + t.Fatalf("unexpected value: %v", value) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can write a bunch of large values. +func TestBucket_Put_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + count, factor := 100, 200 + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for i := 1; i < count; i++ { + if err := b.Put([]byte(strings.Repeat("0", i*factor)), []byte(strings.Repeat("X", (count-i)*factor))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 1; i < count; i++ { + value := b.Get([]byte(strings.Repeat("0", i*factor))) + if !bytes.Equal(value, []byte(strings.Repeat("X", (count-i)*factor))) { + t.Fatalf("unexpected value: %v", value) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a database can perform multiple large appends safely. +func TestDB_Put_VeryLarge(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + n, batchN := 400000, 200000 + ksize, vsize := 8, 500 + + db := MustOpenDB() + defer db.MustClose() + + for i := 0; i < n; i += batchN { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for j := 0; j < batchN; j++ { + k, v := make([]byte, ksize), make([]byte, vsize) + binary.BigEndian.PutUint32(k, uint32(i+j)) + if err := b.Put(k, v); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + } +} + +// Ensure that a setting a value on a key with a bucket value returns an error. +func TestBucket_Put_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b0, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if err := b0.Put([]byte("foo"), []byte("bar")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a setting a value while the transaction is closed returns an error. +func TestBucket_Put_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + if err := b.Put([]byte("foo"), []byte("bar")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that setting a value on a read-only bucket returns an error. +func TestBucket_Put_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("foo"), []byte("bar")); err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can delete an existing key. +func TestBucket_Delete(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); v != nil { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a large set of keys will work correctly. +func TestBucket_Delete_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 100; i++ { + if err := b.Put([]byte(strconv.Itoa(i)), []byte(strings.Repeat("*", 1024))); err != nil { + t.Fatal(err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < 100; i++ { + if err := b.Delete([]byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < 100; i++ { + if v := b.Get([]byte(strconv.Itoa(i))); v != nil { + t.Fatalf("unexpected value: %v, i=%d", v, i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Deleting a very large list of keys will cause the freelist to use overflow. +func TestBucket_Delete_FreelistOverflow(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + db := MustOpenDB() + defer db.MustClose() + + k := make([]byte, 16) + for i := uint64(0); i < 10000; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("0")) + if err != nil { + t.Fatalf("bucket error: %s", err) + } + + for j := uint64(0); j < 1000; j++ { + binary.BigEndian.PutUint64(k[:8], i) + binary.BigEndian.PutUint64(k[8:], j) + if err := b.Put(k, nil); err != nil { + t.Fatalf("put error: %s", err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + } + + // Delete all of them in one large transaction + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("0")) + c := b.Cursor() + for k, _ := c.First(); k != nil; k, _ = c.Next() { + if err := c.Delete(); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that accessing and updating nested buckets is ok across transactions. +func TestBucket_Nested(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + // Create a widgets bucket. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + // Create a widgets/foo bucket. + _, err = b.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + // Create a widgets/bar key. + if err := b.Put([]byte("bar"), []byte("0000")); err != nil { + t.Fatal(err) + } + + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Update widgets/bar. + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("bar"), []byte("xxxx")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Cause a split. + if err := db.Update(func(tx *bolt.Tx) error { + var b = tx.Bucket([]byte("widgets")) + for i := 0; i < 10000; i++ { + if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Insert into widgets/foo/baz. + if err := db.Update(func(tx *bolt.Tx) error { + var b = tx.Bucket([]byte("widgets")) + if err := b.Bucket([]byte("foo")).Put([]byte("baz"), []byte("yyyy")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Verify. + if err := db.View(func(tx *bolt.Tx) error { + var b = tx.Bucket([]byte("widgets")) + if v := b.Bucket([]byte("foo")).Get([]byte("baz")); !bytes.Equal(v, []byte("yyyy")) { + t.Fatalf("unexpected value: %v", v) + } + if v := b.Get([]byte("bar")); !bytes.Equal(v, []byte("xxxx")) { + t.Fatalf("unexpected value: %v", v) + } + for i := 0; i < 10000; i++ { + if v := b.Get([]byte(strconv.Itoa(i))); !bytes.Equal(v, []byte(strconv.Itoa(i))) { + t.Fatalf("unexpected value: %v", v) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket using Delete() returns an error. +func TestBucket_Delete_Bucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a key on a read-only bucket returns an error. +func TestBucket_Delete_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).Delete([]byte("foo")); err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a deleting value while the transaction is closed returns an error. +func TestBucket_Delete_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that deleting a bucket causes nested buckets to be deleted. +func TestBucket_DeleteBucket_Nested(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + foo, err := widgets.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + bar, err := foo.CreateBucket([]byte("bar")) + if err != nil { + t.Fatal(err) + } + if err := bar.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket causes nested buckets to be deleted after they have been committed. +func TestBucket_DeleteBucket_Nested2(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + foo, err := widgets.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + bar, err := foo.CreateBucket([]byte("bar")) + if err != nil { + t.Fatal(err) + } + + if err := bar.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + widgets := tx.Bucket([]byte("widgets")) + if widgets == nil { + t.Fatal("expected widgets bucket") + } + + foo := widgets.Bucket([]byte("foo")) + if foo == nil { + t.Fatal("expected foo bucket") + } + + bar := foo.Bucket([]byte("bar")) + if bar == nil { + t.Fatal("expected bar bucket") + } + + if v := bar.Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) { + t.Fatalf("unexpected value: %v", v) + } + if err := tx.DeleteBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) != nil { + t.Fatal("expected bucket to be deleted") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a child bucket with multiple pages causes all pages to get collected. +// NOTE: Consistency check in bolt_test.DB.Close() will panic if pages not freed properly. +func TestBucket_DeleteBucket_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + foo, err := widgets.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 1000; i++ { + if err := foo.Put([]byte(fmt.Sprintf("%d", i)), []byte(fmt.Sprintf("%0100d", i))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a simple value retrieved via Bucket() returns a nil. +func TestBucket_Bucket_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if b := tx.Bucket([]byte("widgets")).Bucket([]byte("foo")); b != nil { + t.Fatal("expected nil bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that creating a bucket on an existing non-bucket key returns an error. +func TestBucket_CreateBucket_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if _, err := widgets.CreateBucket([]byte("foo")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket on an existing non-bucket key returns an error. +func TestBucket_DeleteBucket_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure bucket can set and update its sequence number. +func TestBucket_Sequence(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + bkt, err := tx.CreateBucket([]byte("0")) + if err != nil { + t.Fatal(err) + } + + // Retrieve sequence. + if v := bkt.Sequence(); v != 0 { + t.Fatalf("unexpected sequence: %d", v) + } + + // Update sequence. + if err := bkt.SetSequence(1000); err != nil { + t.Fatal(err) + } + + // Read sequence again. + if v := bkt.Sequence(); v != 1000 { + t.Fatalf("unexpected sequence: %d", v) + } + + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify sequence in separate transaction. + if err := db.View(func(tx *bolt.Tx) error { + if v := tx.Bucket([]byte("0")).Sequence(); v != 1000 { + t.Fatalf("unexpected sequence: %d", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can return an autoincrementing sequence. +func TestBucket_NextSequence(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + woojits, err := tx.CreateBucket([]byte("woojits")) + if err != nil { + t.Fatal(err) + } + + // Make sure sequence increments. + if seq, err := widgets.NextSequence(); err != nil { + t.Fatal(err) + } else if seq != 1 { + t.Fatalf("unexpecte sequence: %d", seq) + } + + if seq, err := widgets.NextSequence(); err != nil { + t.Fatal(err) + } else if seq != 2 { + t.Fatalf("unexpected sequence: %d", seq) + } + + // Buckets should be separate. + if seq, err := woojits.NextSequence(); err != nil { + t.Fatal(err) + } else if seq != 1 { + t.Fatalf("unexpected sequence: %d", 1) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket will persist an autoincrementing sequence even if its +// the only thing updated on the bucket. +// https://github.com/boltdb/bolt/issues/296 +func TestBucket_NextSequence_Persist(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.Bucket([]byte("widgets")).NextSequence(); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + seq, err := tx.Bucket([]byte("widgets")).NextSequence() + if err != nil { + t.Fatalf("unexpected error: %s", err) + } else if seq != 2 { + t.Fatalf("unexpected sequence: %d", seq) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that retrieving the next sequence on a read-only bucket returns an error. +func TestBucket_NextSequence_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + _, err := tx.Bucket([]byte("widgets")).NextSequence() + if err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that retrieving the next sequence for a bucket on a closed database return an error. +func TestBucket_NextSequence_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + if _, err := b.NextSequence(); err != bolt.ErrTxClosed { + t.Fatal(err) + } +} + +// Ensure a user can loop over all key/value pairs in a bucket. +func TestBucket_ForEach(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("0000")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("0001")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte("0002")); err != nil { + t.Fatal(err) + } + + var index int + if err := b.ForEach(func(k, v []byte) error { + switch index { + case 0: + if !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0002")) { + t.Fatalf("unexpected value: %v", v) + } + case 1: + if !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0001")) { + t.Fatalf("unexpected value: %v", v) + } + case 2: + if !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0000")) { + t.Fatalf("unexpected value: %v", v) + } + } + index++ + return nil + }); err != nil { + t.Fatal(err) + } + + if index != 3 { + t.Fatalf("unexpected index: %d", index) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a database can stop iteration early. +func TestBucket_ForEach_ShortCircuit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte("0000")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("0000")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("0000")); err != nil { + t.Fatal(err) + } + + var index int + if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error { + index++ + if bytes.Equal(k, []byte("baz")) { + return errors.New("marker") + } + return nil + }); err == nil || err.Error() != "marker" { + t.Fatalf("unexpected error: %s", err) + } + if index != 2 { + t.Fatalf("unexpected index: %d", index) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that looping over a bucket on a closed database returns an error. +func TestBucket_ForEach_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + if err := b.ForEach(func(k, v []byte) error { return nil }); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that an error is returned when inserting with an empty key. +func TestBucket_Put_EmptyKey(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte(""), []byte("bar")); err != bolt.ErrKeyRequired { + t.Fatalf("unexpected error: %s", err) + } + if err := b.Put(nil, []byte("bar")); err != bolt.ErrKeyRequired { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that an error is returned when inserting with a key that's too large. +func TestBucket_Put_KeyTooLarge(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put(make([]byte, 32769), []byte("bar")); err != bolt.ErrKeyTooLarge { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that an error is returned when inserting a value that's too large. +func TestBucket_Put_ValueTooLarge(t *testing.T) { + // Skip this test on DroneCI because the machine is resource constrained. + if os.Getenv("DRONE") == "true" { + t.Skip("not enough RAM for test") + } + + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), make([]byte, bolt.MaxValueSize+1)); err != bolt.ErrValueTooLarge { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket can calculate stats. +func TestBucket_Stats(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Add bucket with fewer keys but one big value. + bigKey := []byte("really-big-value") + for i := 0; i < 500; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("woojits")) + if err != nil { + t.Fatal(err) + } + + if err := b.Put([]byte(fmt.Sprintf("%03d", i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + } + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("woojits")).Put(bigKey, []byte(strings.Repeat("*", 10000))); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("woojits")).Stats() + if stats.BranchPageN != 1 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 7 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 2 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 501 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 2 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } + + branchInuse := 16 // branch page header + branchInuse += 7 * 16 // branch elements + branchInuse += 7 * 3 // branch keys (6 3-byte keys) + if stats.BranchInuse != branchInuse { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } + + leafInuse := 7 * 16 // leaf page header + leafInuse += 501 * 16 // leaf elements + leafInuse += 500*3 + len(bigKey) // leaf keys + leafInuse += 1*10 + 2*90 + 3*400 + 10000 // leaf values + if stats.LeafInuse != leafInuse { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + // Only check allocations for 4KB pages. + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 4096 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 36864 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 0 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 0 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket with random insertion utilizes fill percentage correctly. +func TestBucket_Stats_RandomFill(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } else if os.Getpagesize() != 4096 { + t.Skip("invalid page size for test") + } + + db := MustOpenDB() + defer db.MustClose() + + // Add a set of values in random order. It will be the same random + // order so we can maintain consistency between test runs. + var count int + rand := rand.New(rand.NewSource(42)) + for _, i := range rand.Perm(1000) { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("woojits")) + if err != nil { + t.Fatal(err) + } + b.FillPercent = 0.9 + for _, j := range rand.Perm(100) { + index := (j * 10000) + i + if err := b.Put([]byte(fmt.Sprintf("%d000000000000000", index)), []byte("0000000000")); err != nil { + t.Fatal(err) + } + count++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("woojits")).Stats() + if stats.KeyN != 100000 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } + + if stats.BranchPageN != 98 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.BranchInuse != 130984 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.BranchAlloc != 401408 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } + + if stats.LeafPageN != 3412 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.LeafInuse != 4742482 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } else if stats.LeafAlloc != 13975552 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket can calculate stats. +func TestBucket_Stats_Small(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + // Add a bucket that fits on a single root leaf. + b, err := tx.CreateBucket([]byte("whozawhats")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("whozawhats")) + stats := b.Stats() + if stats.BranchPageN != 0 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 0 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 1 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 1 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 0 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.LeafInuse != 0 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 0 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 0 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 1 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 16+16+6 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestBucket_Stats_EmptyBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + // Add a bucket that fits on a single root leaf. + if _, err := tx.CreateBucket([]byte("whozawhats")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("whozawhats")) + stats := b.Stats() + if stats.BranchPageN != 0 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 0 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 0 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 1 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 0 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.LeafInuse != 0 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 0 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 0 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 1 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 16 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket can calculate stats. +func TestBucket_Stats_Nested(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 100; i++ { + if err := b.Put([]byte(fmt.Sprintf("%02d", i)), []byte(fmt.Sprintf("%02d", i))); err != nil { + t.Fatal(err) + } + } + + bar, err := b.CreateBucket([]byte("bar")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 10; i++ { + if err := bar.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + + baz, err := bar.CreateBucket([]byte("baz")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 10; i++ { + if err := baz.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("foo")) + stats := b.Stats() + if stats.BranchPageN != 0 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 2 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 122 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 3 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 0 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } + + foo := 16 // foo (pghdr) + foo += 101 * 16 // foo leaf elements + foo += 100*2 + 100*2 // foo leaf key/values + foo += 3 + 16 // foo -> bar key/value + + bar := 16 // bar (pghdr) + bar += 11 * 16 // bar leaf elements + bar += 10 + 10 // bar leaf key/values + bar += 3 + 16 // bar -> baz key/value + + baz := 16 // baz (inline) (pghdr) + baz += 10 * 16 // baz leaf elements + baz += 10 + 10 // baz leaf key/values + + if stats.LeafInuse != foo+bar+baz { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 0 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 8192 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 3 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 1 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != baz { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a large bucket can calculate stats. +func TestBucket_Stats_Large(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + db := MustOpenDB() + defer db.MustClose() + + var index int + for i := 0; i < 100; i++ { + // Add bucket with lots of keys. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 1000; i++ { + if err := b.Put([]byte(strconv.Itoa(index)), []byte(strconv.Itoa(index))); err != nil { + t.Fatal(err) + } + index++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("widgets")).Stats() + if stats.BranchPageN != 13 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 1196 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 100000 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 3 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 25257 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.LeafInuse != 2596916 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 53248 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 4898816 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 0 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 0 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can write random keys and values across multiple transactions. +func TestBucket_Put_Single(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + index := 0 + if err := quick.Check(func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + m := make(map[string][]byte) + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + for _, item := range items { + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).Put(item.Key, item.Value); err != nil { + panic("put error: " + err.Error()) + } + m[string(item.Key)] = item.Value + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify all key/values so far. + if err := db.View(func(tx *bolt.Tx) error { + i := 0 + for k, v := range m { + value := tx.Bucket([]byte("widgets")).Get([]byte(k)) + if !bytes.Equal(value, v) { + t.Logf("value mismatch [run %d] (%d of %d):\nkey: %x\ngot: %x\nexp: %x", index, i, len(m), []byte(k), value, v) + db.CopyTempFile() + t.FailNow() + } + i++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + index++ + return true + }, nil); err != nil { + t.Error(err) + } +} + +// Ensure that a transaction can insert multiple key/value pairs at once. +func TestBucket_Put_Multiple(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + if err := quick.Check(func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify all items exist. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for _, item := range items { + value := b.Get(item.Key) + if !bytes.Equal(item.Value, value) { + db.CopyTempFile() + t.Fatalf("exp=%x; got=%x", item.Value, value) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + return true + }, qconfig()); err != nil { + t.Error(err) + } +} + +// Ensure that a transaction can delete all key/value pairs and return to a single leaf page. +func TestBucket_Delete_Quick(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + if err := quick.Check(func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Remove items one at a time and check consistency. + for _, item := range items { + if err := db.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Delete(item.Key) + }); err != nil { + t.Fatal(err) + } + } + + // Anything before our deletion index should be nil. + if err := db.View(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error { + t.Fatalf("bucket should be empty; found: %06x", trunc(k, 3)) + return nil + }); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + return true + }, qconfig()); err != nil { + t.Error(err) + } +} + +func ExampleBucket_Put() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a bucket. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + + // Set the value "bar" for the key "foo". + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Read value back in a different read-only transaction. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value of 'foo' is: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value of 'foo' is: bar +} + +func ExampleBucket_Delete() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a bucket. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + + // Set the value "bar" for the key "foo". + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + + // Retrieve the key back from the database and verify it. + value := b.Get([]byte("foo")) + fmt.Printf("The value of 'foo' was: %s\n", value) + + return nil + }); err != nil { + log.Fatal(err) + } + + // Delete the key in a different write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Delete([]byte("foo")) + }); err != nil { + log.Fatal(err) + } + + // Retrieve the key again. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + if value == nil { + fmt.Printf("The value of 'foo' is now: nil\n") + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value of 'foo' was: bar + // The value of 'foo' is now: nil +} + +func ExampleBucket_ForEach() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Insert data into a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("animals")) + if err != nil { + return err + } + + if err := b.Put([]byte("dog"), []byte("fun")); err != nil { + return err + } + if err := b.Put([]byte("cat"), []byte("lame")); err != nil { + return err + } + if err := b.Put([]byte("liger"), []byte("awesome")); err != nil { + return err + } + + // Iterate over items in sorted key order. + if err := b.ForEach(func(k, v []byte) error { + fmt.Printf("A %s is %s.\n", k, v) + return nil + }); err != nil { + return err + } + + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // A cat is lame. + // A dog is fun. + // A liger is awesome. +} diff --git a/vendor/github.com/boltdb/bolt/cursor.go b/vendor/github.com/boltdb/bolt/cursor.go new file mode 100644 index 0000000..1be9f35 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/cursor.go @@ -0,0 +1,400 @@ +package bolt + +import ( + "bytes" + "fmt" + "sort" +) + +// Cursor represents an iterator that can traverse over all key/value pairs in a bucket in sorted order. +// Cursors see nested buckets with value == nil. +// Cursors can be obtained from a transaction and are valid as long as the transaction is open. +// +// Keys and values returned from the cursor are only valid for the life of the transaction. +// +// Changing data while traversing with a cursor may cause it to be invalidated +// and return unexpected keys and/or values. You must reposition your cursor +// after mutating data. +type Cursor struct { + bucket *Bucket + stack []elemRef +} + +// Bucket returns the bucket that this cursor was created from. +func (c *Cursor) Bucket() *Bucket { + return c.bucket +} + +// First moves the cursor to the first item in the bucket and returns its key and value. +// If the bucket is empty then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) First() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + c.stack = c.stack[:0] + p, n := c.bucket.pageNode(c.bucket.root) + c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) + c.first() + + // If we land on an empty page then move to the next value. + // https://github.com/boltdb/bolt/issues/450 + if c.stack[len(c.stack)-1].count() == 0 { + c.next() + } + + k, v, flags := c.keyValue() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v + +} + +// Last moves the cursor to the last item in the bucket and returns its key and value. +// If the bucket is empty then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Last() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + c.stack = c.stack[:0] + p, n := c.bucket.pageNode(c.bucket.root) + ref := elemRef{page: p, node: n} + ref.index = ref.count() - 1 + c.stack = append(c.stack, ref) + c.last() + k, v, flags := c.keyValue() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Next moves the cursor to the next item in the bucket and returns its key and value. +// If the cursor is at the end of the bucket then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Next() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + k, v, flags := c.next() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Prev moves the cursor to the previous item in the bucket and returns its key and value. +// If the cursor is at the beginning of the bucket then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Prev() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + + // Attempt to move back one element until we're successful. + // Move up the stack as we hit the beginning of each page in our stack. + for i := len(c.stack) - 1; i >= 0; i-- { + elem := &c.stack[i] + if elem.index > 0 { + elem.index-- + break + } + c.stack = c.stack[:i] + } + + // If we've hit the end then return nil. + if len(c.stack) == 0 { + return nil, nil + } + + // Move down the stack to find the last element of the last leaf under this branch. + c.last() + k, v, flags := c.keyValue() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Seek moves the cursor to a given key and returns it. +// If the key does not exist then the next key is used. If no keys +// follow, a nil key is returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) { + k, v, flags := c.seek(seek) + + // If we ended up after the last element of a page then move to the next one. + if ref := &c.stack[len(c.stack)-1]; ref.index >= ref.count() { + k, v, flags = c.next() + } + + if k == nil { + return nil, nil + } else if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Delete removes the current key/value under the cursor from the bucket. +// Delete fails if current key/value is a bucket or if the transaction is not writable. +func (c *Cursor) Delete() error { + if c.bucket.tx.db == nil { + return ErrTxClosed + } else if !c.bucket.Writable() { + return ErrTxNotWritable + } + + key, _, flags := c.keyValue() + // Return an error if current value is a bucket. + if (flags & bucketLeafFlag) != 0 { + return ErrIncompatibleValue + } + c.node().del(key) + + return nil +} + +// seek moves the cursor to a given key and returns it. +// If the key does not exist then the next key is used. +func (c *Cursor) seek(seek []byte) (key []byte, value []byte, flags uint32) { + _assert(c.bucket.tx.db != nil, "tx closed") + + // Start from root page/node and traverse to correct page. + c.stack = c.stack[:0] + c.search(seek, c.bucket.root) + ref := &c.stack[len(c.stack)-1] + + // If the cursor is pointing to the end of page/node then return nil. + if ref.index >= ref.count() { + return nil, nil, 0 + } + + // If this is a bucket then return a nil value. + return c.keyValue() +} + +// first moves the cursor to the first leaf element under the last page in the stack. +func (c *Cursor) first() { + for { + // Exit when we hit a leaf page. + var ref = &c.stack[len(c.stack)-1] + if ref.isLeaf() { + break + } + + // Keep adding pages pointing to the first element to the stack. + var pgid pgid + if ref.node != nil { + pgid = ref.node.inodes[ref.index].pgid + } else { + pgid = ref.page.branchPageElement(uint16(ref.index)).pgid + } + p, n := c.bucket.pageNode(pgid) + c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) + } +} + +// last moves the cursor to the last leaf element under the last page in the stack. +func (c *Cursor) last() { + for { + // Exit when we hit a leaf page. + ref := &c.stack[len(c.stack)-1] + if ref.isLeaf() { + break + } + + // Keep adding pages pointing to the last element in the stack. + var pgid pgid + if ref.node != nil { + pgid = ref.node.inodes[ref.index].pgid + } else { + pgid = ref.page.branchPageElement(uint16(ref.index)).pgid + } + p, n := c.bucket.pageNode(pgid) + + var nextRef = elemRef{page: p, node: n} + nextRef.index = nextRef.count() - 1 + c.stack = append(c.stack, nextRef) + } +} + +// next moves to the next leaf element and returns the key and value. +// If the cursor is at the last leaf element then it stays there and returns nil. +func (c *Cursor) next() (key []byte, value []byte, flags uint32) { + for { + // Attempt to move over one element until we're successful. + // Move up the stack as we hit the end of each page in our stack. + var i int + for i = len(c.stack) - 1; i >= 0; i-- { + elem := &c.stack[i] + if elem.index < elem.count()-1 { + elem.index++ + break + } + } + + // If we've hit the root page then stop and return. This will leave the + // cursor on the last element of the last page. + if i == -1 { + return nil, nil, 0 + } + + // Otherwise start from where we left off in the stack and find the + // first element of the first leaf page. + c.stack = c.stack[:i+1] + c.first() + + // If this is an empty page then restart and move back up the stack. + // https://github.com/boltdb/bolt/issues/450 + if c.stack[len(c.stack)-1].count() == 0 { + continue + } + + return c.keyValue() + } +} + +// search recursively performs a binary search against a given page/node until it finds a given key. +func (c *Cursor) search(key []byte, pgid pgid) { + p, n := c.bucket.pageNode(pgid) + if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 { + panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags)) + } + e := elemRef{page: p, node: n} + c.stack = append(c.stack, e) + + // If we're on a leaf page/node then find the specific node. + if e.isLeaf() { + c.nsearch(key) + return + } + + if n != nil { + c.searchNode(key, n) + return + } + c.searchPage(key, p) +} + +func (c *Cursor) searchNode(key []byte, n *node) { + var exact bool + index := sort.Search(len(n.inodes), func(i int) bool { + // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now. + // sort.Search() finds the lowest index where f() != -1 but we need the highest index. + ret := bytes.Compare(n.inodes[i].key, key) + if ret == 0 { + exact = true + } + return ret != -1 + }) + if !exact && index > 0 { + index-- + } + c.stack[len(c.stack)-1].index = index + + // Recursively search to the next page. + c.search(key, n.inodes[index].pgid) +} + +func (c *Cursor) searchPage(key []byte, p *page) { + // Binary search for the correct range. + inodes := p.branchPageElements() + + var exact bool + index := sort.Search(int(p.count), func(i int) bool { + // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now. + // sort.Search() finds the lowest index where f() != -1 but we need the highest index. + ret := bytes.Compare(inodes[i].key(), key) + if ret == 0 { + exact = true + } + return ret != -1 + }) + if !exact && index > 0 { + index-- + } + c.stack[len(c.stack)-1].index = index + + // Recursively search to the next page. + c.search(key, inodes[index].pgid) +} + +// nsearch searches the leaf node on the top of the stack for a key. +func (c *Cursor) nsearch(key []byte) { + e := &c.stack[len(c.stack)-1] + p, n := e.page, e.node + + // If we have a node then search its inodes. + if n != nil { + index := sort.Search(len(n.inodes), func(i int) bool { + return bytes.Compare(n.inodes[i].key, key) != -1 + }) + e.index = index + return + } + + // If we have a page then search its leaf elements. + inodes := p.leafPageElements() + index := sort.Search(int(p.count), func(i int) bool { + return bytes.Compare(inodes[i].key(), key) != -1 + }) + e.index = index +} + +// keyValue returns the key and value of the current leaf element. +func (c *Cursor) keyValue() ([]byte, []byte, uint32) { + ref := &c.stack[len(c.stack)-1] + if ref.count() == 0 || ref.index >= ref.count() { + return nil, nil, 0 + } + + // Retrieve value from node. + if ref.node != nil { + inode := &ref.node.inodes[ref.index] + return inode.key, inode.value, inode.flags + } + + // Or retrieve value from page. + elem := ref.page.leafPageElement(uint16(ref.index)) + return elem.key(), elem.value(), elem.flags +} + +// node returns the node that the cursor is currently positioned on. +func (c *Cursor) node() *node { + _assert(len(c.stack) > 0, "accessing a node with a zero-length cursor stack") + + // If the top of the stack is a leaf node then just return it. + if ref := &c.stack[len(c.stack)-1]; ref.node != nil && ref.isLeaf() { + return ref.node + } + + // Start from root and traverse down the hierarchy. + var n = c.stack[0].node + if n == nil { + n = c.bucket.node(c.stack[0].page.id, nil) + } + for _, ref := range c.stack[:len(c.stack)-1] { + _assert(!n.isLeaf, "expected branch node") + n = n.childAt(int(ref.index)) + } + _assert(n.isLeaf, "expected leaf node") + return n +} + +// elemRef represents a reference to an element on a given page/node. +type elemRef struct { + page *page + node *node + index int +} + +// isLeaf returns whether the ref is pointing at a leaf page/node. +func (r *elemRef) isLeaf() bool { + if r.node != nil { + return r.node.isLeaf + } + return (r.page.flags & leafPageFlag) != 0 +} + +// count returns the number of inodes or page elements. +func (r *elemRef) count() int { + if r.node != nil { + return len(r.node.inodes) + } + return int(r.page.count) +} diff --git a/vendor/github.com/boltdb/bolt/cursor_test.go b/vendor/github.com/boltdb/bolt/cursor_test.go new file mode 100644 index 0000000..562d60f --- /dev/null +++ b/vendor/github.com/boltdb/bolt/cursor_test.go @@ -0,0 +1,817 @@ +package bolt_test + +import ( + "bytes" + "encoding/binary" + "fmt" + "log" + "os" + "reflect" + "sort" + "testing" + "testing/quick" + + "github.com/boltdb/bolt" +) + +// Ensure that a cursor can return a reference to the bucket that created it. +func TestCursor_Bucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if cb := b.Cursor().Bucket(); !reflect.DeepEqual(cb, b) { + t.Fatal("cursor bucket mismatch") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can seek to the appropriate keys. +func TestCursor_Seek(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("0001")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte("0002")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("0003")); err != nil { + t.Fatal(err) + } + + if _, err := b.CreateBucket([]byte("bkt")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + + // Exact match should go to the key. + if k, v := c.Seek([]byte("bar")); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0002")) { + t.Fatalf("unexpected value: %v", v) + } + + // Inexact match should go to the next key. + if k, v := c.Seek([]byte("bas")); !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0003")) { + t.Fatalf("unexpected value: %v", v) + } + + // Low key should go to the first key. + if k, v := c.Seek([]byte("")); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0002")) { + t.Fatalf("unexpected value: %v", v) + } + + // High key should return no key. + if k, v := c.Seek([]byte("zzz")); k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + // Buckets should return their key but no value. + if k, v := c.Seek([]byte("bkt")); !bytes.Equal(k, []byte("bkt")) { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestCursor_Delete(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + const count = 1000 + + // Insert every other key between 0 and $count. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < count; i += 1 { + k := make([]byte, 8) + binary.BigEndian.PutUint64(k, uint64(i)) + if err := b.Put(k, make([]byte, 100)); err != nil { + t.Fatal(err) + } + } + if _, err := b.CreateBucket([]byte("sub")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + bound := make([]byte, 8) + binary.BigEndian.PutUint64(bound, uint64(count/2)) + for key, _ := c.First(); bytes.Compare(key, bound) < 0; key, _ = c.Next() { + if err := c.Delete(); err != nil { + t.Fatal(err) + } + } + + c.Seek([]byte("sub")) + if err := c.Delete(); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("widgets")).Stats() + if stats.KeyN != count/2+1 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can seek to the appropriate keys when there are a +// large number of keys. This test also checks that seek will always move +// forward to the next key. +// +// Related: https://github.com/boltdb/bolt/pull/187 +func TestCursor_Seek_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var count = 10000 + + // Insert every other key between 0 and $count. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < count; i += 100 { + for j := i; j < i+100; j += 2 { + k := make([]byte, 8) + binary.BigEndian.PutUint64(k, uint64(j)) + if err := b.Put(k, make([]byte, 100)); err != nil { + t.Fatal(err) + } + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + for i := 0; i < count; i++ { + seek := make([]byte, 8) + binary.BigEndian.PutUint64(seek, uint64(i)) + + k, _ := c.Seek(seek) + + // The last seek is beyond the end of the the range so + // it should return nil. + if i == count-1 { + if k != nil { + t.Fatal("expected nil key") + } + continue + } + + // Otherwise we should seek to the exact key or the next key. + num := binary.BigEndian.Uint64(k) + if i%2 == 0 { + if num != uint64(i) { + t.Fatalf("unexpected num: %d", num) + } + } else { + if num != uint64(i+1) { + t.Fatalf("unexpected num: %d", num) + } + } + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a cursor can iterate over an empty bucket without error. +func TestCursor_EmptyBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + k, v := c.First() + if k != nil { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can reverse iterate over an empty bucket without error. +func TestCursor_EmptyBucketReverse(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + k, v := c.Last() + if k != nil { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can iterate over a single root with a couple elements. +func TestCursor_Iterate_Leaf(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte{}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte{0}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte{1}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + defer func() { _ = tx.Rollback() }() + + c := tx.Bucket([]byte("widgets")).Cursor() + + k, v := c.First() + if !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{1}) { + t.Fatalf("unexpected value: %v", v) + } + + k, v = c.Next() + if !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{}) { + t.Fatalf("unexpected value: %v", v) + } + + k, v = c.Next() + if !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{0}) { + t.Fatalf("unexpected value: %v", v) + } + + k, v = c.Next() + if k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + k, v = c.Next() + if k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can iterate in reverse over a single root with a couple elements. +func TestCursor_LeafRootReverse(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte{}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte{0}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte{1}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + + if k, v := c.Last(); !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{0}) { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Prev(); !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{}) { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Prev(); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{1}) { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Prev(); k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + if k, v := c.Prev(); k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can restart from the beginning. +func TestCursor_Restart(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte{}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte{}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + + if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } + if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } + + if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } + if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a cursor can skip over empty pages that have been deleted. +func TestCursor_First_EmptyPages(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create 1000 keys in the "widgets" bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 1000; i++ { + if err := b.Put(u64tob(uint64(i)), []byte{}); err != nil { + t.Fatal(err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + + // Delete half the keys and then try to iterate. + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < 600; i++ { + if err := b.Delete(u64tob(uint64(i))); err != nil { + t.Fatal(err) + } + } + + c := b.Cursor() + var n int + for k, _ := c.First(); k != nil; k, _ = c.Next() { + n++ + } + if n != 400 { + t.Fatalf("unexpected key count: %d", n) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx can iterate over all elements in a bucket. +func TestCursor_QuickCheck(t *testing.T) { + f := func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + // Sort test data. + sort.Sort(items) + + // Iterate over all items and check consistency. + var index = 0 + tx, err = db.Begin(false) + if err != nil { + t.Fatal(err) + } + + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.First(); k != nil && index < len(items); k, v = c.Next() { + if !bytes.Equal(k, items[index].Key) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, items[index].Value) { + t.Fatalf("unexpected value: %v", v) + } + index++ + } + if len(items) != index { + t.Fatalf("unexpected item count: %v, expected %v", len(items), index) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + return true + } + if err := quick.Check(f, qconfig()); err != nil { + t.Error(err) + } +} + +// Ensure that a transaction can iterate over all elements in a bucket in reverse. +func TestCursor_QuickCheck_Reverse(t *testing.T) { + f := func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + // Sort test data. + sort.Sort(revtestdata(items)) + + // Iterate over all items and check consistency. + var index = 0 + tx, err = db.Begin(false) + if err != nil { + t.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.Last(); k != nil && index < len(items); k, v = c.Prev() { + if !bytes.Equal(k, items[index].Key) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, items[index].Value) { + t.Fatalf("unexpected value: %v", v) + } + index++ + } + if len(items) != index { + t.Fatalf("unexpected item count: %v, expected %v", len(items), index) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + return true + } + if err := quick.Check(f, qconfig()); err != nil { + t.Error(err) + } +} + +// Ensure that a Tx cursor can iterate over subbuckets. +func TestCursor_QuickCheck_BucketsOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("bar")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("baz")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + var names []string + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + names = append(names, string(k)) + if v != nil { + t.Fatalf("unexpected value: %v", v) + } + } + if !reflect.DeepEqual(names, []string{"bar", "baz", "foo"}) { + t.Fatalf("unexpected names: %+v", names) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can reverse iterate over subbuckets. +func TestCursor_QuickCheck_BucketsOnly_Reverse(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("bar")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("baz")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + var names []string + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.Last(); k != nil; k, v = c.Prev() { + names = append(names, string(k)) + if v != nil { + t.Fatalf("unexpected value: %v", v) + } + } + if !reflect.DeepEqual(names, []string{"foo", "baz", "bar"}) { + t.Fatalf("unexpected names: %+v", names) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func ExampleCursor() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a new bucket. + b, err := tx.CreateBucket([]byte("animals")) + if err != nil { + return err + } + + // Insert data into a bucket. + if err := b.Put([]byte("dog"), []byte("fun")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("cat"), []byte("lame")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("liger"), []byte("awesome")); err != nil { + log.Fatal(err) + } + + // Create a cursor for iteration. + c := b.Cursor() + + // Iterate over items in sorted key order. This starts from the + // first key/value pair and updates the k/v variables to the + // next key/value on each iteration. + // + // The loop finishes at the end of the cursor when a nil key is returned. + for k, v := c.First(); k != nil; k, v = c.Next() { + fmt.Printf("A %s is %s.\n", k, v) + } + + return nil + }); err != nil { + log.Fatal(err) + } + + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // A cat is lame. + // A dog is fun. + // A liger is awesome. +} + +func ExampleCursor_reverse() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a new bucket. + b, err := tx.CreateBucket([]byte("animals")) + if err != nil { + return err + } + + // Insert data into a bucket. + if err := b.Put([]byte("dog"), []byte("fun")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("cat"), []byte("lame")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("liger"), []byte("awesome")); err != nil { + log.Fatal(err) + } + + // Create a cursor for iteration. + c := b.Cursor() + + // Iterate over items in reverse sorted key order. This starts + // from the last key/value pair and updates the k/v variables to + // the previous key/value on each iteration. + // + // The loop finishes at the beginning of the cursor when a nil key + // is returned. + for k, v := c.Last(); k != nil; k, v = c.Prev() { + fmt.Printf("A %s is %s.\n", k, v) + } + + return nil + }); err != nil { + log.Fatal(err) + } + + // Close the database to release the file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // A liger is awesome. + // A dog is fun. + // A cat is lame. +} diff --git a/vendor/github.com/boltdb/bolt/db.go b/vendor/github.com/boltdb/bolt/db.go new file mode 100644 index 0000000..f352ff1 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/db.go @@ -0,0 +1,1039 @@ +package bolt + +import ( + "errors" + "fmt" + "hash/fnv" + "log" + "os" + "runtime" + "runtime/debug" + "strings" + "sync" + "time" + "unsafe" +) + +// The largest step that can be taken when remapping the mmap. +const maxMmapStep = 1 << 30 // 1GB + +// The data file format version. +const version = 2 + +// Represents a marker value to indicate that a file is a Bolt DB. +const magic uint32 = 0xED0CDAED + +// IgnoreNoSync specifies whether the NoSync field of a DB is ignored when +// syncing changes to a file. This is required as some operating systems, +// such as OpenBSD, do not have a unified buffer cache (UBC) and writes +// must be synchronized using the msync(2) syscall. +const IgnoreNoSync = runtime.GOOS == "openbsd" + +// Default values if not set in a DB instance. +const ( + DefaultMaxBatchSize int = 1000 + DefaultMaxBatchDelay = 10 * time.Millisecond + DefaultAllocSize = 16 * 1024 * 1024 +) + +// default page size for db is set to the OS page size. +var defaultPageSize = os.Getpagesize() + +// DB represents a collection of buckets persisted to a file on disk. +// All data access is performed through transactions which can be obtained through the DB. +// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called. +type DB struct { + // When enabled, the database will perform a Check() after every commit. + // A panic is issued if the database is in an inconsistent state. This + // flag has a large performance impact so it should only be used for + // debugging purposes. + StrictMode bool + + // Setting the NoSync flag will cause the database to skip fsync() + // calls after each commit. This can be useful when bulk loading data + // into a database and you can restart the bulk load in the event of + // a system failure or database corruption. Do not set this flag for + // normal use. + // + // If the package global IgnoreNoSync constant is true, this value is + // ignored. See the comment on that constant for more details. + // + // THIS IS UNSAFE. PLEASE USE WITH CAUTION. + NoSync bool + + // When true, skips the truncate call when growing the database. + // Setting this to true is only safe on non-ext3/ext4 systems. + // Skipping truncation avoids preallocation of hard drive space and + // bypasses a truncate() and fsync() syscall on remapping. + // + // https://github.com/boltdb/bolt/issues/284 + NoGrowSync bool + + // If you want to read the entire database fast, you can set MmapFlag to + // syscall.MAP_POPULATE on Linux 2.6.23+ for sequential read-ahead. + MmapFlags int + + // MaxBatchSize is the maximum size of a batch. Default value is + // copied from DefaultMaxBatchSize in Open. + // + // If <=0, disables batching. + // + // Do not change concurrently with calls to Batch. + MaxBatchSize int + + // MaxBatchDelay is the maximum delay before a batch starts. + // Default value is copied from DefaultMaxBatchDelay in Open. + // + // If <=0, effectively disables batching. + // + // Do not change concurrently with calls to Batch. + MaxBatchDelay time.Duration + + // AllocSize is the amount of space allocated when the database + // needs to create new pages. This is done to amortize the cost + // of truncate() and fsync() when growing the data file. + AllocSize int + + path string + file *os.File + lockfile *os.File // windows only + dataref []byte // mmap'ed readonly, write throws SEGV + data *[maxMapSize]byte + datasz int + filesz int // current on disk file size + meta0 *meta + meta1 *meta + pageSize int + opened bool + rwtx *Tx + txs []*Tx + freelist *freelist + stats Stats + + pagePool sync.Pool + + batchMu sync.Mutex + batch *batch + + rwlock sync.Mutex // Allows only one writer at a time. + metalock sync.Mutex // Protects meta page access. + mmaplock sync.RWMutex // Protects mmap access during remapping. + statlock sync.RWMutex // Protects stats access. + + ops struct { + writeAt func(b []byte, off int64) (n int, err error) + } + + // Read only mode. + // When true, Update() and Begin(true) return ErrDatabaseReadOnly immediately. + readOnly bool +} + +// Path returns the path to currently open database file. +func (db *DB) Path() string { + return db.path +} + +// GoString returns the Go string representation of the database. +func (db *DB) GoString() string { + return fmt.Sprintf("bolt.DB{path:%q}", db.path) +} + +// String returns the string representation of the database. +func (db *DB) String() string { + return fmt.Sprintf("DB<%q>", db.path) +} + +// Open creates and opens a database at the given path. +// If the file does not exist then it will be created automatically. +// Passing in nil options will cause Bolt to open the database with the default options. +func Open(path string, mode os.FileMode, options *Options) (*DB, error) { + var db = &DB{opened: true} + + // Set default options if no options are provided. + if options == nil { + options = DefaultOptions + } + db.NoGrowSync = options.NoGrowSync + db.MmapFlags = options.MmapFlags + + // Set default values for later DB operations. + db.MaxBatchSize = DefaultMaxBatchSize + db.MaxBatchDelay = DefaultMaxBatchDelay + db.AllocSize = DefaultAllocSize + + flag := os.O_RDWR + if options.ReadOnly { + flag = os.O_RDONLY + db.readOnly = true + } + + // Open data file and separate sync handler for metadata writes. + db.path = path + var err error + if db.file, err = os.OpenFile(db.path, flag|os.O_CREATE, mode); err != nil { + _ = db.close() + return nil, err + } + + // Lock file so that other processes using Bolt in read-write mode cannot + // use the database at the same time. This would cause corruption since + // the two processes would write meta pages and free pages separately. + // The database file is locked exclusively (only one process can grab the lock) + // if !options.ReadOnly. + // The database file is locked using the shared lock (more than one process may + // hold a lock at the same time) otherwise (options.ReadOnly is set). + if err := flock(db, mode, !db.readOnly, options.Timeout); err != nil { + _ = db.close() + return nil, err + } + + // Default values for test hooks + db.ops.writeAt = db.file.WriteAt + + // Initialize the database if it doesn't exist. + if info, err := db.file.Stat(); err != nil { + return nil, err + } else if info.Size() == 0 { + // Initialize new files with meta pages. + if err := db.init(); err != nil { + return nil, err + } + } else { + // Read the first meta page to determine the page size. + var buf [0x1000]byte + if _, err := db.file.ReadAt(buf[:], 0); err == nil { + m := db.pageInBuffer(buf[:], 0).meta() + if err := m.validate(); err != nil { + // If we can't read the page size, we can assume it's the same + // as the OS -- since that's how the page size was chosen in the + // first place. + // + // If the first page is invalid and this OS uses a different + // page size than what the database was created with then we + // are out of luck and cannot access the database. + db.pageSize = os.Getpagesize() + } else { + db.pageSize = int(m.pageSize) + } + } + } + + // Initialize page pool. + db.pagePool = sync.Pool{ + New: func() interface{} { + return make([]byte, db.pageSize) + }, + } + + // Memory map the data file. + if err := db.mmap(options.InitialMmapSize); err != nil { + _ = db.close() + return nil, err + } + + // Read in the freelist. + db.freelist = newFreelist() + db.freelist.read(db.page(db.meta().freelist)) + + // Mark the database as opened and return. + return db, nil +} + +// mmap opens the underlying memory-mapped file and initializes the meta references. +// minsz is the minimum size that the new mmap can be. +func (db *DB) mmap(minsz int) error { + db.mmaplock.Lock() + defer db.mmaplock.Unlock() + + info, err := db.file.Stat() + if err != nil { + return fmt.Errorf("mmap stat error: %s", err) + } else if int(info.Size()) < db.pageSize*2 { + return fmt.Errorf("file size too small") + } + + // Ensure the size is at least the minimum size. + var size = int(info.Size()) + if size < minsz { + size = minsz + } + size, err = db.mmapSize(size) + if err != nil { + return err + } + + // Dereference all mmap references before unmapping. + if db.rwtx != nil { + db.rwtx.root.dereference() + } + + // Unmap existing data before continuing. + if err := db.munmap(); err != nil { + return err + } + + // Memory-map the data file as a byte slice. + if err := mmap(db, size); err != nil { + return err + } + + // Save references to the meta pages. + db.meta0 = db.page(0).meta() + db.meta1 = db.page(1).meta() + + // Validate the meta pages. We only return an error if both meta pages fail + // validation, since meta0 failing validation means that it wasn't saved + // properly -- but we can recover using meta1. And vice-versa. + err0 := db.meta0.validate() + err1 := db.meta1.validate() + if err0 != nil && err1 != nil { + return err0 + } + + return nil +} + +// munmap unmaps the data file from memory. +func (db *DB) munmap() error { + if err := munmap(db); err != nil { + return fmt.Errorf("unmap error: " + err.Error()) + } + return nil +} + +// mmapSize determines the appropriate size for the mmap given the current size +// of the database. The minimum size is 32KB and doubles until it reaches 1GB. +// Returns an error if the new mmap size is greater than the max allowed. +func (db *DB) mmapSize(size int) (int, error) { + // Double the size from 32KB until 1GB. + for i := uint(15); i <= 30; i++ { + if size <= 1< maxMapSize { + return 0, fmt.Errorf("mmap too large") + } + + // If larger than 1GB then grow by 1GB at a time. + sz := int64(size) + if remainder := sz % int64(maxMmapStep); remainder > 0 { + sz += int64(maxMmapStep) - remainder + } + + // Ensure that the mmap size is a multiple of the page size. + // This should always be true since we're incrementing in MBs. + pageSize := int64(db.pageSize) + if (sz % pageSize) != 0 { + sz = ((sz / pageSize) + 1) * pageSize + } + + // If we've exceeded the max size then only grow up to the max size. + if sz > maxMapSize { + sz = maxMapSize + } + + return int(sz), nil +} + +// init creates a new database file and initializes its meta pages. +func (db *DB) init() error { + // Set the page size to the OS page size. + db.pageSize = os.Getpagesize() + + // Create two meta pages on a buffer. + buf := make([]byte, db.pageSize*4) + for i := 0; i < 2; i++ { + p := db.pageInBuffer(buf[:], pgid(i)) + p.id = pgid(i) + p.flags = metaPageFlag + + // Initialize the meta page. + m := p.meta() + m.magic = magic + m.version = version + m.pageSize = uint32(db.pageSize) + m.freelist = 2 + m.root = bucket{root: 3} + m.pgid = 4 + m.txid = txid(i) + m.checksum = m.sum64() + } + + // Write an empty freelist at page 3. + p := db.pageInBuffer(buf[:], pgid(2)) + p.id = pgid(2) + p.flags = freelistPageFlag + p.count = 0 + + // Write an empty leaf page at page 4. + p = db.pageInBuffer(buf[:], pgid(3)) + p.id = pgid(3) + p.flags = leafPageFlag + p.count = 0 + + // Write the buffer to our data file. + if _, err := db.ops.writeAt(buf, 0); err != nil { + return err + } + if err := fdatasync(db); err != nil { + return err + } + + return nil +} + +// Close releases all database resources. +// All transactions must be closed before closing the database. +func (db *DB) Close() error { + db.rwlock.Lock() + defer db.rwlock.Unlock() + + db.metalock.Lock() + defer db.metalock.Unlock() + + db.mmaplock.RLock() + defer db.mmaplock.RUnlock() + + return db.close() +} + +func (db *DB) close() error { + if !db.opened { + return nil + } + + db.opened = false + + db.freelist = nil + + // Clear ops. + db.ops.writeAt = nil + + // Close the mmap. + if err := db.munmap(); err != nil { + return err + } + + // Close file handles. + if db.file != nil { + // No need to unlock read-only file. + if !db.readOnly { + // Unlock the file. + if err := funlock(db); err != nil { + log.Printf("bolt.Close(): funlock error: %s", err) + } + } + + // Close the file descriptor. + if err := db.file.Close(); err != nil { + return fmt.Errorf("db file close: %s", err) + } + db.file = nil + } + + db.path = "" + return nil +} + +// Begin starts a new transaction. +// Multiple read-only transactions can be used concurrently but only one +// write transaction can be used at a time. Starting multiple write transactions +// will cause the calls to block and be serialized until the current write +// transaction finishes. +// +// Transactions should not be dependent on one another. Opening a read +// transaction and a write transaction in the same goroutine can cause the +// writer to deadlock because the database periodically needs to re-mmap itself +// as it grows and it cannot do that while a read transaction is open. +// +// If a long running read transaction (for example, a snapshot transaction) is +// needed, you might want to set DB.InitialMmapSize to a large enough value +// to avoid potential blocking of write transaction. +// +// IMPORTANT: You must close read-only transactions after you are finished or +// else the database will not reclaim old pages. +func (db *DB) Begin(writable bool) (*Tx, error) { + if writable { + return db.beginRWTx() + } + return db.beginTx() +} + +func (db *DB) beginTx() (*Tx, error) { + // Lock the meta pages while we initialize the transaction. We obtain + // the meta lock before the mmap lock because that's the order that the + // write transaction will obtain them. + db.metalock.Lock() + + // Obtain a read-only lock on the mmap. When the mmap is remapped it will + // obtain a write lock so all transactions must finish before it can be + // remapped. + db.mmaplock.RLock() + + // Exit if the database is not open yet. + if !db.opened { + db.mmaplock.RUnlock() + db.metalock.Unlock() + return nil, ErrDatabaseNotOpen + } + + // Create a transaction associated with the database. + t := &Tx{} + t.init(db) + + // Keep track of transaction until it closes. + db.txs = append(db.txs, t) + n := len(db.txs) + + // Unlock the meta pages. + db.metalock.Unlock() + + // Update the transaction stats. + db.statlock.Lock() + db.stats.TxN++ + db.stats.OpenTxN = n + db.statlock.Unlock() + + return t, nil +} + +func (db *DB) beginRWTx() (*Tx, error) { + // If the database was opened with Options.ReadOnly, return an error. + if db.readOnly { + return nil, ErrDatabaseReadOnly + } + + // Obtain writer lock. This is released by the transaction when it closes. + // This enforces only one writer transaction at a time. + db.rwlock.Lock() + + // Once we have the writer lock then we can lock the meta pages so that + // we can set up the transaction. + db.metalock.Lock() + defer db.metalock.Unlock() + + // Exit if the database is not open yet. + if !db.opened { + db.rwlock.Unlock() + return nil, ErrDatabaseNotOpen + } + + // Create a transaction associated with the database. + t := &Tx{writable: true} + t.init(db) + db.rwtx = t + + // Free any pages associated with closed read-only transactions. + var minid txid = 0xFFFFFFFFFFFFFFFF + for _, t := range db.txs { + if t.meta.txid < minid { + minid = t.meta.txid + } + } + if minid > 0 { + db.freelist.release(minid - 1) + } + + return t, nil +} + +// removeTx removes a transaction from the database. +func (db *DB) removeTx(tx *Tx) { + // Release the read lock on the mmap. + db.mmaplock.RUnlock() + + // Use the meta lock to restrict access to the DB object. + db.metalock.Lock() + + // Remove the transaction. + for i, t := range db.txs { + if t == tx { + last := len(db.txs) - 1 + db.txs[i] = db.txs[last] + db.txs[last] = nil + db.txs = db.txs[:last] + break + } + } + n := len(db.txs) + + // Unlock the meta pages. + db.metalock.Unlock() + + // Merge statistics. + db.statlock.Lock() + db.stats.OpenTxN = n + db.stats.TxStats.add(&tx.stats) + db.statlock.Unlock() +} + +// Update executes a function within the context of a read-write managed transaction. +// If no error is returned from the function then the transaction is committed. +// If an error is returned then the entire transaction is rolled back. +// Any error that is returned from the function or returned from the commit is +// returned from the Update() method. +// +// Attempting to manually commit or rollback within the function will cause a panic. +func (db *DB) Update(fn func(*Tx) error) error { + t, err := db.Begin(true) + if err != nil { + return err + } + + // Make sure the transaction rolls back in the event of a panic. + defer func() { + if t.db != nil { + t.rollback() + } + }() + + // Mark as a managed tx so that the inner function cannot manually commit. + t.managed = true + + // If an error is returned from the function then rollback and return error. + err = fn(t) + t.managed = false + if err != nil { + _ = t.Rollback() + return err + } + + return t.Commit() +} + +// View executes a function within the context of a managed read-only transaction. +// Any error that is returned from the function is returned from the View() method. +// +// Attempting to manually rollback within the function will cause a panic. +func (db *DB) View(fn func(*Tx) error) error { + t, err := db.Begin(false) + if err != nil { + return err + } + + // Make sure the transaction rolls back in the event of a panic. + defer func() { + if t.db != nil { + t.rollback() + } + }() + + // Mark as a managed tx so that the inner function cannot manually rollback. + t.managed = true + + // If an error is returned from the function then pass it through. + err = fn(t) + t.managed = false + if err != nil { + _ = t.Rollback() + return err + } + + if err := t.Rollback(); err != nil { + return err + } + + return nil +} + +// Batch calls fn as part of a batch. It behaves similar to Update, +// except: +// +// 1. concurrent Batch calls can be combined into a single Bolt +// transaction. +// +// 2. the function passed to Batch may be called multiple times, +// regardless of whether it returns error or not. +// +// This means that Batch function side effects must be idempotent and +// take permanent effect only after a successful return is seen in +// caller. +// +// The maximum batch size and delay can be adjusted with DB.MaxBatchSize +// and DB.MaxBatchDelay, respectively. +// +// Batch is only useful when there are multiple goroutines calling it. +func (db *DB) Batch(fn func(*Tx) error) error { + errCh := make(chan error, 1) + + db.batchMu.Lock() + if (db.batch == nil) || (db.batch != nil && len(db.batch.calls) >= db.MaxBatchSize) { + // There is no existing batch, or the existing batch is full; start a new one. + db.batch = &batch{ + db: db, + } + db.batch.timer = time.AfterFunc(db.MaxBatchDelay, db.batch.trigger) + } + db.batch.calls = append(db.batch.calls, call{fn: fn, err: errCh}) + if len(db.batch.calls) >= db.MaxBatchSize { + // wake up batch, it's ready to run + go db.batch.trigger() + } + db.batchMu.Unlock() + + err := <-errCh + if err == trySolo { + err = db.Update(fn) + } + return err +} + +type call struct { + fn func(*Tx) error + err chan<- error +} + +type batch struct { + db *DB + timer *time.Timer + start sync.Once + calls []call +} + +// trigger runs the batch if it hasn't already been run. +func (b *batch) trigger() { + b.start.Do(b.run) +} + +// run performs the transactions in the batch and communicates results +// back to DB.Batch. +func (b *batch) run() { + b.db.batchMu.Lock() + b.timer.Stop() + // Make sure no new work is added to this batch, but don't break + // other batches. + if b.db.batch == b { + b.db.batch = nil + } + b.db.batchMu.Unlock() + +retry: + for len(b.calls) > 0 { + var failIdx = -1 + err := b.db.Update(func(tx *Tx) error { + for i, c := range b.calls { + if err := safelyCall(c.fn, tx); err != nil { + failIdx = i + return err + } + } + return nil + }) + + if failIdx >= 0 { + // take the failing transaction out of the batch. it's + // safe to shorten b.calls here because db.batch no longer + // points to us, and we hold the mutex anyway. + c := b.calls[failIdx] + b.calls[failIdx], b.calls = b.calls[len(b.calls)-1], b.calls[:len(b.calls)-1] + // tell the submitter re-run it solo, continue with the rest of the batch + c.err <- trySolo + continue retry + } + + // pass success, or bolt internal errors, to all callers + for _, c := range b.calls { + if c.err != nil { + c.err <- err + } + } + break retry + } +} + +// trySolo is a special sentinel error value used for signaling that a +// transaction function should be re-run. It should never be seen by +// callers. +var trySolo = errors.New("batch function returned an error and should be re-run solo") + +type panicked struct { + reason interface{} +} + +func (p panicked) Error() string { + if err, ok := p.reason.(error); ok { + return err.Error() + } + return fmt.Sprintf("panic: %v", p.reason) +} + +func safelyCall(fn func(*Tx) error, tx *Tx) (err error) { + defer func() { + if p := recover(); p != nil { + err = panicked{p} + } + }() + return fn(tx) +} + +// Sync executes fdatasync() against the database file handle. +// +// This is not necessary under normal operation, however, if you use NoSync +// then it allows you to force the database file to sync against the disk. +func (db *DB) Sync() error { return fdatasync(db) } + +// Stats retrieves ongoing performance stats for the database. +// This is only updated when a transaction closes. +func (db *DB) Stats() Stats { + db.statlock.RLock() + defer db.statlock.RUnlock() + return db.stats +} + +// This is for internal access to the raw data bytes from the C cursor, use +// carefully, or not at all. +func (db *DB) Info() *Info { + return &Info{uintptr(unsafe.Pointer(&db.data[0])), db.pageSize} +} + +// page retrieves a page reference from the mmap based on the current page size. +func (db *DB) page(id pgid) *page { + pos := id * pgid(db.pageSize) + return (*page)(unsafe.Pointer(&db.data[pos])) +} + +// pageInBuffer retrieves a page reference from a given byte array based on the current page size. +func (db *DB) pageInBuffer(b []byte, id pgid) *page { + return (*page)(unsafe.Pointer(&b[id*pgid(db.pageSize)])) +} + +// meta retrieves the current meta page reference. +func (db *DB) meta() *meta { + // We have to return the meta with the highest txid which doesn't fail + // validation. Otherwise, we can cause errors when in fact the database is + // in a consistent state. metaA is the one with the higher txid. + metaA := db.meta0 + metaB := db.meta1 + if db.meta1.txid > db.meta0.txid { + metaA = db.meta1 + metaB = db.meta0 + } + + // Use higher meta page if valid. Otherwise fallback to previous, if valid. + if err := metaA.validate(); err == nil { + return metaA + } else if err := metaB.validate(); err == nil { + return metaB + } + + // This should never be reached, because both meta1 and meta0 were validated + // on mmap() and we do fsync() on every write. + panic("bolt.DB.meta(): invalid meta pages") +} + +// allocate returns a contiguous block of memory starting at a given page. +func (db *DB) allocate(count int) (*page, error) { + // Allocate a temporary buffer for the page. + var buf []byte + if count == 1 { + buf = db.pagePool.Get().([]byte) + } else { + buf = make([]byte, count*db.pageSize) + } + p := (*page)(unsafe.Pointer(&buf[0])) + p.overflow = uint32(count - 1) + + // Use pages from the freelist if they are available. + if p.id = db.freelist.allocate(count); p.id != 0 { + return p, nil + } + + // Resize mmap() if we're at the end. + p.id = db.rwtx.meta.pgid + var minsz = int((p.id+pgid(count))+1) * db.pageSize + if minsz >= db.datasz { + if err := db.mmap(minsz); err != nil { + return nil, fmt.Errorf("mmap allocate error: %s", err) + } + } + + // Move the page id high water mark. + db.rwtx.meta.pgid += pgid(count) + + return p, nil +} + +// grow grows the size of the database to the given sz. +func (db *DB) grow(sz int) error { + // Ignore if the new size is less than available file size. + if sz <= db.filesz { + return nil + } + + // If the data is smaller than the alloc size then only allocate what's needed. + // Once it goes over the allocation size then allocate in chunks. + if db.datasz < db.AllocSize { + sz = db.datasz + } else { + sz += db.AllocSize + } + + // Truncate and fsync to ensure file size metadata is flushed. + // https://github.com/boltdb/bolt/issues/284 + if !db.NoGrowSync && !db.readOnly { + if runtime.GOOS != "windows" { + if err := db.file.Truncate(int64(sz)); err != nil { + return fmt.Errorf("file resize error: %s", err) + } + } + if err := db.file.Sync(); err != nil { + return fmt.Errorf("file sync error: %s", err) + } + } + + db.filesz = sz + return nil +} + +func (db *DB) IsReadOnly() bool { + return db.readOnly +} + +// Options represents the options that can be set when opening a database. +type Options struct { + // Timeout is the amount of time to wait to obtain a file lock. + // When set to zero it will wait indefinitely. This option is only + // available on Darwin and Linux. + Timeout time.Duration + + // Sets the DB.NoGrowSync flag before memory mapping the file. + NoGrowSync bool + + // Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to + // grab a shared lock (UNIX). + ReadOnly bool + + // Sets the DB.MmapFlags flag before memory mapping the file. + MmapFlags int + + // InitialMmapSize is the initial mmap size of the database + // in bytes. Read transactions won't block write transaction + // if the InitialMmapSize is large enough to hold database mmap + // size. (See DB.Begin for more information) + // + // If <=0, the initial map size is 0. + // If initialMmapSize is smaller than the previous database size, + // it takes no effect. + InitialMmapSize int +} + +// DefaultOptions represent the options used if nil options are passed into Open(). +// No timeout is used which will cause Bolt to wait indefinitely for a lock. +var DefaultOptions = &Options{ + Timeout: 0, + NoGrowSync: false, +} + +// Stats represents statistics about the database. +type Stats struct { + // Freelist stats + FreePageN int // total number of free pages on the freelist + PendingPageN int // total number of pending pages on the freelist + FreeAlloc int // total bytes allocated in free pages + FreelistInuse int // total bytes used by the freelist + + // Transaction stats + TxN int // total number of started read transactions + OpenTxN int // number of currently open read transactions + + TxStats TxStats // global, ongoing stats. +} + +// Sub calculates and returns the difference between two sets of database stats. +// This is useful when obtaining stats at two different points and time and +// you need the performance counters that occurred within that time span. +func (s *Stats) Sub(other *Stats) Stats { + if other == nil { + return *s + } + var diff Stats + diff.FreePageN = s.FreePageN + diff.PendingPageN = s.PendingPageN + diff.FreeAlloc = s.FreeAlloc + diff.FreelistInuse = s.FreelistInuse + diff.TxN = s.TxN - other.TxN + diff.TxStats = s.TxStats.Sub(&other.TxStats) + return diff +} + +func (s *Stats) add(other *Stats) { + s.TxStats.add(&other.TxStats) +} + +type Info struct { + Data uintptr + PageSize int +} + +type meta struct { + magic uint32 + version uint32 + pageSize uint32 + flags uint32 + root bucket + freelist pgid + pgid pgid + txid txid + checksum uint64 +} + +// validate checks the marker bytes and version of the meta page to ensure it matches this binary. +func (m *meta) validate() error { + if m.magic != magic { + return ErrInvalid + } else if m.version != version { + return ErrVersionMismatch + } else if m.checksum != 0 && m.checksum != m.sum64() { + return ErrChecksum + } + return nil +} + +// copy copies one meta object to another. +func (m *meta) copy(dest *meta) { + *dest = *m +} + +// write writes the meta onto a page. +func (m *meta) write(p *page) { + if m.root.root >= m.pgid { + panic(fmt.Sprintf("root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid)) + } else if m.freelist >= m.pgid { + panic(fmt.Sprintf("freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid)) + } + + // Page id is either going to be 0 or 1 which we can determine by the transaction ID. + p.id = pgid(m.txid % 2) + p.flags |= metaPageFlag + + // Calculate the checksum. + m.checksum = m.sum64() + + m.copy(p.meta()) +} + +// generates the checksum for the meta. +func (m *meta) sum64() uint64 { + var h = fnv.New64a() + _, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:]) + return h.Sum64() +} + +// _assert will panic with a given formatted message if the given condition is false. +func _assert(condition bool, msg string, v ...interface{}) { + if !condition { + panic(fmt.Sprintf("assertion failed: "+msg, v...)) + } +} + +func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) } +func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) } + +func printstack() { + stack := strings.Join(strings.Split(string(debug.Stack()), "\n")[2:], "\n") + fmt.Fprintln(os.Stderr, stack) +} diff --git a/vendor/github.com/boltdb/bolt/db_test.go b/vendor/github.com/boltdb/bolt/db_test.go new file mode 100644 index 0000000..3034d4f --- /dev/null +++ b/vendor/github.com/boltdb/bolt/db_test.go @@ -0,0 +1,1545 @@ +package bolt_test + +import ( + "bytes" + "encoding/binary" + "errors" + "flag" + "fmt" + "hash/fnv" + "io/ioutil" + "log" + "os" + "path/filepath" + "regexp" + "sort" + "strings" + "sync" + "testing" + "time" + "unsafe" + + "github.com/boltdb/bolt" +) + +var statsFlag = flag.Bool("stats", false, "show performance stats") + +// version is the data file format version. +const version = 2 + +// magic is the marker value to indicate that a file is a Bolt DB. +const magic uint32 = 0xED0CDAED + +// pageSize is the size of one page in the data file. +const pageSize = 4096 + +// pageHeaderSize is the size of a page header. +const pageHeaderSize = 16 + +// meta represents a simplified version of a database meta page for testing. +type meta struct { + magic uint32 + version uint32 + _ uint32 + _ uint32 + _ [16]byte + _ uint64 + pgid uint64 + _ uint64 + checksum uint64 +} + +// Ensure that a database can be opened without error. +func TestOpen(t *testing.T) { + path := tempfile() + db, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } else if db == nil { + t.Fatal("expected db") + } + + if s := db.Path(); s != path { + t.Fatalf("unexpected path: %s", s) + } + + if err := db.Close(); err != nil { + t.Fatal(err) + } +} + +// Ensure that opening a database with a blank path returns an error. +func TestOpen_ErrPathRequired(t *testing.T) { + _, err := bolt.Open("", 0666, nil) + if err == nil { + t.Fatalf("expected error") + } +} + +// Ensure that opening a database with a bad path returns an error. +func TestOpen_ErrNotExists(t *testing.T) { + _, err := bolt.Open(filepath.Join(tempfile(), "bad-path"), 0666, nil) + if err == nil { + t.Fatal("expected error") + } +} + +// Ensure that opening a file that is not a Bolt database returns ErrInvalid. +func TestOpen_ErrInvalid(t *testing.T) { + path := tempfile() + + f, err := os.Create(path) + if err != nil { + t.Fatal(err) + } + if _, err := fmt.Fprintln(f, "this is not a bolt database"); err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + defer os.Remove(path) + + if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrInvalid { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that opening a file with two invalid versions returns ErrVersionMismatch. +func TestOpen_ErrVersionMismatch(t *testing.T) { + if pageSize != os.Getpagesize() { + t.Skip("page size mismatch") + } + + // Create empty database. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + // Close database. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + + // Read data file. + buf, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + // Rewrite meta pages. + meta0 := (*meta)(unsafe.Pointer(&buf[pageHeaderSize])) + meta0.version++ + meta1 := (*meta)(unsafe.Pointer(&buf[pageSize+pageHeaderSize])) + meta1.version++ + if err := ioutil.WriteFile(path, buf, 0666); err != nil { + t.Fatal(err) + } + + // Reopen data file. + if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrVersionMismatch { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that opening a file with two invalid checksums returns ErrChecksum. +func TestOpen_ErrChecksum(t *testing.T) { + if pageSize != os.Getpagesize() { + t.Skip("page size mismatch") + } + + // Create empty database. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + // Close database. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + + // Read data file. + buf, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + // Rewrite meta pages. + meta0 := (*meta)(unsafe.Pointer(&buf[pageHeaderSize])) + meta0.pgid++ + meta1 := (*meta)(unsafe.Pointer(&buf[pageSize+pageHeaderSize])) + meta1.pgid++ + if err := ioutil.WriteFile(path, buf, 0666); err != nil { + t.Fatal(err) + } + + // Reopen data file. + if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrChecksum { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that opening a database does not increase its size. +// https://github.com/boltdb/bolt/issues/291 +func TestOpen_Size(t *testing.T) { + // Open a data file. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + pagesize := db.Info().PageSize + + // Insert until we get above the minimum 4MB size. + if err := db.Update(func(tx *bolt.Tx) error { + b, _ := tx.CreateBucketIfNotExists([]byte("data")) + for i := 0; i < 10000; i++ { + if err := b.Put([]byte(fmt.Sprintf("%04d", i)), make([]byte, 1000)); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Close database and grab the size. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + sz := fileSize(path) + if sz == 0 { + t.Fatalf("unexpected new file size: %d", sz) + } + + // Reopen database, update, and check size again. + db0, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db0.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + if err := db0.Close(); err != nil { + t.Fatal(err) + } + newSz := fileSize(path) + if newSz == 0 { + t.Fatalf("unexpected new file size: %d", newSz) + } + + // Compare the original size with the new size. + // db size might increase by a few page sizes due to the new small update. + if sz < newSz-5*int64(pagesize) { + t.Fatalf("unexpected file growth: %d => %d", sz, newSz) + } +} + +// Ensure that opening a database beyond the max step size does not increase its size. +// https://github.com/boltdb/bolt/issues/303 +func TestOpen_Size_Large(t *testing.T) { + if testing.Short() { + t.Skip("short mode") + } + + // Open a data file. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + pagesize := db.Info().PageSize + + // Insert until we get above the minimum 4MB size. + var index uint64 + for i := 0; i < 10000; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + b, _ := tx.CreateBucketIfNotExists([]byte("data")) + for j := 0; j < 1000; j++ { + if err := b.Put(u64tob(index), make([]byte, 50)); err != nil { + t.Fatal(err) + } + index++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + // Close database and grab the size. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + sz := fileSize(path) + if sz == 0 { + t.Fatalf("unexpected new file size: %d", sz) + } else if sz < (1 << 30) { + t.Fatalf("expected larger initial size: %d", sz) + } + + // Reopen database, update, and check size again. + db0, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db0.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0}) + }); err != nil { + t.Fatal(err) + } + if err := db0.Close(); err != nil { + t.Fatal(err) + } + + newSz := fileSize(path) + if newSz == 0 { + t.Fatalf("unexpected new file size: %d", newSz) + } + + // Compare the original size with the new size. + // db size might increase by a few page sizes due to the new small update. + if sz < newSz-5*int64(pagesize) { + t.Fatalf("unexpected file growth: %d => %d", sz, newSz) + } +} + +// Ensure that a re-opened database is consistent. +func TestOpen_Check(t *testing.T) { + path := tempfile() + + db, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { return <-tx.Check() }); err != nil { + t.Fatal(err) + } + if err := db.Close(); err != nil { + t.Fatal(err) + } + + db, err = bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { return <-tx.Check() }); err != nil { + t.Fatal(err) + } + if err := db.Close(); err != nil { + t.Fatal(err) + } +} + +// Ensure that write errors to the meta file handler during initialization are returned. +func TestOpen_MetaInitWriteError(t *testing.T) { + t.Skip("pending") +} + +// Ensure that a database that is too small returns an error. +func TestOpen_FileTooSmall(t *testing.T) { + path := tempfile() + + db, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db.Close(); err != nil { + t.Fatal(err) + } + + // corrupt the database + if err := os.Truncate(path, int64(os.Getpagesize())); err != nil { + t.Fatal(err) + } + + db, err = bolt.Open(path, 0666, nil) + if err == nil || err.Error() != "file size too small" { + t.Fatalf("unexpected error: %s", err) + } +} + +// TestDB_Open_InitialMmapSize tests if having InitialMmapSize large enough +// to hold data from concurrent write transaction resolves the issue that +// read transaction blocks the write transaction and causes deadlock. +// This is a very hacky test since the mmap size is not exposed. +func TestDB_Open_InitialMmapSize(t *testing.T) { + path := tempfile() + defer os.Remove(path) + + initMmapSize := 1 << 31 // 2GB + testWriteSize := 1 << 27 // 134MB + + db, err := bolt.Open(path, 0666, &bolt.Options{InitialMmapSize: initMmapSize}) + if err != nil { + t.Fatal(err) + } + + // create a long-running read transaction + // that never gets closed while writing + rtx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + + // create a write transaction + wtx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := wtx.CreateBucket([]byte("test")) + if err != nil { + t.Fatal(err) + } + + // and commit a large write + err = b.Put([]byte("foo"), make([]byte, testWriteSize)) + if err != nil { + t.Fatal(err) + } + + done := make(chan struct{}) + + go func() { + if err := wtx.Commit(); err != nil { + t.Fatal(err) + } + done <- struct{}{} + }() + + select { + case <-time.After(5 * time.Second): + t.Errorf("unexpected that the reader blocks writer") + case <-done: + } + + if err := rtx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a database cannot open a transaction when it's not open. +func TestDB_Begin_ErrDatabaseNotOpen(t *testing.T) { + var db bolt.DB + if _, err := db.Begin(false); err != bolt.ErrDatabaseNotOpen { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that a read-write transaction can be retrieved. +func TestDB_BeginRW(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } else if tx == nil { + t.Fatal("expected tx") + } + + if tx.DB() != db.DB { + t.Fatal("unexpected tx database") + } else if !tx.Writable() { + t.Fatal("expected writable tx") + } + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } +} + +// Ensure that opening a transaction while the DB is closed returns an error. +func TestDB_BeginRW_Closed(t *testing.T) { + var db bolt.DB + if _, err := db.Begin(true); err != bolt.ErrDatabaseNotOpen { + t.Fatalf("unexpected error: %s", err) + } +} + +func TestDB_Close_PendingTx_RW(t *testing.T) { testDB_Close_PendingTx(t, true) } +func TestDB_Close_PendingTx_RO(t *testing.T) { testDB_Close_PendingTx(t, false) } + +// Ensure that a database cannot close while transactions are open. +func testDB_Close_PendingTx(t *testing.T, writable bool) { + db := MustOpenDB() + defer db.MustClose() + + // Start transaction. + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + // Open update in separate goroutine. + done := make(chan struct{}) + go func() { + if err := db.Close(); err != nil { + t.Fatal(err) + } + close(done) + }() + + // Ensure database hasn't closed. + time.Sleep(100 * time.Millisecond) + select { + case <-done: + t.Fatal("database closed too early") + default: + } + + // Commit transaction. + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + // Ensure database closed now. + time.Sleep(100 * time.Millisecond) + select { + case <-done: + default: + t.Fatal("database did not close") + } +} + +// Ensure a database can provide a transactional block. +func TestDB_Update(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + if v := b.Get([]byte("foo")); v != nil { + t.Fatalf("expected nil value, got: %v", v) + } + if v := b.Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a closed database returns an error while running a transaction block +func TestDB_Update_Closed(t *testing.T) { + var db bolt.DB + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != bolt.ErrDatabaseNotOpen { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure a panic occurs while trying to commit a managed transaction. +func TestDB_Update_ManualCommit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.Update(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a panic occurs while trying to rollback a managed transaction. +func TestDB_Update_ManualRollback(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.Update(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a panic occurs while trying to commit a managed transaction. +func TestDB_View_ManualCommit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.View(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a panic occurs while trying to rollback a managed transaction. +func TestDB_View_ManualRollback(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.View(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a write transaction that panics does not hold open locks. +func TestDB_Update_Panic(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Panic during update but recover. + func() { + defer func() { + if r := recover(); r != nil { + t.Log("recover: update", r) + } + }() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + panic("omg") + }); err != nil { + t.Fatal(err) + } + }() + + // Verify we can update again. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify that our change persisted. + if err := db.Update(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a database can return an error through a read-only transactional block. +func TestDB_View_Error(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.View(func(tx *bolt.Tx) error { + return errors.New("xxx") + }); err == nil || err.Error() != "xxx" { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure a read transaction that panics does not hold open locks. +func TestDB_View_Panic(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Panic during view transaction but recover. + func() { + defer func() { + if r := recover(); r != nil { + t.Log("recover: view", r) + } + }() + + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + panic("omg") + }); err != nil { + t.Fatal(err) + } + }() + + // Verify that we can still use read transactions. + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that DB stats can be returned. +func TestDB_Stats(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + stats := db.Stats() + if stats.TxStats.PageCount != 2 { + t.Fatalf("unexpected TxStats.PageCount: %d", stats.TxStats.PageCount) + } else if stats.FreePageN != 0 { + t.Fatalf("unexpected FreePageN != 0: %d", stats.FreePageN) + } else if stats.PendingPageN != 2 { + t.Fatalf("unexpected PendingPageN != 2: %d", stats.PendingPageN) + } +} + +// Ensure that database pages are in expected order and type. +func TestDB_Consistency(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + if err := db.Update(func(tx *bolt.Tx) error { + if p, _ := tx.Page(0); p == nil { + t.Fatal("expected page") + } else if p.Type != "meta" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(1); p == nil { + t.Fatal("expected page") + } else if p.Type != "meta" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(2); p == nil { + t.Fatal("expected page") + } else if p.Type != "free" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(3); p == nil { + t.Fatal("expected page") + } else if p.Type != "free" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(4); p == nil { + t.Fatal("expected page") + } else if p.Type != "leaf" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(5); p == nil { + t.Fatal("expected page") + } else if p.Type != "freelist" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(6); p != nil { + t.Fatal("unexpected page") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that DB stats can be subtracted from one another. +func TestDBStats_Sub(t *testing.T) { + var a, b bolt.Stats + a.TxStats.PageCount = 3 + a.FreePageN = 4 + b.TxStats.PageCount = 10 + b.FreePageN = 14 + diff := b.Sub(&a) + if diff.TxStats.PageCount != 7 { + t.Fatalf("unexpected TxStats.PageCount: %d", diff.TxStats.PageCount) + } + + // free page stats are copied from the receiver and not subtracted + if diff.FreePageN != 14 { + t.Fatalf("unexpected FreePageN: %d", diff.FreePageN) + } +} + +// Ensure two functions can perform updates in a single batch. +func TestDB_Batch(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Iterate over multiple updates in separate goroutines. + n := 2 + ch := make(chan error) + for i := 0; i < n; i++ { + go func(i int) { + ch <- db.Batch(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{}) + }) + }(i) + } + + // Check all responses to make sure there's no error. + for i := 0; i < n; i++ { + if err := <-ch; err != nil { + t.Fatal(err) + } + } + + // Ensure data is correct. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < n; i++ { + if v := b.Get(u64tob(uint64(i))); v == nil { + t.Errorf("key not found: %d", i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestDB_Batch_Panic(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var sentinel int + var bork = &sentinel + var problem interface{} + var err error + + // Execute a function inside a batch that panics. + func() { + defer func() { + if p := recover(); p != nil { + problem = p + } + }() + err = db.Batch(func(tx *bolt.Tx) error { + panic(bork) + }) + }() + + // Verify there is no error. + if g, e := err, error(nil); g != e { + t.Fatalf("wrong error: %v != %v", g, e) + } + // Verify the panic was captured. + if g, e := problem, bork; g != e { + t.Fatalf("wrong error: %v != %v", g, e) + } +} + +func TestDB_BatchFull(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + const size = 3 + // buffered so we never leak goroutines + ch := make(chan error, size) + put := func(i int) { + ch <- db.Batch(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{}) + }) + } + + db.MaxBatchSize = size + // high enough to never trigger here + db.MaxBatchDelay = 1 * time.Hour + + go put(1) + go put(2) + + // Give the batch a chance to exhibit bugs. + time.Sleep(10 * time.Millisecond) + + // not triggered yet + select { + case <-ch: + t.Fatalf("batch triggered too early") + default: + } + + go put(3) + + // Check all responses to make sure there's no error. + for i := 0; i < size; i++ { + if err := <-ch; err != nil { + t.Fatal(err) + } + } + + // Ensure data is correct. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 1; i <= size; i++ { + if v := b.Get(u64tob(uint64(i))); v == nil { + t.Errorf("key not found: %d", i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestDB_BatchTime(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + const size = 1 + // buffered so we never leak goroutines + ch := make(chan error, size) + put := func(i int) { + ch <- db.Batch(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{}) + }) + } + + db.MaxBatchSize = 1000 + db.MaxBatchDelay = 0 + + go put(1) + + // Batch must trigger by time alone. + + // Check all responses to make sure there's no error. + for i := 0; i < size; i++ { + if err := <-ch; err != nil { + t.Fatal(err) + } + } + + // Ensure data is correct. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 1; i <= size; i++ { + if v := b.Get(u64tob(uint64(i))); v == nil { + t.Errorf("key not found: %d", i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func ExampleDB_Update() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Execute several commands within a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Read the value back from a separate read-only transaction. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value of 'foo' is: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release the file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value of 'foo' is: bar +} + +func ExampleDB_View() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Insert data into a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("people")) + if err != nil { + return err + } + if err := b.Put([]byte("john"), []byte("doe")); err != nil { + return err + } + if err := b.Put([]byte("susy"), []byte("que")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Access data from within a read-only transactional block. + if err := db.View(func(tx *bolt.Tx) error { + v := tx.Bucket([]byte("people")).Get([]byte("john")) + fmt.Printf("John's last name is %s.\n", v) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release the file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // John's last name is doe. +} + +func ExampleDB_Begin_ReadOnly() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Create a bucket using a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + log.Fatal(err) + } + + // Create several keys in a transaction. + tx, err := db.Begin(true) + if err != nil { + log.Fatal(err) + } + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("john"), []byte("blue")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("abby"), []byte("red")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("zephyr"), []byte("purple")); err != nil { + log.Fatal(err) + } + if err := tx.Commit(); err != nil { + log.Fatal(err) + } + + // Iterate over the values in sorted key order. + tx, err = db.Begin(false) + if err != nil { + log.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + fmt.Printf("%s likes %s\n", k, v) + } + + if err := tx.Rollback(); err != nil { + log.Fatal(err) + } + + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // abby likes red + // john likes blue + // zephyr likes purple +} + +func BenchmarkDBBatchAutomatic(b *testing.B) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("bench")) + return err + }); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + start := make(chan struct{}) + var wg sync.WaitGroup + + for round := 0; round < 1000; round++ { + wg.Add(1) + + go func(id uint32) { + defer wg.Done() + <-start + + h := fnv.New32a() + buf := make([]byte, 4) + binary.LittleEndian.PutUint32(buf, id) + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + insert := func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("bench")) + return b.Put(k, []byte("filler")) + } + if err := db.Batch(insert); err != nil { + b.Error(err) + return + } + }(uint32(round)) + } + close(start) + wg.Wait() + } + + b.StopTimer() + validateBatchBench(b, db) +} + +func BenchmarkDBBatchSingle(b *testing.B) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("bench")) + return err + }); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + start := make(chan struct{}) + var wg sync.WaitGroup + + for round := 0; round < 1000; round++ { + wg.Add(1) + go func(id uint32) { + defer wg.Done() + <-start + + h := fnv.New32a() + buf := make([]byte, 4) + binary.LittleEndian.PutUint32(buf, id) + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + insert := func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("bench")) + return b.Put(k, []byte("filler")) + } + if err := db.Update(insert); err != nil { + b.Error(err) + return + } + }(uint32(round)) + } + close(start) + wg.Wait() + } + + b.StopTimer() + validateBatchBench(b, db) +} + +func BenchmarkDBBatchManual10x100(b *testing.B) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("bench")) + return err + }); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + start := make(chan struct{}) + var wg sync.WaitGroup + + for major := 0; major < 10; major++ { + wg.Add(1) + go func(id uint32) { + defer wg.Done() + <-start + + insert100 := func(tx *bolt.Tx) error { + h := fnv.New32a() + buf := make([]byte, 4) + for minor := uint32(0); minor < 100; minor++ { + binary.LittleEndian.PutUint32(buf, uint32(id*100+minor)) + h.Reset() + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + b := tx.Bucket([]byte("bench")) + if err := b.Put(k, []byte("filler")); err != nil { + return err + } + } + return nil + } + if err := db.Update(insert100); err != nil { + b.Fatal(err) + } + }(uint32(major)) + } + close(start) + wg.Wait() + } + + b.StopTimer() + validateBatchBench(b, db) +} + +func validateBatchBench(b *testing.B, db *DB) { + var rollback = errors.New("sentinel error to cause rollback") + validate := func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte("bench")) + h := fnv.New32a() + buf := make([]byte, 4) + for id := uint32(0); id < 1000; id++ { + binary.LittleEndian.PutUint32(buf, id) + h.Reset() + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + v := bucket.Get(k) + if v == nil { + b.Errorf("not found id=%d key=%x", id, k) + continue + } + if g, e := v, []byte("filler"); !bytes.Equal(g, e) { + b.Errorf("bad value for id=%d key=%x: %s != %q", id, k, g, e) + } + if err := bucket.Delete(k); err != nil { + return err + } + } + // should be empty now + c := bucket.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + b.Errorf("unexpected key: %x = %q", k, v) + } + return rollback + } + if err := db.Update(validate); err != nil && err != rollback { + b.Error(err) + } +} + +// DB is a test wrapper for bolt.DB. +type DB struct { + *bolt.DB +} + +// MustOpenDB returns a new, open DB at a temporary location. +func MustOpenDB() *DB { + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + panic(err) + } + return &DB{db} +} + +// Close closes the database and deletes the underlying file. +func (db *DB) Close() error { + // Log statistics. + if *statsFlag { + db.PrintStats() + } + + // Check database consistency after every test. + db.MustCheck() + + // Close database and remove file. + defer os.Remove(db.Path()) + return db.DB.Close() +} + +// MustClose closes the database and deletes the underlying file. Panic on error. +func (db *DB) MustClose() { + if err := db.Close(); err != nil { + panic(err) + } +} + +// PrintStats prints the database stats +func (db *DB) PrintStats() { + var stats = db.Stats() + fmt.Printf("[db] %-20s %-20s %-20s\n", + fmt.Sprintf("pg(%d/%d)", stats.TxStats.PageCount, stats.TxStats.PageAlloc), + fmt.Sprintf("cur(%d)", stats.TxStats.CursorCount), + fmt.Sprintf("node(%d/%d)", stats.TxStats.NodeCount, stats.TxStats.NodeDeref), + ) + fmt.Printf(" %-20s %-20s %-20s\n", + fmt.Sprintf("rebal(%d/%v)", stats.TxStats.Rebalance, truncDuration(stats.TxStats.RebalanceTime)), + fmt.Sprintf("spill(%d/%v)", stats.TxStats.Spill, truncDuration(stats.TxStats.SpillTime)), + fmt.Sprintf("w(%d/%v)", stats.TxStats.Write, truncDuration(stats.TxStats.WriteTime)), + ) +} + +// MustCheck runs a consistency check on the database and panics if any errors are found. +func (db *DB) MustCheck() { + if err := db.Update(func(tx *bolt.Tx) error { + // Collect all the errors. + var errors []error + for err := range tx.Check() { + errors = append(errors, err) + if len(errors) > 10 { + break + } + } + + // If errors occurred, copy the DB and print the errors. + if len(errors) > 0 { + var path = tempfile() + if err := tx.CopyFile(path, 0600); err != nil { + panic(err) + } + + // Print errors. + fmt.Print("\n\n") + fmt.Printf("consistency check failed (%d errors)\n", len(errors)) + for _, err := range errors { + fmt.Println(err) + } + fmt.Println("") + fmt.Println("db saved to:") + fmt.Println(path) + fmt.Print("\n\n") + os.Exit(-1) + } + + return nil + }); err != nil && err != bolt.ErrDatabaseNotOpen { + panic(err) + } +} + +// CopyTempFile copies a database to a temporary file. +func (db *DB) CopyTempFile() { + path := tempfile() + if err := db.View(func(tx *bolt.Tx) error { + return tx.CopyFile(path, 0600) + }); err != nil { + panic(err) + } + fmt.Println("db copied to: ", path) +} + +// tempfile returns a temporary file path. +func tempfile() string { + f, err := ioutil.TempFile("", "bolt-") + if err != nil { + panic(err) + } + if err := f.Close(); err != nil { + panic(err) + } + if err := os.Remove(f.Name()); err != nil { + panic(err) + } + return f.Name() +} + +// mustContainKeys checks that a bucket contains a given set of keys. +func mustContainKeys(b *bolt.Bucket, m map[string]string) { + found := make(map[string]string) + if err := b.ForEach(func(k, _ []byte) error { + found[string(k)] = "" + return nil + }); err != nil { + panic(err) + } + + // Check for keys found in bucket that shouldn't be there. + var keys []string + for k, _ := range found { + if _, ok := m[string(k)]; !ok { + keys = append(keys, k) + } + } + if len(keys) > 0 { + sort.Strings(keys) + panic(fmt.Sprintf("keys found(%d): %s", len(keys), strings.Join(keys, ","))) + } + + // Check for keys not found in bucket that should be there. + for k, _ := range m { + if _, ok := found[string(k)]; !ok { + keys = append(keys, k) + } + } + if len(keys) > 0 { + sort.Strings(keys) + panic(fmt.Sprintf("keys not found(%d): %s", len(keys), strings.Join(keys, ","))) + } +} + +func trunc(b []byte, length int) []byte { + if length < len(b) { + return b[:length] + } + return b +} + +func truncDuration(d time.Duration) string { + return regexp.MustCompile(`^(\d+)(\.\d+)`).ReplaceAllString(d.String(), "$1") +} + +func fileSize(path string) int64 { + fi, err := os.Stat(path) + if err != nil { + return 0 + } + return fi.Size() +} + +func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) } +func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) } + +// u64tob converts a uint64 into an 8-byte slice. +func u64tob(v uint64) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, v) + return b +} + +// btou64 converts an 8-byte slice into an uint64. +func btou64(b []byte) uint64 { return binary.BigEndian.Uint64(b) } diff --git a/vendor/github.com/boltdb/bolt/doc.go b/vendor/github.com/boltdb/bolt/doc.go new file mode 100644 index 0000000..cc93784 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/doc.go @@ -0,0 +1,44 @@ +/* +Package bolt implements a low-level key/value store in pure Go. It supports +fully serializable transactions, ACID semantics, and lock-free MVCC with +multiple readers and a single writer. Bolt can be used for projects that +want a simple data store without the need to add large dependencies such as +Postgres or MySQL. + +Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is +optimized for fast read access and does not require recovery in the event of a +system crash. Transactions which have not finished committing will simply be +rolled back in the event of a crash. + +The design of Bolt is based on Howard Chu's LMDB database project. + +Bolt currently works on Windows, Mac OS X, and Linux. + + +Basics + +There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is +a collection of buckets and is represented by a single file on disk. A bucket is +a collection of unique keys that are associated with values. + +Transactions provide either read-only or read-write access to the database. +Read-only transactions can retrieve key/value pairs and can use Cursors to +iterate over the dataset sequentially. Read-write transactions can create and +delete buckets and can insert and remove keys. Only one read-write transaction +is allowed at a time. + + +Caveats + +The database uses a read-only, memory-mapped data file to ensure that +applications cannot corrupt the database, however, this means that keys and +values returned from Bolt cannot be changed. Writing to a read-only byte slice +will cause Go to panic. + +Keys and values retrieved from the database are only valid for the life of +the transaction. When used outside the transaction, these byte slices can +point to different data or can point to invalid memory which will cause a panic. + + +*/ +package bolt diff --git a/vendor/github.com/boltdb/bolt/errors.go b/vendor/github.com/boltdb/bolt/errors.go new file mode 100644 index 0000000..a3620a3 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/errors.go @@ -0,0 +1,71 @@ +package bolt + +import "errors" + +// These errors can be returned when opening or calling methods on a DB. +var ( + // ErrDatabaseNotOpen is returned when a DB instance is accessed before it + // is opened or after it is closed. + ErrDatabaseNotOpen = errors.New("database not open") + + // ErrDatabaseOpen is returned when opening a database that is + // already open. + ErrDatabaseOpen = errors.New("database already open") + + // ErrInvalid is returned when both meta pages on a database are invalid. + // This typically occurs when a file is not a bolt database. + ErrInvalid = errors.New("invalid database") + + // ErrVersionMismatch is returned when the data file was created with a + // different version of Bolt. + ErrVersionMismatch = errors.New("version mismatch") + + // ErrChecksum is returned when either meta page checksum does not match. + ErrChecksum = errors.New("checksum error") + + // ErrTimeout is returned when a database cannot obtain an exclusive lock + // on the data file after the timeout passed to Open(). + ErrTimeout = errors.New("timeout") +) + +// These errors can occur when beginning or committing a Tx. +var ( + // ErrTxNotWritable is returned when performing a write operation on a + // read-only transaction. + ErrTxNotWritable = errors.New("tx not writable") + + // ErrTxClosed is returned when committing or rolling back a transaction + // that has already been committed or rolled back. + ErrTxClosed = errors.New("tx closed") + + // ErrDatabaseReadOnly is returned when a mutating transaction is started on a + // read-only database. + ErrDatabaseReadOnly = errors.New("database is in read-only mode") +) + +// These errors can occur when putting or deleting a value or a bucket. +var ( + // ErrBucketNotFound is returned when trying to access a bucket that has + // not been created yet. + ErrBucketNotFound = errors.New("bucket not found") + + // ErrBucketExists is returned when creating a bucket that already exists. + ErrBucketExists = errors.New("bucket already exists") + + // ErrBucketNameRequired is returned when creating a bucket with a blank name. + ErrBucketNameRequired = errors.New("bucket name required") + + // ErrKeyRequired is returned when inserting a zero-length key. + ErrKeyRequired = errors.New("key required") + + // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize. + ErrKeyTooLarge = errors.New("key too large") + + // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize. + ErrValueTooLarge = errors.New("value too large") + + // ErrIncompatibleValue is returned when trying create or delete a bucket + // on an existing non-bucket key or when trying to create or delete a + // non-bucket key on an existing bucket key. + ErrIncompatibleValue = errors.New("incompatible value") +) diff --git a/vendor/github.com/boltdb/bolt/freelist.go b/vendor/github.com/boltdb/bolt/freelist.go new file mode 100644 index 0000000..aba48f5 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/freelist.go @@ -0,0 +1,252 @@ +package bolt + +import ( + "fmt" + "sort" + "unsafe" +) + +// freelist represents a list of all pages that are available for allocation. +// It also tracks pages that have been freed but are still in use by open transactions. +type freelist struct { + ids []pgid // all free and available free page ids. + pending map[txid][]pgid // mapping of soon-to-be free page ids by tx. + cache map[pgid]bool // fast lookup of all free and pending page ids. +} + +// newFreelist returns an empty, initialized freelist. +func newFreelist() *freelist { + return &freelist{ + pending: make(map[txid][]pgid), + cache: make(map[pgid]bool), + } +} + +// size returns the size of the page after serialization. +func (f *freelist) size() int { + n := f.count() + if n >= 0xFFFF { + // The first element will be used to store the count. See freelist.write. + n++ + } + return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * n) +} + +// count returns count of pages on the freelist +func (f *freelist) count() int { + return f.free_count() + f.pending_count() +} + +// free_count returns count of free pages +func (f *freelist) free_count() int { + return len(f.ids) +} + +// pending_count returns count of pending pages +func (f *freelist) pending_count() int { + var count int + for _, list := range f.pending { + count += len(list) + } + return count +} + +// copyall copies into dst a list of all free ids and all pending ids in one sorted list. +// f.count returns the minimum length required for dst. +func (f *freelist) copyall(dst []pgid) { + m := make(pgids, 0, f.pending_count()) + for _, list := range f.pending { + m = append(m, list...) + } + sort.Sort(m) + mergepgids(dst, f.ids, m) +} + +// allocate returns the starting page id of a contiguous list of pages of a given size. +// If a contiguous block cannot be found then 0 is returned. +func (f *freelist) allocate(n int) pgid { + if len(f.ids) == 0 { + return 0 + } + + var initial, previd pgid + for i, id := range f.ids { + if id <= 1 { + panic(fmt.Sprintf("invalid page allocation: %d", id)) + } + + // Reset initial page if this is not contiguous. + if previd == 0 || id-previd != 1 { + initial = id + } + + // If we found a contiguous block then remove it and return it. + if (id-initial)+1 == pgid(n) { + // If we're allocating off the beginning then take the fast path + // and just adjust the existing slice. This will use extra memory + // temporarily but the append() in free() will realloc the slice + // as is necessary. + if (i + 1) == n { + f.ids = f.ids[i+1:] + } else { + copy(f.ids[i-n+1:], f.ids[i+1:]) + f.ids = f.ids[:len(f.ids)-n] + } + + // Remove from the free cache. + for i := pgid(0); i < pgid(n); i++ { + delete(f.cache, initial+i) + } + + return initial + } + + previd = id + } + return 0 +} + +// free releases a page and its overflow for a given transaction id. +// If the page is already free then a panic will occur. +func (f *freelist) free(txid txid, p *page) { + if p.id <= 1 { + panic(fmt.Sprintf("cannot free page 0 or 1: %d", p.id)) + } + + // Free page and all its overflow pages. + var ids = f.pending[txid] + for id := p.id; id <= p.id+pgid(p.overflow); id++ { + // Verify that page is not already free. + if f.cache[id] { + panic(fmt.Sprintf("page %d already freed", id)) + } + + // Add to the freelist and cache. + ids = append(ids, id) + f.cache[id] = true + } + f.pending[txid] = ids +} + +// release moves all page ids for a transaction id (or older) to the freelist. +func (f *freelist) release(txid txid) { + m := make(pgids, 0) + for tid, ids := range f.pending { + if tid <= txid { + // Move transaction's pending pages to the available freelist. + // Don't remove from the cache since the page is still free. + m = append(m, ids...) + delete(f.pending, tid) + } + } + sort.Sort(m) + f.ids = pgids(f.ids).merge(m) +} + +// rollback removes the pages from a given pending tx. +func (f *freelist) rollback(txid txid) { + // Remove page ids from cache. + for _, id := range f.pending[txid] { + delete(f.cache, id) + } + + // Remove pages from pending list. + delete(f.pending, txid) +} + +// freed returns whether a given page is in the free list. +func (f *freelist) freed(pgid pgid) bool { + return f.cache[pgid] +} + +// read initializes the freelist from a freelist page. +func (f *freelist) read(p *page) { + // If the page.count is at the max uint16 value (64k) then it's considered + // an overflow and the size of the freelist is stored as the first element. + idx, count := 0, int(p.count) + if count == 0xFFFF { + idx = 1 + count = int(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0]) + } + + // Copy the list of page ids from the freelist. + if count == 0 { + f.ids = nil + } else { + ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] + f.ids = make([]pgid, len(ids)) + copy(f.ids, ids) + + // Make sure they're sorted. + sort.Sort(pgids(f.ids)) + } + + // Rebuild the page cache. + f.reindex() +} + +// write writes the page ids onto a freelist page. All free and pending ids are +// saved to disk since in the event of a program crash, all pending ids will +// become free. +func (f *freelist) write(p *page) error { + // Combine the old free pgids and pgids waiting on an open transaction. + + // Update the header flag. + p.flags |= freelistPageFlag + + // The page.count can only hold up to 64k elements so if we overflow that + // number then we handle it by putting the size in the first element. + lenids := f.count() + if lenids == 0 { + p.count = uint16(lenids) + } else if lenids < 0xFFFF { + p.count = uint16(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:]) + } else { + p.count = 0xFFFF + ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:]) + } + + return nil +} + +// reload reads the freelist from a page and filters out pending items. +func (f *freelist) reload(p *page) { + f.read(p) + + // Build a cache of only pending pages. + pcache := make(map[pgid]bool) + for _, pendingIDs := range f.pending { + for _, pendingID := range pendingIDs { + pcache[pendingID] = true + } + } + + // Check each page in the freelist and build a new available freelist + // with any pages not in the pending lists. + var a []pgid + for _, id := range f.ids { + if !pcache[id] { + a = append(a, id) + } + } + f.ids = a + + // Once the available list is rebuilt then rebuild the free cache so that + // it includes the available and pending free pages. + f.reindex() +} + +// reindex rebuilds the free cache based on available and pending free lists. +func (f *freelist) reindex() { + f.cache = make(map[pgid]bool, len(f.ids)) + for _, id := range f.ids { + f.cache[id] = true + } + for _, pendingIDs := range f.pending { + for _, pendingID := range pendingIDs { + f.cache[pendingID] = true + } + } +} diff --git a/vendor/github.com/boltdb/bolt/freelist_test.go b/vendor/github.com/boltdb/bolt/freelist_test.go new file mode 100644 index 0000000..4e9b3a8 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/freelist_test.go @@ -0,0 +1,158 @@ +package bolt + +import ( + "math/rand" + "reflect" + "sort" + "testing" + "unsafe" +) + +// Ensure that a page is added to a transaction's freelist. +func TestFreelist_free(t *testing.T) { + f := newFreelist() + f.free(100, &page{id: 12}) + if !reflect.DeepEqual([]pgid{12}, f.pending[100]) { + t.Fatalf("exp=%v; got=%v", []pgid{12}, f.pending[100]) + } +} + +// Ensure that a page and its overflow is added to a transaction's freelist. +func TestFreelist_free_overflow(t *testing.T) { + f := newFreelist() + f.free(100, &page{id: 12, overflow: 3}) + if exp := []pgid{12, 13, 14, 15}; !reflect.DeepEqual(exp, f.pending[100]) { + t.Fatalf("exp=%v; got=%v", exp, f.pending[100]) + } +} + +// Ensure that a transaction's free pages can be released. +func TestFreelist_release(t *testing.T) { + f := newFreelist() + f.free(100, &page{id: 12, overflow: 1}) + f.free(100, &page{id: 9}) + f.free(102, &page{id: 39}) + f.release(100) + f.release(101) + if exp := []pgid{9, 12, 13}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } + + f.release(102) + if exp := []pgid{9, 12, 13, 39}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } +} + +// Ensure that a freelist can find contiguous blocks of pages. +func TestFreelist_allocate(t *testing.T) { + f := &freelist{ids: []pgid{3, 4, 5, 6, 7, 9, 12, 13, 18}} + if id := int(f.allocate(3)); id != 3 { + t.Fatalf("exp=3; got=%v", id) + } + if id := int(f.allocate(1)); id != 6 { + t.Fatalf("exp=6; got=%v", id) + } + if id := int(f.allocate(3)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if id := int(f.allocate(2)); id != 12 { + t.Fatalf("exp=12; got=%v", id) + } + if id := int(f.allocate(1)); id != 7 { + t.Fatalf("exp=7; got=%v", id) + } + if id := int(f.allocate(0)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if id := int(f.allocate(0)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if exp := []pgid{9, 18}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } + + if id := int(f.allocate(1)); id != 9 { + t.Fatalf("exp=9; got=%v", id) + } + if id := int(f.allocate(1)); id != 18 { + t.Fatalf("exp=18; got=%v", id) + } + if id := int(f.allocate(1)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if exp := []pgid{}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } +} + +// Ensure that a freelist can deserialize from a freelist page. +func TestFreelist_read(t *testing.T) { + // Create a page. + var buf [4096]byte + page := (*page)(unsafe.Pointer(&buf[0])) + page.flags = freelistPageFlag + page.count = 2 + + // Insert 2 page ids. + ids := (*[3]pgid)(unsafe.Pointer(&page.ptr)) + ids[0] = 23 + ids[1] = 50 + + // Deserialize page into a freelist. + f := newFreelist() + f.read(page) + + // Ensure that there are two page ids in the freelist. + if exp := []pgid{23, 50}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } +} + +// Ensure that a freelist can serialize into a freelist page. +func TestFreelist_write(t *testing.T) { + // Create a freelist and write it to a page. + var buf [4096]byte + f := &freelist{ids: []pgid{12, 39}, pending: make(map[txid][]pgid)} + f.pending[100] = []pgid{28, 11} + f.pending[101] = []pgid{3} + p := (*page)(unsafe.Pointer(&buf[0])) + if err := f.write(p); err != nil { + t.Fatal(err) + } + + // Read the page back out. + f2 := newFreelist() + f2.read(p) + + // Ensure that the freelist is correct. + // All pages should be present and in reverse order. + if exp := []pgid{3, 11, 12, 28, 39}; !reflect.DeepEqual(exp, f2.ids) { + t.Fatalf("exp=%v; got=%v", exp, f2.ids) + } +} + +func Benchmark_FreelistRelease10K(b *testing.B) { benchmark_FreelistRelease(b, 10000) } +func Benchmark_FreelistRelease100K(b *testing.B) { benchmark_FreelistRelease(b, 100000) } +func Benchmark_FreelistRelease1000K(b *testing.B) { benchmark_FreelistRelease(b, 1000000) } +func Benchmark_FreelistRelease10000K(b *testing.B) { benchmark_FreelistRelease(b, 10000000) } + +func benchmark_FreelistRelease(b *testing.B, size int) { + ids := randomPgids(size) + pending := randomPgids(len(ids) / 400) + b.ResetTimer() + for i := 0; i < b.N; i++ { + f := &freelist{ids: ids, pending: map[txid][]pgid{1: pending}} + f.release(1) + } +} + +func randomPgids(n int) []pgid { + rand.Seed(42) + pgids := make(pgids, n) + for i := range pgids { + pgids[i] = pgid(rand.Int63()) + } + sort.Sort(pgids) + return pgids +} diff --git a/vendor/github.com/boltdb/bolt/node.go b/vendor/github.com/boltdb/bolt/node.go new file mode 100644 index 0000000..159318b --- /dev/null +++ b/vendor/github.com/boltdb/bolt/node.go @@ -0,0 +1,604 @@ +package bolt + +import ( + "bytes" + "fmt" + "sort" + "unsafe" +) + +// node represents an in-memory, deserialized page. +type node struct { + bucket *Bucket + isLeaf bool + unbalanced bool + spilled bool + key []byte + pgid pgid + parent *node + children nodes + inodes inodes +} + +// root returns the top-level node this node is attached to. +func (n *node) root() *node { + if n.parent == nil { + return n + } + return n.parent.root() +} + +// minKeys returns the minimum number of inodes this node should have. +func (n *node) minKeys() int { + if n.isLeaf { + return 1 + } + return 2 +} + +// size returns the size of the node after serialization. +func (n *node) size() int { + sz, elsz := pageHeaderSize, n.pageElementSize() + for i := 0; i < len(n.inodes); i++ { + item := &n.inodes[i] + sz += elsz + len(item.key) + len(item.value) + } + return sz +} + +// sizeLessThan returns true if the node is less than a given size. +// This is an optimization to avoid calculating a large node when we only need +// to know if it fits inside a certain page size. +func (n *node) sizeLessThan(v int) bool { + sz, elsz := pageHeaderSize, n.pageElementSize() + for i := 0; i < len(n.inodes); i++ { + item := &n.inodes[i] + sz += elsz + len(item.key) + len(item.value) + if sz >= v { + return false + } + } + return true +} + +// pageElementSize returns the size of each page element based on the type of node. +func (n *node) pageElementSize() int { + if n.isLeaf { + return leafPageElementSize + } + return branchPageElementSize +} + +// childAt returns the child node at a given index. +func (n *node) childAt(index int) *node { + if n.isLeaf { + panic(fmt.Sprintf("invalid childAt(%d) on a leaf node", index)) + } + return n.bucket.node(n.inodes[index].pgid, n) +} + +// childIndex returns the index of a given child node. +func (n *node) childIndex(child *node) int { + index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, child.key) != -1 }) + return index +} + +// numChildren returns the number of children. +func (n *node) numChildren() int { + return len(n.inodes) +} + +// nextSibling returns the next node with the same parent. +func (n *node) nextSibling() *node { + if n.parent == nil { + return nil + } + index := n.parent.childIndex(n) + if index >= n.parent.numChildren()-1 { + return nil + } + return n.parent.childAt(index + 1) +} + +// prevSibling returns the previous node with the same parent. +func (n *node) prevSibling() *node { + if n.parent == nil { + return nil + } + index := n.parent.childIndex(n) + if index == 0 { + return nil + } + return n.parent.childAt(index - 1) +} + +// put inserts a key/value. +func (n *node) put(oldKey, newKey, value []byte, pgid pgid, flags uint32) { + if pgid >= n.bucket.tx.meta.pgid { + panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", pgid, n.bucket.tx.meta.pgid)) + } else if len(oldKey) <= 0 { + panic("put: zero-length old key") + } else if len(newKey) <= 0 { + panic("put: zero-length new key") + } + + // Find insertion index. + index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, oldKey) != -1 }) + + // Add capacity and shift nodes if we don't have an exact match and need to insert. + exact := (len(n.inodes) > 0 && index < len(n.inodes) && bytes.Equal(n.inodes[index].key, oldKey)) + if !exact { + n.inodes = append(n.inodes, inode{}) + copy(n.inodes[index+1:], n.inodes[index:]) + } + + inode := &n.inodes[index] + inode.flags = flags + inode.key = newKey + inode.value = value + inode.pgid = pgid + _assert(len(inode.key) > 0, "put: zero-length inode key") +} + +// del removes a key from the node. +func (n *node) del(key []byte) { + // Find index of key. + index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, key) != -1 }) + + // Exit if the key isn't found. + if index >= len(n.inodes) || !bytes.Equal(n.inodes[index].key, key) { + return + } + + // Delete inode from the node. + n.inodes = append(n.inodes[:index], n.inodes[index+1:]...) + + // Mark the node as needing rebalancing. + n.unbalanced = true +} + +// read initializes the node from a page. +func (n *node) read(p *page) { + n.pgid = p.id + n.isLeaf = ((p.flags & leafPageFlag) != 0) + n.inodes = make(inodes, int(p.count)) + + for i := 0; i < int(p.count); i++ { + inode := &n.inodes[i] + if n.isLeaf { + elem := p.leafPageElement(uint16(i)) + inode.flags = elem.flags + inode.key = elem.key() + inode.value = elem.value() + } else { + elem := p.branchPageElement(uint16(i)) + inode.pgid = elem.pgid + inode.key = elem.key() + } + _assert(len(inode.key) > 0, "read: zero-length inode key") + } + + // Save first key so we can find the node in the parent when we spill. + if len(n.inodes) > 0 { + n.key = n.inodes[0].key + _assert(len(n.key) > 0, "read: zero-length node key") + } else { + n.key = nil + } +} + +// write writes the items onto one or more pages. +func (n *node) write(p *page) { + // Initialize page. + if n.isLeaf { + p.flags |= leafPageFlag + } else { + p.flags |= branchPageFlag + } + + if len(n.inodes) >= 0xFFFF { + panic(fmt.Sprintf("inode overflow: %d (pgid=%d)", len(n.inodes), p.id)) + } + p.count = uint16(len(n.inodes)) + + // Stop here if there are no items to write. + if p.count == 0 { + return + } + + // Loop over each item and write it to the page. + b := (*[maxAllocSize]byte)(unsafe.Pointer(&p.ptr))[n.pageElementSize()*len(n.inodes):] + for i, item := range n.inodes { + _assert(len(item.key) > 0, "write: zero-length inode key") + + // Write the page element. + if n.isLeaf { + elem := p.leafPageElement(uint16(i)) + elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))) + elem.flags = item.flags + elem.ksize = uint32(len(item.key)) + elem.vsize = uint32(len(item.value)) + } else { + elem := p.branchPageElement(uint16(i)) + elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))) + elem.ksize = uint32(len(item.key)) + elem.pgid = item.pgid + _assert(elem.pgid != p.id, "write: circular dependency occurred") + } + + // If the length of key+value is larger than the max allocation size + // then we need to reallocate the byte array pointer. + // + // See: https://github.com/boltdb/bolt/pull/335 + klen, vlen := len(item.key), len(item.value) + if len(b) < klen+vlen { + b = (*[maxAllocSize]byte)(unsafe.Pointer(&b[0]))[:] + } + + // Write data for the element to the end of the page. + copy(b[0:], item.key) + b = b[klen:] + copy(b[0:], item.value) + b = b[vlen:] + } + + // DEBUG ONLY: n.dump() +} + +// split breaks up a node into multiple smaller nodes, if appropriate. +// This should only be called from the spill() function. +func (n *node) split(pageSize int) []*node { + var nodes []*node + + node := n + for { + // Split node into two. + a, b := node.splitTwo(pageSize) + nodes = append(nodes, a) + + // If we can't split then exit the loop. + if b == nil { + break + } + + // Set node to b so it gets split on the next iteration. + node = b + } + + return nodes +} + +// splitTwo breaks up a node into two smaller nodes, if appropriate. +// This should only be called from the split() function. +func (n *node) splitTwo(pageSize int) (*node, *node) { + // Ignore the split if the page doesn't have at least enough nodes for + // two pages or if the nodes can fit in a single page. + if len(n.inodes) <= (minKeysPerPage*2) || n.sizeLessThan(pageSize) { + return n, nil + } + + // Determine the threshold before starting a new node. + var fillPercent = n.bucket.FillPercent + if fillPercent < minFillPercent { + fillPercent = minFillPercent + } else if fillPercent > maxFillPercent { + fillPercent = maxFillPercent + } + threshold := int(float64(pageSize) * fillPercent) + + // Determine split position and sizes of the two pages. + splitIndex, _ := n.splitIndex(threshold) + + // Split node into two separate nodes. + // If there's no parent then we'll need to create one. + if n.parent == nil { + n.parent = &node{bucket: n.bucket, children: []*node{n}} + } + + // Create a new node and add it to the parent. + next := &node{bucket: n.bucket, isLeaf: n.isLeaf, parent: n.parent} + n.parent.children = append(n.parent.children, next) + + // Split inodes across two nodes. + next.inodes = n.inodes[splitIndex:] + n.inodes = n.inodes[:splitIndex] + + // Update the statistics. + n.bucket.tx.stats.Split++ + + return n, next +} + +// splitIndex finds the position where a page will fill a given threshold. +// It returns the index as well as the size of the first page. +// This is only be called from split(). +func (n *node) splitIndex(threshold int) (index, sz int) { + sz = pageHeaderSize + + // Loop until we only have the minimum number of keys required for the second page. + for i := 0; i < len(n.inodes)-minKeysPerPage; i++ { + index = i + inode := n.inodes[i] + elsize := n.pageElementSize() + len(inode.key) + len(inode.value) + + // If we have at least the minimum number of keys and adding another + // node would put us over the threshold then exit and return. + if i >= minKeysPerPage && sz+elsize > threshold { + break + } + + // Add the element size to the total size. + sz += elsize + } + + return +} + +// spill writes the nodes to dirty pages and splits nodes as it goes. +// Returns an error if dirty pages cannot be allocated. +func (n *node) spill() error { + var tx = n.bucket.tx + if n.spilled { + return nil + } + + // Spill child nodes first. Child nodes can materialize sibling nodes in + // the case of split-merge so we cannot use a range loop. We have to check + // the children size on every loop iteration. + sort.Sort(n.children) + for i := 0; i < len(n.children); i++ { + if err := n.children[i].spill(); err != nil { + return err + } + } + + // We no longer need the child list because it's only used for spill tracking. + n.children = nil + + // Split nodes into appropriate sizes. The first node will always be n. + var nodes = n.split(tx.db.pageSize) + for _, node := range nodes { + // Add node's page to the freelist if it's not new. + if node.pgid > 0 { + tx.db.freelist.free(tx.meta.txid, tx.page(node.pgid)) + node.pgid = 0 + } + + // Allocate contiguous space for the node. + p, err := tx.allocate((node.size() / tx.db.pageSize) + 1) + if err != nil { + return err + } + + // Write the node. + if p.id >= tx.meta.pgid { + panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid)) + } + node.pgid = p.id + node.write(p) + node.spilled = true + + // Insert into parent inodes. + if node.parent != nil { + var key = node.key + if key == nil { + key = node.inodes[0].key + } + + node.parent.put(key, node.inodes[0].key, nil, node.pgid, 0) + node.key = node.inodes[0].key + _assert(len(node.key) > 0, "spill: zero-length node key") + } + + // Update the statistics. + tx.stats.Spill++ + } + + // If the root node split and created a new root then we need to spill that + // as well. We'll clear out the children to make sure it doesn't try to respill. + if n.parent != nil && n.parent.pgid == 0 { + n.children = nil + return n.parent.spill() + } + + return nil +} + +// rebalance attempts to combine the node with sibling nodes if the node fill +// size is below a threshold or if there are not enough keys. +func (n *node) rebalance() { + if !n.unbalanced { + return + } + n.unbalanced = false + + // Update statistics. + n.bucket.tx.stats.Rebalance++ + + // Ignore if node is above threshold (25%) and has enough keys. + var threshold = n.bucket.tx.db.pageSize / 4 + if n.size() > threshold && len(n.inodes) > n.minKeys() { + return + } + + // Root node has special handling. + if n.parent == nil { + // If root node is a branch and only has one node then collapse it. + if !n.isLeaf && len(n.inodes) == 1 { + // Move root's child up. + child := n.bucket.node(n.inodes[0].pgid, n) + n.isLeaf = child.isLeaf + n.inodes = child.inodes[:] + n.children = child.children + + // Reparent all child nodes being moved. + for _, inode := range n.inodes { + if child, ok := n.bucket.nodes[inode.pgid]; ok { + child.parent = n + } + } + + // Remove old child. + child.parent = nil + delete(n.bucket.nodes, child.pgid) + child.free() + } + + return + } + + // If node has no keys then just remove it. + if n.numChildren() == 0 { + n.parent.del(n.key) + n.parent.removeChild(n) + delete(n.bucket.nodes, n.pgid) + n.free() + n.parent.rebalance() + return + } + + _assert(n.parent.numChildren() > 1, "parent must have at least 2 children") + + // Destination node is right sibling if idx == 0, otherwise left sibling. + var target *node + var useNextSibling = (n.parent.childIndex(n) == 0) + if useNextSibling { + target = n.nextSibling() + } else { + target = n.prevSibling() + } + + // If both this node and the target node are too small then merge them. + if useNextSibling { + // Reparent all child nodes being moved. + for _, inode := range target.inodes { + if child, ok := n.bucket.nodes[inode.pgid]; ok { + child.parent.removeChild(child) + child.parent = n + child.parent.children = append(child.parent.children, child) + } + } + + // Copy over inodes from target and remove target. + n.inodes = append(n.inodes, target.inodes...) + n.parent.del(target.key) + n.parent.removeChild(target) + delete(n.bucket.nodes, target.pgid) + target.free() + } else { + // Reparent all child nodes being moved. + for _, inode := range n.inodes { + if child, ok := n.bucket.nodes[inode.pgid]; ok { + child.parent.removeChild(child) + child.parent = target + child.parent.children = append(child.parent.children, child) + } + } + + // Copy over inodes to target and remove node. + target.inodes = append(target.inodes, n.inodes...) + n.parent.del(n.key) + n.parent.removeChild(n) + delete(n.bucket.nodes, n.pgid) + n.free() + } + + // Either this node or the target node was deleted from the parent so rebalance it. + n.parent.rebalance() +} + +// removes a node from the list of in-memory children. +// This does not affect the inodes. +func (n *node) removeChild(target *node) { + for i, child := range n.children { + if child == target { + n.children = append(n.children[:i], n.children[i+1:]...) + return + } + } +} + +// dereference causes the node to copy all its inode key/value references to heap memory. +// This is required when the mmap is reallocated so inodes are not pointing to stale data. +func (n *node) dereference() { + if n.key != nil { + key := make([]byte, len(n.key)) + copy(key, n.key) + n.key = key + _assert(n.pgid == 0 || len(n.key) > 0, "dereference: zero-length node key on existing node") + } + + for i := range n.inodes { + inode := &n.inodes[i] + + key := make([]byte, len(inode.key)) + copy(key, inode.key) + inode.key = key + _assert(len(inode.key) > 0, "dereference: zero-length inode key") + + value := make([]byte, len(inode.value)) + copy(value, inode.value) + inode.value = value + } + + // Recursively dereference children. + for _, child := range n.children { + child.dereference() + } + + // Update statistics. + n.bucket.tx.stats.NodeDeref++ +} + +// free adds the node's underlying page to the freelist. +func (n *node) free() { + if n.pgid != 0 { + n.bucket.tx.db.freelist.free(n.bucket.tx.meta.txid, n.bucket.tx.page(n.pgid)) + n.pgid = 0 + } +} + +// dump writes the contents of the node to STDERR for debugging purposes. +/* +func (n *node) dump() { + // Write node header. + var typ = "branch" + if n.isLeaf { + typ = "leaf" + } + warnf("[NODE %d {type=%s count=%d}]", n.pgid, typ, len(n.inodes)) + + // Write out abbreviated version of each item. + for _, item := range n.inodes { + if n.isLeaf { + if item.flags&bucketLeafFlag != 0 { + bucket := (*bucket)(unsafe.Pointer(&item.value[0])) + warnf("+L %08x -> (bucket root=%d)", trunc(item.key, 4), bucket.root) + } else { + warnf("+L %08x -> %08x", trunc(item.key, 4), trunc(item.value, 4)) + } + } else { + warnf("+B %08x -> pgid=%d", trunc(item.key, 4), item.pgid) + } + } + warn("") +} +*/ + +type nodes []*node + +func (s nodes) Len() int { return len(s) } +func (s nodes) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s nodes) Less(i, j int) bool { return bytes.Compare(s[i].inodes[0].key, s[j].inodes[0].key) == -1 } + +// inode represents an internal node inside of a node. +// It can be used to point to elements in a page or point +// to an element which hasn't been added to a page yet. +type inode struct { + flags uint32 + pgid pgid + key []byte + value []byte +} + +type inodes []inode diff --git a/vendor/github.com/boltdb/bolt/node_test.go b/vendor/github.com/boltdb/bolt/node_test.go new file mode 100644 index 0000000..fa5d10f --- /dev/null +++ b/vendor/github.com/boltdb/bolt/node_test.go @@ -0,0 +1,156 @@ +package bolt + +import ( + "testing" + "unsafe" +) + +// Ensure that a node can insert a key/value. +func TestNode_put(t *testing.T) { + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}} + n.put([]byte("baz"), []byte("baz"), []byte("2"), 0, 0) + n.put([]byte("foo"), []byte("foo"), []byte("0"), 0, 0) + n.put([]byte("bar"), []byte("bar"), []byte("1"), 0, 0) + n.put([]byte("foo"), []byte("foo"), []byte("3"), 0, leafPageFlag) + + if len(n.inodes) != 3 { + t.Fatalf("exp=3; got=%d", len(n.inodes)) + } + if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "1" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "baz" || string(v) != "2" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n.inodes[2].key, n.inodes[2].value; string(k) != "foo" || string(v) != "3" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if n.inodes[2].flags != uint32(leafPageFlag) { + t.Fatalf("not a leaf: %d", n.inodes[2].flags) + } +} + +// Ensure that a node can deserialize from a leaf page. +func TestNode_read_LeafPage(t *testing.T) { + // Create a page. + var buf [4096]byte + page := (*page)(unsafe.Pointer(&buf[0])) + page.flags = leafPageFlag + page.count = 2 + + // Insert 2 elements at the beginning. sizeof(leafPageElement) == 16 + nodes := (*[3]leafPageElement)(unsafe.Pointer(&page.ptr)) + nodes[0] = leafPageElement{flags: 0, pos: 32, ksize: 3, vsize: 4} // pos = sizeof(leafPageElement) * 2 + nodes[1] = leafPageElement{flags: 0, pos: 23, ksize: 10, vsize: 3} // pos = sizeof(leafPageElement) + 3 + 4 + + // Write data for the nodes at the end. + data := (*[4096]byte)(unsafe.Pointer(&nodes[2])) + copy(data[:], []byte("barfooz")) + copy(data[7:], []byte("helloworldbye")) + + // Deserialize page into a leaf. + n := &node{} + n.read(page) + + // Check that there are two inodes with correct data. + if !n.isLeaf { + t.Fatal("expected leaf") + } + if len(n.inodes) != 2 { + t.Fatalf("exp=2; got=%d", len(n.inodes)) + } + if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "fooz" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "helloworld" || string(v) != "bye" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } +} + +// Ensure that a node can serialize into a leaf page. +func TestNode_write_LeafPage(t *testing.T) { + // Create a node. + n := &node{isLeaf: true, inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("susy"), []byte("susy"), []byte("que"), 0, 0) + n.put([]byte("ricki"), []byte("ricki"), []byte("lake"), 0, 0) + n.put([]byte("john"), []byte("john"), []byte("johnson"), 0, 0) + + // Write it to a page. + var buf [4096]byte + p := (*page)(unsafe.Pointer(&buf[0])) + n.write(p) + + // Read the page back in. + n2 := &node{} + n2.read(p) + + // Check that the two pages are the same. + if len(n2.inodes) != 3 { + t.Fatalf("exp=3; got=%d", len(n2.inodes)) + } + if k, v := n2.inodes[0].key, n2.inodes[0].value; string(k) != "john" || string(v) != "johnson" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n2.inodes[1].key, n2.inodes[1].value; string(k) != "ricki" || string(v) != "lake" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n2.inodes[2].key, n2.inodes[2].value; string(k) != "susy" || string(v) != "que" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } +} + +// Ensure that a node can split into appropriate subgroups. +func TestNode_split(t *testing.T) { + // Create a node. + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000004"), []byte("00000004"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000005"), []byte("00000005"), []byte("0123456701234567"), 0, 0) + + // Split between 2 & 3. + n.split(100) + + var parent = n.parent + if len(parent.children) != 2 { + t.Fatalf("exp=2; got=%d", len(parent.children)) + } + if len(parent.children[0].inodes) != 2 { + t.Fatalf("exp=2; got=%d", len(parent.children[0].inodes)) + } + if len(parent.children[1].inodes) != 3 { + t.Fatalf("exp=3; got=%d", len(parent.children[1].inodes)) + } +} + +// Ensure that a page with the minimum number of inodes just returns a single node. +func TestNode_split_MinKeys(t *testing.T) { + // Create a node. + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0) + + // Split. + n.split(20) + if n.parent != nil { + t.Fatalf("expected nil parent") + } +} + +// Ensure that a node that has keys that all fit on a page just returns one leaf. +func TestNode_split_SinglePage(t *testing.T) { + // Create a node. + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000004"), []byte("00000004"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000005"), []byte("00000005"), []byte("0123456701234567"), 0, 0) + + // Split. + n.split(4096) + if n.parent != nil { + t.Fatalf("expected nil parent") + } +} diff --git a/vendor/github.com/boltdb/bolt/page.go b/vendor/github.com/boltdb/bolt/page.go new file mode 100644 index 0000000..cde403a --- /dev/null +++ b/vendor/github.com/boltdb/bolt/page.go @@ -0,0 +1,197 @@ +package bolt + +import ( + "fmt" + "os" + "sort" + "unsafe" +) + +const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr)) + +const minKeysPerPage = 2 + +const branchPageElementSize = int(unsafe.Sizeof(branchPageElement{})) +const leafPageElementSize = int(unsafe.Sizeof(leafPageElement{})) + +const ( + branchPageFlag = 0x01 + leafPageFlag = 0x02 + metaPageFlag = 0x04 + freelistPageFlag = 0x10 +) + +const ( + bucketLeafFlag = 0x01 +) + +type pgid uint64 + +type page struct { + id pgid + flags uint16 + count uint16 + overflow uint32 + ptr uintptr +} + +// typ returns a human readable page type string used for debugging. +func (p *page) typ() string { + if (p.flags & branchPageFlag) != 0 { + return "branch" + } else if (p.flags & leafPageFlag) != 0 { + return "leaf" + } else if (p.flags & metaPageFlag) != 0 { + return "meta" + } else if (p.flags & freelistPageFlag) != 0 { + return "freelist" + } + return fmt.Sprintf("unknown<%02x>", p.flags) +} + +// meta returns a pointer to the metadata section of the page. +func (p *page) meta() *meta { + return (*meta)(unsafe.Pointer(&p.ptr)) +} + +// leafPageElement retrieves the leaf node by index +func (p *page) leafPageElement(index uint16) *leafPageElement { + n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index] + return n +} + +// leafPageElements retrieves a list of leaf nodes. +func (p *page) leafPageElements() []leafPageElement { + if p.count == 0 { + return nil + } + return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:] +} + +// branchPageElement retrieves the branch node by index +func (p *page) branchPageElement(index uint16) *branchPageElement { + return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index] +} + +// branchPageElements retrieves a list of branch nodes. +func (p *page) branchPageElements() []branchPageElement { + if p.count == 0 { + return nil + } + return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:] +} + +// dump writes n bytes of the page to STDERR as hex output. +func (p *page) hexdump(n int) { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:n] + fmt.Fprintf(os.Stderr, "%x\n", buf) +} + +type pages []*page + +func (s pages) Len() int { return len(s) } +func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s pages) Less(i, j int) bool { return s[i].id < s[j].id } + +// branchPageElement represents a node on a branch page. +type branchPageElement struct { + pos uint32 + ksize uint32 + pgid pgid +} + +// key returns a byte slice of the node key. +func (n *branchPageElement) key() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize] +} + +// leafPageElement represents a node on a leaf page. +type leafPageElement struct { + flags uint32 + pos uint32 + ksize uint32 + vsize uint32 +} + +// key returns a byte slice of the node key. +func (n *leafPageElement) key() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize:n.ksize] +} + +// value returns a byte slice of the node value. +func (n *leafPageElement) value() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize:n.vsize] +} + +// PageInfo represents human readable information about a page. +type PageInfo struct { + ID int + Type string + Count int + OverflowCount int +} + +type pgids []pgid + +func (s pgids) Len() int { return len(s) } +func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s pgids) Less(i, j int) bool { return s[i] < s[j] } + +// merge returns the sorted union of a and b. +func (a pgids) merge(b pgids) pgids { + // Return the opposite slice if one is nil. + if len(a) == 0 { + return b + } + if len(b) == 0 { + return a + } + merged := make(pgids, len(a)+len(b)) + mergepgids(merged, a, b) + return merged +} + +// mergepgids copies the sorted union of a and b into dst. +// If dst is too small, it panics. +func mergepgids(dst, a, b pgids) { + if len(dst) < len(a)+len(b) { + panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b))) + } + // Copy in the opposite slice if one is nil. + if len(a) == 0 { + copy(dst, b) + return + } + if len(b) == 0 { + copy(dst, a) + return + } + + // Merged will hold all elements from both lists. + merged := dst[:0] + + // Assign lead to the slice with a lower starting value, follow to the higher value. + lead, follow := a, b + if b[0] < a[0] { + lead, follow = b, a + } + + // Continue while there are elements in the lead. + for len(lead) > 0 { + // Merge largest prefix of lead that is ahead of follow[0]. + n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] }) + merged = append(merged, lead[:n]...) + if n >= len(lead) { + break + } + + // Swap lead and follow. + lead, follow = follow, lead[n:] + } + + // Append what's left in follow. + _ = append(merged, follow...) +} diff --git a/vendor/github.com/boltdb/bolt/page_test.go b/vendor/github.com/boltdb/bolt/page_test.go new file mode 100644 index 0000000..59f4a30 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/page_test.go @@ -0,0 +1,72 @@ +package bolt + +import ( + "reflect" + "sort" + "testing" + "testing/quick" +) + +// Ensure that the page type can be returned in human readable format. +func TestPage_typ(t *testing.T) { + if typ := (&page{flags: branchPageFlag}).typ(); typ != "branch" { + t.Fatalf("exp=branch; got=%v", typ) + } + if typ := (&page{flags: leafPageFlag}).typ(); typ != "leaf" { + t.Fatalf("exp=leaf; got=%v", typ) + } + if typ := (&page{flags: metaPageFlag}).typ(); typ != "meta" { + t.Fatalf("exp=meta; got=%v", typ) + } + if typ := (&page{flags: freelistPageFlag}).typ(); typ != "freelist" { + t.Fatalf("exp=freelist; got=%v", typ) + } + if typ := (&page{flags: 20000}).typ(); typ != "unknown<4e20>" { + t.Fatalf("exp=unknown<4e20>; got=%v", typ) + } +} + +// Ensure that the hexdump debugging function doesn't blow up. +func TestPage_dump(t *testing.T) { + (&page{id: 256}).hexdump(16) +} + +func TestPgids_merge(t *testing.T) { + a := pgids{4, 5, 6, 10, 11, 12, 13, 27} + b := pgids{1, 3, 8, 9, 25, 30} + c := a.merge(b) + if !reflect.DeepEqual(c, pgids{1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30}) { + t.Errorf("mismatch: %v", c) + } + + a = pgids{4, 5, 6, 10, 11, 12, 13, 27, 35, 36} + b = pgids{8, 9, 25, 30} + c = a.merge(b) + if !reflect.DeepEqual(c, pgids{4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30, 35, 36}) { + t.Errorf("mismatch: %v", c) + } +} + +func TestPgids_merge_quick(t *testing.T) { + if err := quick.Check(func(a, b pgids) bool { + // Sort incoming lists. + sort.Sort(a) + sort.Sort(b) + + // Merge the two lists together. + got := a.merge(b) + + // The expected value should be the two lists combined and sorted. + exp := append(a, b...) + sort.Sort(exp) + + if !reflect.DeepEqual(exp, got) { + t.Errorf("\nexp=%+v\ngot=%+v\n", exp, got) + return false + } + + return true + }, nil); err != nil { + t.Fatal(err) + } +} diff --git a/vendor/github.com/boltdb/bolt/quick_test.go b/vendor/github.com/boltdb/bolt/quick_test.go new file mode 100644 index 0000000..9e27792 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/quick_test.go @@ -0,0 +1,87 @@ +package bolt_test + +import ( + "bytes" + "flag" + "fmt" + "math/rand" + "os" + "reflect" + "testing/quick" + "time" +) + +// testing/quick defaults to 5 iterations and a random seed. +// You can override these settings from the command line: +// +// -quick.count The number of iterations to perform. +// -quick.seed The seed to use for randomizing. +// -quick.maxitems The maximum number of items to insert into a DB. +// -quick.maxksize The maximum size of a key. +// -quick.maxvsize The maximum size of a value. +// + +var qcount, qseed, qmaxitems, qmaxksize, qmaxvsize int + +func init() { + flag.IntVar(&qcount, "quick.count", 5, "") + flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "") + flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "") + flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "") + flag.IntVar(&qmaxvsize, "quick.maxvsize", 1024, "") + flag.Parse() + fmt.Fprintln(os.Stderr, "seed:", qseed) + fmt.Fprintf(os.Stderr, "quick settings: count=%v, items=%v, ksize=%v, vsize=%v\n", qcount, qmaxitems, qmaxksize, qmaxvsize) +} + +func qconfig() *quick.Config { + return &quick.Config{ + MaxCount: qcount, + Rand: rand.New(rand.NewSource(int64(qseed))), + } +} + +type testdata []testdataitem + +func (t testdata) Len() int { return len(t) } +func (t testdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t testdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == -1 } + +func (t testdata) Generate(rand *rand.Rand, size int) reflect.Value { + n := rand.Intn(qmaxitems-1) + 1 + items := make(testdata, n) + used := make(map[string]bool) + for i := 0; i < n; i++ { + item := &items[i] + // Ensure that keys are unique by looping until we find one that we have not already used. + for { + item.Key = randByteSlice(rand, 1, qmaxksize) + if !used[string(item.Key)] { + used[string(item.Key)] = true + break + } + } + item.Value = randByteSlice(rand, 0, qmaxvsize) + } + return reflect.ValueOf(items) +} + +type revtestdata []testdataitem + +func (t revtestdata) Len() int { return len(t) } +func (t revtestdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t revtestdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == 1 } + +type testdataitem struct { + Key []byte + Value []byte +} + +func randByteSlice(rand *rand.Rand, minSize, maxSize int) []byte { + n := rand.Intn(maxSize-minSize) + minSize + b := make([]byte, n) + for i := 0; i < n; i++ { + b[i] = byte(rand.Intn(255)) + } + return b +} diff --git a/vendor/github.com/boltdb/bolt/simulation_test.go b/vendor/github.com/boltdb/bolt/simulation_test.go new file mode 100644 index 0000000..3831016 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/simulation_test.go @@ -0,0 +1,329 @@ +package bolt_test + +import ( + "bytes" + "fmt" + "math/rand" + "sync" + "testing" + + "github.com/boltdb/bolt" +) + +func TestSimulate_1op_1p(t *testing.T) { testSimulate(t, 1, 1) } +func TestSimulate_10op_1p(t *testing.T) { testSimulate(t, 10, 1) } +func TestSimulate_100op_1p(t *testing.T) { testSimulate(t, 100, 1) } +func TestSimulate_1000op_1p(t *testing.T) { testSimulate(t, 1000, 1) } +func TestSimulate_10000op_1p(t *testing.T) { testSimulate(t, 10000, 1) } + +func TestSimulate_10op_10p(t *testing.T) { testSimulate(t, 10, 10) } +func TestSimulate_100op_10p(t *testing.T) { testSimulate(t, 100, 10) } +func TestSimulate_1000op_10p(t *testing.T) { testSimulate(t, 1000, 10) } +func TestSimulate_10000op_10p(t *testing.T) { testSimulate(t, 10000, 10) } + +func TestSimulate_100op_100p(t *testing.T) { testSimulate(t, 100, 100) } +func TestSimulate_1000op_100p(t *testing.T) { testSimulate(t, 1000, 100) } +func TestSimulate_10000op_100p(t *testing.T) { testSimulate(t, 10000, 100) } + +func TestSimulate_10000op_1000p(t *testing.T) { testSimulate(t, 10000, 1000) } + +// Randomly generate operations on a given database with multiple clients to ensure consistency and thread safety. +func testSimulate(t *testing.T, threadCount, parallelism int) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + rand.Seed(int64(qseed)) + + // A list of operations that readers and writers can perform. + var readerHandlers = []simulateHandler{simulateGetHandler} + var writerHandlers = []simulateHandler{simulateGetHandler, simulatePutHandler} + + var versions = make(map[int]*QuickDB) + versions[1] = NewQuickDB() + + db := MustOpenDB() + defer db.MustClose() + + var mutex sync.Mutex + + // Run n threads in parallel, each with their own operation. + var wg sync.WaitGroup + var threads = make(chan bool, parallelism) + var i int + for { + threads <- true + wg.Add(1) + writable := ((rand.Int() % 100) < 20) // 20% writers + + // Choose an operation to execute. + var handler simulateHandler + if writable { + handler = writerHandlers[rand.Intn(len(writerHandlers))] + } else { + handler = readerHandlers[rand.Intn(len(readerHandlers))] + } + + // Execute a thread for the given operation. + go func(writable bool, handler simulateHandler) { + defer wg.Done() + + // Start transaction. + tx, err := db.Begin(writable) + if err != nil { + t.Fatal("tx begin: ", err) + } + + // Obtain current state of the dataset. + mutex.Lock() + var qdb = versions[tx.ID()] + if writable { + qdb = versions[tx.ID()-1].Copy() + } + mutex.Unlock() + + // Make sure we commit/rollback the tx at the end and update the state. + if writable { + defer func() { + mutex.Lock() + versions[tx.ID()] = qdb + mutex.Unlock() + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + }() + } else { + defer func() { _ = tx.Rollback() }() + } + + // Ignore operation if we don't have data yet. + if qdb == nil { + return + } + + // Execute handler. + handler(tx, qdb) + + // Release a thread back to the scheduling loop. + <-threads + }(writable, handler) + + i++ + if i > threadCount { + break + } + } + + // Wait until all threads are done. + wg.Wait() +} + +type simulateHandler func(tx *bolt.Tx, qdb *QuickDB) + +// Retrieves a key from the database and verifies that it is what is expected. +func simulateGetHandler(tx *bolt.Tx, qdb *QuickDB) { + // Randomly retrieve an existing exist. + keys := qdb.Rand() + if len(keys) == 0 { + return + } + + // Retrieve root bucket. + b := tx.Bucket(keys[0]) + if b == nil { + panic(fmt.Sprintf("bucket[0] expected: %08x\n", trunc(keys[0], 4))) + } + + // Drill into nested buckets. + for _, key := range keys[1 : len(keys)-1] { + b = b.Bucket(key) + if b == nil { + panic(fmt.Sprintf("bucket[n] expected: %v -> %v\n", keys, key)) + } + } + + // Verify key/value on the final bucket. + expected := qdb.Get(keys) + actual := b.Get(keys[len(keys)-1]) + if !bytes.Equal(actual, expected) { + fmt.Println("=== EXPECTED ===") + fmt.Println(expected) + fmt.Println("=== ACTUAL ===") + fmt.Println(actual) + fmt.Println("=== END ===") + panic("value mismatch") + } +} + +// Inserts a key into the database. +func simulatePutHandler(tx *bolt.Tx, qdb *QuickDB) { + var err error + keys, value := randKeys(), randValue() + + // Retrieve root bucket. + b := tx.Bucket(keys[0]) + if b == nil { + b, err = tx.CreateBucket(keys[0]) + if err != nil { + panic("create bucket: " + err.Error()) + } + } + + // Create nested buckets, if necessary. + for _, key := range keys[1 : len(keys)-1] { + child := b.Bucket(key) + if child != nil { + b = child + } else { + b, err = b.CreateBucket(key) + if err != nil { + panic("create bucket: " + err.Error()) + } + } + } + + // Insert into database. + if err := b.Put(keys[len(keys)-1], value); err != nil { + panic("put: " + err.Error()) + } + + // Insert into in-memory database. + qdb.Put(keys, value) +} + +// QuickDB is an in-memory database that replicates the functionality of the +// Bolt DB type except that it is entirely in-memory. It is meant for testing +// that the Bolt database is consistent. +type QuickDB struct { + sync.RWMutex + m map[string]interface{} +} + +// NewQuickDB returns an instance of QuickDB. +func NewQuickDB() *QuickDB { + return &QuickDB{m: make(map[string]interface{})} +} + +// Get retrieves the value at a key path. +func (db *QuickDB) Get(keys [][]byte) []byte { + db.RLock() + defer db.RUnlock() + + m := db.m + for _, key := range keys[:len(keys)-1] { + value := m[string(key)] + if value == nil { + return nil + } + switch value := value.(type) { + case map[string]interface{}: + m = value + case []byte: + return nil + } + } + + // Only return if it's a simple value. + if value, ok := m[string(keys[len(keys)-1])].([]byte); ok { + return value + } + return nil +} + +// Put inserts a value into a key path. +func (db *QuickDB) Put(keys [][]byte, value []byte) { + db.Lock() + defer db.Unlock() + + // Build buckets all the way down the key path. + m := db.m + for _, key := range keys[:len(keys)-1] { + if _, ok := m[string(key)].([]byte); ok { + return // Keypath intersects with a simple value. Do nothing. + } + + if m[string(key)] == nil { + m[string(key)] = make(map[string]interface{}) + } + m = m[string(key)].(map[string]interface{}) + } + + // Insert value into the last key. + m[string(keys[len(keys)-1])] = value +} + +// Rand returns a random key path that points to a simple value. +func (db *QuickDB) Rand() [][]byte { + db.RLock() + defer db.RUnlock() + if len(db.m) == 0 { + return nil + } + var keys [][]byte + db.rand(db.m, &keys) + return keys +} + +func (db *QuickDB) rand(m map[string]interface{}, keys *[][]byte) { + i, index := 0, rand.Intn(len(m)) + for k, v := range m { + if i == index { + *keys = append(*keys, []byte(k)) + if v, ok := v.(map[string]interface{}); ok { + db.rand(v, keys) + } + return + } + i++ + } + panic("quickdb rand: out-of-range") +} + +// Copy copies the entire database. +func (db *QuickDB) Copy() *QuickDB { + db.RLock() + defer db.RUnlock() + return &QuickDB{m: db.copy(db.m)} +} + +func (db *QuickDB) copy(m map[string]interface{}) map[string]interface{} { + clone := make(map[string]interface{}, len(m)) + for k, v := range m { + switch v := v.(type) { + case map[string]interface{}: + clone[k] = db.copy(v) + default: + clone[k] = v + } + } + return clone +} + +func randKey() []byte { + var min, max = 1, 1024 + n := rand.Intn(max-min) + min + b := make([]byte, n) + for i := 0; i < n; i++ { + b[i] = byte(rand.Intn(255)) + } + return b +} + +func randKeys() [][]byte { + var keys [][]byte + var count = rand.Intn(2) + 2 + for i := 0; i < count; i++ { + keys = append(keys, randKey()) + } + return keys +} + +func randValue() []byte { + n := rand.Intn(8192) + b := make([]byte, n) + for i := 0; i < n; i++ { + b[i] = byte(rand.Intn(255)) + } + return b +} diff --git a/vendor/github.com/boltdb/bolt/tx.go b/vendor/github.com/boltdb/bolt/tx.go new file mode 100644 index 0000000..6700308 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/tx.go @@ -0,0 +1,684 @@ +package bolt + +import ( + "fmt" + "io" + "os" + "sort" + "strings" + "time" + "unsafe" +) + +// txid represents the internal transaction identifier. +type txid uint64 + +// Tx represents a read-only or read/write transaction on the database. +// Read-only transactions can be used for retrieving values for keys and creating cursors. +// Read/write transactions can create and remove buckets and create and remove keys. +// +// IMPORTANT: You must commit or rollback transactions when you are done with +// them. Pages can not be reclaimed by the writer until no more transactions +// are using them. A long running read transaction can cause the database to +// quickly grow. +type Tx struct { + writable bool + managed bool + db *DB + meta *meta + root Bucket + pages map[pgid]*page + stats TxStats + commitHandlers []func() + + // WriteFlag specifies the flag for write-related methods like WriteTo(). + // Tx opens the database file with the specified flag to copy the data. + // + // By default, the flag is unset, which works well for mostly in-memory + // workloads. For databases that are much larger than available RAM, + // set the flag to syscall.O_DIRECT to avoid trashing the page cache. + WriteFlag int +} + +// init initializes the transaction. +func (tx *Tx) init(db *DB) { + tx.db = db + tx.pages = nil + + // Copy the meta page since it can be changed by the writer. + tx.meta = &meta{} + db.meta().copy(tx.meta) + + // Copy over the root bucket. + tx.root = newBucket(tx) + tx.root.bucket = &bucket{} + *tx.root.bucket = tx.meta.root + + // Increment the transaction id and add a page cache for writable transactions. + if tx.writable { + tx.pages = make(map[pgid]*page) + tx.meta.txid += txid(1) + } +} + +// ID returns the transaction id. +func (tx *Tx) ID() int { + return int(tx.meta.txid) +} + +// DB returns a reference to the database that created the transaction. +func (tx *Tx) DB() *DB { + return tx.db +} + +// Size returns current database size in bytes as seen by this transaction. +func (tx *Tx) Size() int64 { + return int64(tx.meta.pgid) * int64(tx.db.pageSize) +} + +// Writable returns whether the transaction can perform write operations. +func (tx *Tx) Writable() bool { + return tx.writable +} + +// Cursor creates a cursor associated with the root bucket. +// All items in the cursor will return a nil value because all root bucket keys point to buckets. +// The cursor is only valid as long as the transaction is open. +// Do not use a cursor after the transaction is closed. +func (tx *Tx) Cursor() *Cursor { + return tx.root.Cursor() +} + +// Stats retrieves a copy of the current transaction statistics. +func (tx *Tx) Stats() TxStats { + return tx.stats +} + +// Bucket retrieves a bucket by name. +// Returns nil if the bucket does not exist. +// The bucket instance is only valid for the lifetime of the transaction. +func (tx *Tx) Bucket(name []byte) *Bucket { + return tx.root.Bucket(name) +} + +// CreateBucket creates a new bucket. +// Returns an error if the bucket already exists, if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (tx *Tx) CreateBucket(name []byte) (*Bucket, error) { + return tx.root.CreateBucket(name) +} + +// CreateBucketIfNotExists creates a new bucket if it doesn't already exist. +// Returns an error if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (tx *Tx) CreateBucketIfNotExists(name []byte) (*Bucket, error) { + return tx.root.CreateBucketIfNotExists(name) +} + +// DeleteBucket deletes a bucket. +// Returns an error if the bucket cannot be found or if the key represents a non-bucket value. +func (tx *Tx) DeleteBucket(name []byte) error { + return tx.root.DeleteBucket(name) +} + +// ForEach executes a function for each bucket in the root. +// If the provided function returns an error then the iteration is stopped and +// the error is returned to the caller. +func (tx *Tx) ForEach(fn func(name []byte, b *Bucket) error) error { + return tx.root.ForEach(func(k, v []byte) error { + if err := fn(k, tx.root.Bucket(k)); err != nil { + return err + } + return nil + }) +} + +// OnCommit adds a handler function to be executed after the transaction successfully commits. +func (tx *Tx) OnCommit(fn func()) { + tx.commitHandlers = append(tx.commitHandlers, fn) +} + +// Commit writes all changes to disk and updates the meta page. +// Returns an error if a disk write error occurs, or if Commit is +// called on a read-only transaction. +func (tx *Tx) Commit() error { + _assert(!tx.managed, "managed tx commit not allowed") + if tx.db == nil { + return ErrTxClosed + } else if !tx.writable { + return ErrTxNotWritable + } + + // TODO(benbjohnson): Use vectorized I/O to write out dirty pages. + + // Rebalance nodes which have had deletions. + var startTime = time.Now() + tx.root.rebalance() + if tx.stats.Rebalance > 0 { + tx.stats.RebalanceTime += time.Since(startTime) + } + + // spill data onto dirty pages. + startTime = time.Now() + if err := tx.root.spill(); err != nil { + tx.rollback() + return err + } + tx.stats.SpillTime += time.Since(startTime) + + // Free the old root bucket. + tx.meta.root.root = tx.root.root + + opgid := tx.meta.pgid + + // Free the freelist and allocate new pages for it. This will overestimate + // the size of the freelist but not underestimate the size (which would be bad). + tx.db.freelist.free(tx.meta.txid, tx.db.page(tx.meta.freelist)) + p, err := tx.allocate((tx.db.freelist.size() / tx.db.pageSize) + 1) + if err != nil { + tx.rollback() + return err + } + if err := tx.db.freelist.write(p); err != nil { + tx.rollback() + return err + } + tx.meta.freelist = p.id + + // If the high water mark has moved up then attempt to grow the database. + if tx.meta.pgid > opgid { + if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil { + tx.rollback() + return err + } + } + + // Write dirty pages to disk. + startTime = time.Now() + if err := tx.write(); err != nil { + tx.rollback() + return err + } + + // If strict mode is enabled then perform a consistency check. + // Only the first consistency error is reported in the panic. + if tx.db.StrictMode { + ch := tx.Check() + var errs []string + for { + err, ok := <-ch + if !ok { + break + } + errs = append(errs, err.Error()) + } + if len(errs) > 0 { + panic("check fail: " + strings.Join(errs, "\n")) + } + } + + // Write meta to disk. + if err := tx.writeMeta(); err != nil { + tx.rollback() + return err + } + tx.stats.WriteTime += time.Since(startTime) + + // Finalize the transaction. + tx.close() + + // Execute commit handlers now that the locks have been removed. + for _, fn := range tx.commitHandlers { + fn() + } + + return nil +} + +// Rollback closes the transaction and ignores all previous updates. Read-only +// transactions must be rolled back and not committed. +func (tx *Tx) Rollback() error { + _assert(!tx.managed, "managed tx rollback not allowed") + if tx.db == nil { + return ErrTxClosed + } + tx.rollback() + return nil +} + +func (tx *Tx) rollback() { + if tx.db == nil { + return + } + if tx.writable { + tx.db.freelist.rollback(tx.meta.txid) + tx.db.freelist.reload(tx.db.page(tx.db.meta().freelist)) + } + tx.close() +} + +func (tx *Tx) close() { + if tx.db == nil { + return + } + if tx.writable { + // Grab freelist stats. + var freelistFreeN = tx.db.freelist.free_count() + var freelistPendingN = tx.db.freelist.pending_count() + var freelistAlloc = tx.db.freelist.size() + + // Remove transaction ref & writer lock. + tx.db.rwtx = nil + tx.db.rwlock.Unlock() + + // Merge statistics. + tx.db.statlock.Lock() + tx.db.stats.FreePageN = freelistFreeN + tx.db.stats.PendingPageN = freelistPendingN + tx.db.stats.FreeAlloc = (freelistFreeN + freelistPendingN) * tx.db.pageSize + tx.db.stats.FreelistInuse = freelistAlloc + tx.db.stats.TxStats.add(&tx.stats) + tx.db.statlock.Unlock() + } else { + tx.db.removeTx(tx) + } + + // Clear all references. + tx.db = nil + tx.meta = nil + tx.root = Bucket{tx: tx} + tx.pages = nil +} + +// Copy writes the entire database to a writer. +// This function exists for backwards compatibility. Use WriteTo() instead. +func (tx *Tx) Copy(w io.Writer) error { + _, err := tx.WriteTo(w) + return err +} + +// WriteTo writes the entire database to a writer. +// If err == nil then exactly tx.Size() bytes will be written into the writer. +func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { + // Attempt to open reader with WriteFlag + f, err := os.OpenFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0) + if err != nil { + return 0, err + } + defer func() { _ = f.Close() }() + + // Generate a meta page. We use the same page data for both meta pages. + buf := make([]byte, tx.db.pageSize) + page := (*page)(unsafe.Pointer(&buf[0])) + page.flags = metaPageFlag + *page.meta() = *tx.meta + + // Write meta 0. + page.id = 0 + page.meta().checksum = page.meta().sum64() + nn, err := w.Write(buf) + n += int64(nn) + if err != nil { + return n, fmt.Errorf("meta 0 copy: %s", err) + } + + // Write meta 1 with a lower transaction id. + page.id = 1 + page.meta().txid -= 1 + page.meta().checksum = page.meta().sum64() + nn, err = w.Write(buf) + n += int64(nn) + if err != nil { + return n, fmt.Errorf("meta 1 copy: %s", err) + } + + // Move past the meta pages in the file. + if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil { + return n, fmt.Errorf("seek: %s", err) + } + + // Copy data pages. + wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2)) + n += wn + if err != nil { + return n, err + } + + return n, f.Close() +} + +// CopyFile copies the entire database to file at the given path. +// A reader transaction is maintained during the copy so it is safe to continue +// using the database while a copy is in progress. +func (tx *Tx) CopyFile(path string, mode os.FileMode) error { + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) + if err != nil { + return err + } + + err = tx.Copy(f) + if err != nil { + _ = f.Close() + return err + } + return f.Close() +} + +// Check performs several consistency checks on the database for this transaction. +// An error is returned if any inconsistency is found. +// +// It can be safely run concurrently on a writable transaction. However, this +// incurs a high cost for large databases and databases with a lot of subbuckets +// because of caching. This overhead can be removed if running on a read-only +// transaction, however, it is not safe to execute other writer transactions at +// the same time. +func (tx *Tx) Check() <-chan error { + ch := make(chan error) + go tx.check(ch) + return ch +} + +func (tx *Tx) check(ch chan error) { + // Check if any pages are double freed. + freed := make(map[pgid]bool) + all := make([]pgid, tx.db.freelist.count()) + tx.db.freelist.copyall(all) + for _, id := range all { + if freed[id] { + ch <- fmt.Errorf("page %d: already freed", id) + } + freed[id] = true + } + + // Track every reachable page. + reachable := make(map[pgid]*page) + reachable[0] = tx.page(0) // meta0 + reachable[1] = tx.page(1) // meta1 + for i := uint32(0); i <= tx.page(tx.meta.freelist).overflow; i++ { + reachable[tx.meta.freelist+pgid(i)] = tx.page(tx.meta.freelist) + } + + // Recursively check buckets. + tx.checkBucket(&tx.root, reachable, freed, ch) + + // Ensure all pages below high water mark are either reachable or freed. + for i := pgid(0); i < tx.meta.pgid; i++ { + _, isReachable := reachable[i] + if !isReachable && !freed[i] { + ch <- fmt.Errorf("page %d: unreachable unfreed", int(i)) + } + } + + // Close the channel to signal completion. + close(ch) +} + +func (tx *Tx) checkBucket(b *Bucket, reachable map[pgid]*page, freed map[pgid]bool, ch chan error) { + // Ignore inline buckets. + if b.root == 0 { + return + } + + // Check every page used by this bucket. + b.tx.forEachPage(b.root, 0, func(p *page, _ int) { + if p.id > tx.meta.pgid { + ch <- fmt.Errorf("page %d: out of bounds: %d", int(p.id), int(b.tx.meta.pgid)) + } + + // Ensure each page is only referenced once. + for i := pgid(0); i <= pgid(p.overflow); i++ { + var id = p.id + i + if _, ok := reachable[id]; ok { + ch <- fmt.Errorf("page %d: multiple references", int(id)) + } + reachable[id] = p + } + + // We should only encounter un-freed leaf and branch pages. + if freed[p.id] { + ch <- fmt.Errorf("page %d: reachable freed", int(p.id)) + } else if (p.flags&branchPageFlag) == 0 && (p.flags&leafPageFlag) == 0 { + ch <- fmt.Errorf("page %d: invalid type: %s", int(p.id), p.typ()) + } + }) + + // Check each bucket within this bucket. + _ = b.ForEach(func(k, v []byte) error { + if child := b.Bucket(k); child != nil { + tx.checkBucket(child, reachable, freed, ch) + } + return nil + }) +} + +// allocate returns a contiguous block of memory starting at a given page. +func (tx *Tx) allocate(count int) (*page, error) { + p, err := tx.db.allocate(count) + if err != nil { + return nil, err + } + + // Save to our page cache. + tx.pages[p.id] = p + + // Update statistics. + tx.stats.PageCount++ + tx.stats.PageAlloc += count * tx.db.pageSize + + return p, nil +} + +// write writes any dirty pages to disk. +func (tx *Tx) write() error { + // Sort pages by id. + pages := make(pages, 0, len(tx.pages)) + for _, p := range tx.pages { + pages = append(pages, p) + } + // Clear out page cache early. + tx.pages = make(map[pgid]*page) + sort.Sort(pages) + + // Write pages to disk in order. + for _, p := range pages { + size := (int(p.overflow) + 1) * tx.db.pageSize + offset := int64(p.id) * int64(tx.db.pageSize) + + // Write out page in "max allocation" sized chunks. + ptr := (*[maxAllocSize]byte)(unsafe.Pointer(p)) + for { + // Limit our write to our max allocation size. + sz := size + if sz > maxAllocSize-1 { + sz = maxAllocSize - 1 + } + + // Write chunk to disk. + buf := ptr[:sz] + if _, err := tx.db.ops.writeAt(buf, offset); err != nil { + return err + } + + // Update statistics. + tx.stats.Write++ + + // Exit inner for loop if we've written all the chunks. + size -= sz + if size == 0 { + break + } + + // Otherwise move offset forward and move pointer to next chunk. + offset += int64(sz) + ptr = (*[maxAllocSize]byte)(unsafe.Pointer(&ptr[sz])) + } + } + + // Ignore file sync if flag is set on DB. + if !tx.db.NoSync || IgnoreNoSync { + if err := fdatasync(tx.db); err != nil { + return err + } + } + + // Put small pages back to page pool. + for _, p := range pages { + // Ignore page sizes over 1 page. + // These are allocated using make() instead of the page pool. + if int(p.overflow) != 0 { + continue + } + + buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:tx.db.pageSize] + + // See https://go.googlesource.com/go/+/f03c9202c43e0abb130669852082117ca50aa9b1 + for i := range buf { + buf[i] = 0 + } + tx.db.pagePool.Put(buf) + } + + return nil +} + +// writeMeta writes the meta to the disk. +func (tx *Tx) writeMeta() error { + // Create a temporary buffer for the meta page. + buf := make([]byte, tx.db.pageSize) + p := tx.db.pageInBuffer(buf, 0) + tx.meta.write(p) + + // Write the meta page to file. + if _, err := tx.db.ops.writeAt(buf, int64(p.id)*int64(tx.db.pageSize)); err != nil { + return err + } + if !tx.db.NoSync || IgnoreNoSync { + if err := fdatasync(tx.db); err != nil { + return err + } + } + + // Update statistics. + tx.stats.Write++ + + return nil +} + +// page returns a reference to the page with a given id. +// If page has been written to then a temporary buffered page is returned. +func (tx *Tx) page(id pgid) *page { + // Check the dirty pages first. + if tx.pages != nil { + if p, ok := tx.pages[id]; ok { + return p + } + } + + // Otherwise return directly from the mmap. + return tx.db.page(id) +} + +// forEachPage iterates over every page within a given page and executes a function. +func (tx *Tx) forEachPage(pgid pgid, depth int, fn func(*page, int)) { + p := tx.page(pgid) + + // Execute function. + fn(p, depth) + + // Recursively loop over children. + if (p.flags & branchPageFlag) != 0 { + for i := 0; i < int(p.count); i++ { + elem := p.branchPageElement(uint16(i)) + tx.forEachPage(elem.pgid, depth+1, fn) + } + } +} + +// Page returns page information for a given page number. +// This is only safe for concurrent use when used by a writable transaction. +func (tx *Tx) Page(id int) (*PageInfo, error) { + if tx.db == nil { + return nil, ErrTxClosed + } else if pgid(id) >= tx.meta.pgid { + return nil, nil + } + + // Build the page info. + p := tx.db.page(pgid(id)) + info := &PageInfo{ + ID: id, + Count: int(p.count), + OverflowCount: int(p.overflow), + } + + // Determine the type (or if it's free). + if tx.db.freelist.freed(pgid(id)) { + info.Type = "free" + } else { + info.Type = p.typ() + } + + return info, nil +} + +// TxStats represents statistics about the actions performed by the transaction. +type TxStats struct { + // Page statistics. + PageCount int // number of page allocations + PageAlloc int // total bytes allocated + + // Cursor statistics. + CursorCount int // number of cursors created + + // Node statistics + NodeCount int // number of node allocations + NodeDeref int // number of node dereferences + + // Rebalance statistics. + Rebalance int // number of node rebalances + RebalanceTime time.Duration // total time spent rebalancing + + // Split/Spill statistics. + Split int // number of nodes split + Spill int // number of nodes spilled + SpillTime time.Duration // total time spent spilling + + // Write statistics. + Write int // number of writes performed + WriteTime time.Duration // total time spent writing to disk +} + +func (s *TxStats) add(other *TxStats) { + s.PageCount += other.PageCount + s.PageAlloc += other.PageAlloc + s.CursorCount += other.CursorCount + s.NodeCount += other.NodeCount + s.NodeDeref += other.NodeDeref + s.Rebalance += other.Rebalance + s.RebalanceTime += other.RebalanceTime + s.Split += other.Split + s.Spill += other.Spill + s.SpillTime += other.SpillTime + s.Write += other.Write + s.WriteTime += other.WriteTime +} + +// Sub calculates and returns the difference between two sets of transaction stats. +// This is useful when obtaining stats at two different points and time and +// you need the performance counters that occurred within that time span. +func (s *TxStats) Sub(other *TxStats) TxStats { + var diff TxStats + diff.PageCount = s.PageCount - other.PageCount + diff.PageAlloc = s.PageAlloc - other.PageAlloc + diff.CursorCount = s.CursorCount - other.CursorCount + diff.NodeCount = s.NodeCount - other.NodeCount + diff.NodeDeref = s.NodeDeref - other.NodeDeref + diff.Rebalance = s.Rebalance - other.Rebalance + diff.RebalanceTime = s.RebalanceTime - other.RebalanceTime + diff.Split = s.Split - other.Split + diff.Spill = s.Spill - other.Spill + diff.SpillTime = s.SpillTime - other.SpillTime + diff.Write = s.Write - other.Write + diff.WriteTime = s.WriteTime - other.WriteTime + return diff +} diff --git a/vendor/github.com/boltdb/bolt/tx_test.go b/vendor/github.com/boltdb/bolt/tx_test.go new file mode 100644 index 0000000..2201e79 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/tx_test.go @@ -0,0 +1,716 @@ +package bolt_test + +import ( + "bytes" + "errors" + "fmt" + "log" + "os" + "testing" + + "github.com/boltdb/bolt" +) + +// Ensure that committing a closed transaction returns an error. +func TestTx_Commit_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + if _, err := tx.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + if err := tx.Commit(); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that rolling back a closed transaction returns an error. +func TestTx_Rollback_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + if err := tx.Rollback(); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that committing a read-only transaction returns an error. +func TestTx_Commit_ErrTxNotWritable(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + if err := tx.Commit(); err != bolt.ErrTxNotWritable { + t.Fatal(err) + } +} + +// Ensure that a transaction can retrieve a cursor on the root bucket. +func TestTx_Cursor(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + + if _, err := tx.CreateBucket([]byte("woojits")); err != nil { + t.Fatal(err) + } + + c := tx.Cursor() + if k, v := c.First(); !bytes.Equal(k, []byte("widgets")) { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Next(); !bytes.Equal(k, []byte("woojits")) { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Next(); k != nil { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", k) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that creating a bucket with a read-only transaction returns an error. +func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.View(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("foo")) + if err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that creating a bucket on a closed transaction returns an error. +func TestTx_CreateBucket_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + if _, err := tx.CreateBucket([]byte("foo")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that a Tx can retrieve a bucket. +func TestTx_Bucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx retrieving a non-existent key returns nil. +func TestTx_Get_NotFound(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if b.Get([]byte("no_such_key")) != nil { + t.Fatal("expected nil value") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can be created and retrieved. +func TestTx_CreateBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } else if b == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Read the bucket through a separate transaction. + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can be created if it doesn't already exist. +func TestTx_CreateBucketIfNotExists(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + // Create bucket. + if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil { + t.Fatal(err) + } else if b == nil { + t.Fatal("expected bucket") + } + + // Create bucket again. + if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil { + t.Fatal(err) + } else if b == nil { + t.Fatal("expected bucket") + } + + return nil + }); err != nil { + t.Fatal(err) + } + + // Read the bucket through a separate transaction. + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure transaction returns an error if creating an unnamed bucket. +func TestTx_CreateBucketIfNotExists_ErrBucketNameRequired(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucketIfNotExists([]byte{}); err != bolt.ErrBucketNameRequired { + t.Fatalf("unexpected error: %s", err) + } + + if _, err := tx.CreateBucketIfNotExists(nil); err != bolt.ErrBucketNameRequired { + t.Fatalf("unexpected error: %s", err) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket cannot be created twice. +func TestTx_CreateBucket_ErrBucketExists(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Create the same bucket again. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != bolt.ErrBucketExists { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket is created with a non-blank name. +func TestTx_CreateBucket_ErrBucketNameRequired(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket(nil); err != bolt.ErrBucketNameRequired { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can be deleted. +func TestTx_DeleteBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create a bucket and add a value. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Delete the bucket and make sure we can't get the value. + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + if tx.Bucket([]byte("widgets")) != nil { + t.Fatal("unexpected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + // Create the bucket again and make sure there's not a phantom value. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); v != nil { + t.Fatalf("unexpected phantom value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket on a closed transaction returns an error. +func TestTx_DeleteBucket_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that deleting a bucket with a read-only transaction returns an error. +func TestTx_DeleteBucket_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.View(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that nothing happens when deleting a bucket that doesn't exist. +func TestTx_DeleteBucket_NotFound(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("widgets")); err != bolt.ErrBucketNotFound { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that no error is returned when a tx.ForEach function does not return +// an error. +func TestTx_ForEach_NoError(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error { + return nil + }); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that an error is returned when a tx.ForEach function returns an error. +func TestTx_ForEach_WithError(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + marker := errors.New("marker") + if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error { + return marker + }); err != marker { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that Tx commit handlers are called after a transaction successfully commits. +func TestTx_OnCommit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var x int + if err := db.Update(func(tx *bolt.Tx) error { + tx.OnCommit(func() { x += 1 }) + tx.OnCommit(func() { x += 2 }) + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } else if x != 3 { + t.Fatalf("unexpected x: %d", x) + } +} + +// Ensure that Tx commit handlers are NOT called after a transaction rolls back. +func TestTx_OnCommit_Rollback(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var x int + if err := db.Update(func(tx *bolt.Tx) error { + tx.OnCommit(func() { x += 1 }) + tx.OnCommit(func() { x += 2 }) + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return errors.New("rollback this commit") + }); err == nil || err.Error() != "rollback this commit" { + t.Fatalf("unexpected error: %s", err) + } else if x != 0 { + t.Fatalf("unexpected x: %d", x) + } +} + +// Ensure that the database can be copied to a file path. +func TestTx_CopyFile(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + path := tempfile() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + return tx.CopyFile(path, 0600) + }); err != nil { + t.Fatal(err) + } + + db2, err := bolt.Open(path, 0600, nil) + if err != nil { + t.Fatal(err) + } + + if err := db2.View(func(tx *bolt.Tx) error { + if v := tx.Bucket([]byte("widgets")).Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) { + t.Fatalf("unexpected value: %v", v) + } + if v := tx.Bucket([]byte("widgets")).Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db2.Close(); err != nil { + t.Fatal(err) + } +} + +type failWriterError struct{} + +func (failWriterError) Error() string { + return "error injected for tests" +} + +type failWriter struct { + // fail after this many bytes + After int +} + +func (f *failWriter) Write(p []byte) (n int, err error) { + n = len(p) + if n > f.After { + n = f.After + err = failWriterError{} + } + f.After -= n + return n, err +} + +// Ensure that Copy handles write errors right. +func TestTx_CopyFile_Error_Meta(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + return tx.Copy(&failWriter{}) + }); err == nil || err.Error() != "meta 0 copy: error injected for tests" { + t.Fatalf("unexpected error: %v", err) + } +} + +// Ensure that Copy handles write errors right. +func TestTx_CopyFile_Error_Normal(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + return tx.Copy(&failWriter{3 * db.Info().PageSize}) + }); err == nil || err.Error() != "error injected for tests" { + t.Fatalf("unexpected error: %v", err) + } +} + +func ExampleTx_Rollback() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Create a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + log.Fatal(err) + } + + // Set a value for a key. + if err := db.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")) + }); err != nil { + log.Fatal(err) + } + + // Update the key but rollback the transaction so it never saves. + tx, err := db.Begin(true) + if err != nil { + log.Fatal(err) + } + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("foo"), []byte("baz")); err != nil { + log.Fatal(err) + } + if err := tx.Rollback(); err != nil { + log.Fatal(err) + } + + // Ensure that our original value is still set. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value for 'foo' is still: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value for 'foo' is still: bar +} + +func ExampleTx_CopyFile() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Create a bucket and a key. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Copy the database to another file. + toFile := tempfile() + if err := db.View(func(tx *bolt.Tx) error { + return tx.CopyFile(toFile, 0666) + }); err != nil { + log.Fatal(err) + } + defer os.Remove(toFile) + + // Open the cloned database. + db2, err := bolt.Open(toFile, 0666, nil) + if err != nil { + log.Fatal(err) + } + + // Ensure that the key exists in the copy. + if err := db2.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value for 'foo' in the clone is: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + if err := db2.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value for 'foo' in the clone is: bar +} diff --git a/vendor/github.com/boombuler/barcode/.gitignore b/vendor/github.com/boombuler/barcode/.gitignore new file mode 100644 index 0000000..1d74e21 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/.gitignore @@ -0,0 +1 @@ +.vscode/ diff --git a/vendor/github.com/boombuler/barcode/LICENSE b/vendor/github.com/boombuler/barcode/LICENSE new file mode 100644 index 0000000..862b0dd --- /dev/null +++ b/vendor/github.com/boombuler/barcode/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Florian Sundermann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/boombuler/barcode/README.md b/vendor/github.com/boombuler/barcode/README.md new file mode 100644 index 0000000..2a988db --- /dev/null +++ b/vendor/github.com/boombuler/barcode/README.md @@ -0,0 +1,53 @@ +[![Join the chat at https://gitter.im/golang-barcode/Lobby](https://badges.gitter.im/golang-barcode/Lobby.svg)](https://gitter.im/golang-barcode/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## Introduction ## + +This is a package for GO which can be used to create different types of barcodes. + +## Supported Barcode Types ## +* 2 of 5 +* Aztec Code +* Codabar +* Code 128 +* Code 39 +* Code 93 +* Datamatrix +* EAN 13 +* EAN 8 +* PDF 417 +* QR Code + +## Example ## + +This is a simple example on how to create a QR-Code and write it to a png-file +```go +package main + +import ( + "image/png" + "os" + + "github.com/boombuler/barcode" + "github.com/boombuler/barcode/qr" +) + +func main() { + // Create the barcode + qrCode, _ := qr.Encode("Hello World", qr.M, qr.Auto) + + // Scale the barcode to 200x200 pixels + qrCode, _ = barcode.Scale(qrCode, 200, 200) + + // create the output file + file, _ := os.Create("qrcode.png") + defer file.Close() + + // encode the barcode as png + png.Encode(file, qrCode) +} +``` + +## Documentation ## +See [GoDoc](https://godoc.org/github.com/boombuler/barcode) + +To create a barcode use the Encode function from one of the subpackages. diff --git a/vendor/github.com/boombuler/barcode/barcode.go b/vendor/github.com/boombuler/barcode/barcode.go new file mode 100644 index 0000000..25f4a69 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/barcode.go @@ -0,0 +1,42 @@ +package barcode + +import "image" + +const ( + TypeAztec = "Aztec" + TypeCodabar = "Codabar" + TypeCode128 = "Code 128" + TypeCode39 = "Code 39" + TypeCode93 = "Code 93" + TypeDataMatrix = "DataMatrix" + TypeEAN8 = "EAN 8" + TypeEAN13 = "EAN 13" + TypePDF = "PDF417" + TypeQR = "QR Code" + Type2of5 = "2 of 5" + Type2of5Interleaved = "2 of 5 (interleaved)" +) + +// Contains some meta information about a barcode +type Metadata struct { + // the name of the barcode kind + CodeKind string + // contains 1 for 1D barcodes or 2 for 2D barcodes + Dimensions byte +} + +// a rendered and encoded barcode +type Barcode interface { + image.Image + // returns some meta information about the barcode + Metadata() Metadata + // the data that was encoded in this barcode + Content() string +} + +// Additional interface that some barcodes might implement to provide +// the value of its checksum. +type BarcodeIntCS interface { + Barcode + CheckSum() int +} diff --git a/vendor/github.com/boombuler/barcode/qr/alphanumeric.go b/vendor/github.com/boombuler/barcode/qr/alphanumeric.go new file mode 100644 index 0000000..4ded7c8 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/alphanumeric.go @@ -0,0 +1,66 @@ +package qr + +import ( + "errors" + "fmt" + "strings" + + "github.com/boombuler/barcode/utils" +) + +const charSet string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" + +func stringToAlphaIdx(content string) <-chan int { + result := make(chan int) + go func() { + for _, r := range content { + idx := strings.IndexRune(charSet, r) + result <- idx + if idx < 0 { + break + } + } + close(result) + }() + + return result +} + +func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { + + contentLenIsOdd := len(content)%2 == 1 + contentBitCount := (len(content) / 2) * 11 + if contentLenIsOdd { + contentBitCount += 6 + } + vi := findSmallestVersionInfo(ecl, alphaNumericMode, contentBitCount) + if vi == nil { + return nil, nil, errors.New("To much data to encode") + } + + res := new(utils.BitList) + res.AddBits(int(alphaNumericMode), 4) + res.AddBits(len(content), vi.charCountBits(alphaNumericMode)) + + encoder := stringToAlphaIdx(content) + + for idx := 0; idx < len(content)/2; idx++ { + c1 := <-encoder + c2 := <-encoder + if c1 < 0 || c2 < 0 { + return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric) + } + res.AddBits(c1*45+c2, 11) + } + if contentLenIsOdd { + c := <-encoder + if c < 0 { + return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric) + } + res.AddBits(c, 6) + } + + addPaddingAndTerminator(res, vi) + + return res, vi, nil +} diff --git a/vendor/github.com/boombuler/barcode/qr/alphanumeric_test.go b/vendor/github.com/boombuler/barcode/qr/alphanumeric_test.go new file mode 100644 index 0000000..d8b1d38 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/alphanumeric_test.go @@ -0,0 +1,44 @@ +package qr + +import ( + "bytes" + "testing" +) + +func makeString(length int, content string) string { + res := "" + + for i := 0; i < length; i++ { + res += content + } + + return res +} + +func Test_AlphaNumericEncoding(t *testing.T) { + encode := AlphaNumeric.getEncoder() + + x, vi, err := encode("HELLO WORLD", M) + + if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17}) != 0 { + t.Errorf("\"HELLO WORLD\" failed to encode: %s", err) + } + + x, vi, err = encode(makeString(4296, "A"), L) + if x == nil || vi == nil || err != nil { + t.Fail() + } + x, vi, err = encode(makeString(4297, "A"), L) + if x != nil || vi != nil || err == nil { + t.Fail() + } + x, vi, err = encode("ABc", L) + if x != nil || vi != nil || err == nil { + t.Fail() + } + x, vi, err = encode("hello world", M) + + if x != nil || vi != nil || err == nil { + t.Error("\"hello world\" should not be encodable in alphanumeric mode") + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/automatic.go b/vendor/github.com/boombuler/barcode/qr/automatic.go new file mode 100644 index 0000000..e7c5601 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/automatic.go @@ -0,0 +1,23 @@ +package qr + +import ( + "fmt" + + "github.com/boombuler/barcode/utils" +) + +func encodeAuto(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { + bits, vi, _ := Numeric.getEncoder()(content, ecl) + if bits != nil && vi != nil { + return bits, vi, nil + } + bits, vi, _ = AlphaNumeric.getEncoder()(content, ecl) + if bits != nil && vi != nil { + return bits, vi, nil + } + bits, vi, _ = Unicode.getEncoder()(content, ecl) + if bits != nil && vi != nil { + return bits, vi, nil + } + return nil, nil, fmt.Errorf("No encoding found to encode \"%s\"", content) +} diff --git a/vendor/github.com/boombuler/barcode/qr/automatic_test.go b/vendor/github.com/boombuler/barcode/qr/automatic_test.go new file mode 100644 index 0000000..07587d4 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/automatic_test.go @@ -0,0 +1,30 @@ +package qr + +import ( + "bytes" + "testing" +) + +func Test_AutomaticEncoding(t *testing.T) { + tests := map[string]encodeFn{ + "0123456789": Numeric.getEncoder(), + "ALPHA NUMERIC": AlphaNumeric.getEncoder(), + "unicode encoing": Unicode.getEncoder(), + "very long unicode encoding" + makeString(3000, "A"): nil, + } + + for str, enc := range tests { + testValue, _, _ := Auto.getEncoder()(str, M) + if enc != nil { + correctValue, _, _ := enc(str, M) + if testValue == nil || bytes.Compare(correctValue.GetBytes(), testValue.GetBytes()) != 0 { + t.Errorf("wrong encoding used for '%s'", str) + } + } else { + if testValue != nil { + t.Errorf("wrong encoding used for '%s'", str) + } + } + + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/blocks.go b/vendor/github.com/boombuler/barcode/qr/blocks.go new file mode 100644 index 0000000..d317378 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/blocks.go @@ -0,0 +1,59 @@ +package qr + +type block struct { + data []byte + ecc []byte +} +type blockList []*block + +func splitToBlocks(data <-chan byte, vi *versionInfo) blockList { + result := make(blockList, vi.NumberOfBlocksInGroup1+vi.NumberOfBlocksInGroup2) + + for b := 0; b < int(vi.NumberOfBlocksInGroup1); b++ { + blk := new(block) + blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup1) + for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup1); cw++ { + blk.data[cw] = <-data + } + blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock) + result[b] = blk + } + + for b := 0; b < int(vi.NumberOfBlocksInGroup2); b++ { + blk := new(block) + blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup2) + for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup2); cw++ { + blk.data[cw] = <-data + } + blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock) + result[int(vi.NumberOfBlocksInGroup1)+b] = blk + } + + return result +} + +func (bl blockList) interleave(vi *versionInfo) []byte { + var maxCodewordCount int + if vi.DataCodeWordsPerBlockInGroup1 > vi.DataCodeWordsPerBlockInGroup2 { + maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup1) + } else { + maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup2) + } + resultLen := (vi.DataCodeWordsPerBlockInGroup1+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup1 + + (vi.DataCodeWordsPerBlockInGroup2+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup2 + + result := make([]byte, 0, resultLen) + for i := 0; i < maxCodewordCount; i++ { + for b := 0; b < len(bl); b++ { + if len(bl[b].data) > i { + result = append(result, bl[b].data[i]) + } + } + } + for i := 0; i < int(vi.ErrorCorrectionCodewordsPerBlock); i++ { + for b := 0; b < len(bl); b++ { + result = append(result, bl[b].ecc[i]) + } + } + return result +} diff --git a/vendor/github.com/boombuler/barcode/qr/blocks_test.go b/vendor/github.com/boombuler/barcode/qr/blocks_test.go new file mode 100644 index 0000000..656fba0 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/blocks_test.go @@ -0,0 +1,36 @@ +package qr + +import ( + "bytes" + "testing" +) + +func Test_Blocks(t *testing.T) { + byteIt := make(chan byte) + go func() { + for _, b := range []byte{67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38, 246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6, 182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7, 70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236} { + byteIt <- b + } + close(byteIt) + }() + vi := &versionInfo{5, Q, 18, 2, 15, 2, 16} + + data := splitToBlocks(byteIt, vi).interleave(vi) + if bytes.Compare(data, []byte{67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118, 134, 7, 119, 86, 87, 118, 50, 194, 38, 134, 7, 6, 85, 242, 118, 151, 194, 7, 134, 50, 119, 38, 87, 16, 50, 86, 38, 236, 6, 22, 82, 17, 18, 198, 6, 236, 6, 199, 134, 17, 103, 146, 151, 236, 38, 6, 50, 17, 7, 236, 213, 87, 148, 235, 199, 204, 116, 159, 11, 96, 177, 5, 45, 60, 212, 173, 115, 202, 76, 24, 247, 182, 133, 147, 241, 124, 75, 59, 223, 157, 242, 33, 229, 200, 238, 106, 248, 134, 76, 40, 154, 27, 195, 255, 117, 129, 230, 172, 154, 209, 189, 82, 111, 17, 10, 2, 86, 163, 108, 131, 161, 163, 240, 32, 111, 120, 192, 178, 39, 133, 141, 236}) != 0 { + t.Fail() + } + + byteIt2 := make(chan byte) + go func() { + for _, b := range []byte{67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38, 246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6, 182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7, 70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236} { + byteIt2 <- b + } + close(byteIt2) + }() + vi = &versionInfo{5, Q, 18, 2, 16, 2, 15} + + data = splitToBlocks(byteIt2, vi).interleave(vi) + if bytes.Compare(data, []byte{67, 246, 247, 247, 85, 66, 119, 118, 70, 7, 50, 86, 134, 118, 7, 194, 87, 134, 118, 6, 38, 242, 134, 151, 85, 7, 87, 50, 194, 38, 38, 16, 119, 86, 82, 236, 50, 22, 6, 17, 6, 198, 134, 236, 18, 199, 151, 17, 6, 146, 50, 236, 103, 6, 7, 17, 38, 182, 70, 236, 246, 230, 71, 101, 27, 62, 13, 91, 166, 86, 138, 16, 78, 229, 102, 11, 199, 107, 2, 182, 132, 103, 89, 66, 136, 69, 78, 255, 116, 129, 126, 163, 219, 234, 158, 216, 42, 234, 97, 62, 186, 59, 123, 148, 220, 191, 254, 145, 82, 95, 129, 79, 236, 254, 30, 174, 228, 50, 181, 110, 150, 205, 34, 235, 242, 0, 115, 147, 58, 243, 28, 140, 221, 219}) != 0 { + t.Fail() + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/encoder.go b/vendor/github.com/boombuler/barcode/qr/encoder.go new file mode 100644 index 0000000..2c6ab21 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/encoder.go @@ -0,0 +1,416 @@ +// Package qr can be used to create QR barcodes. +package qr + +import ( + "image" + + "github.com/boombuler/barcode" + "github.com/boombuler/barcode/utils" +) + +type encodeFn func(content string, eccLevel ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) + +// Encoding mode for QR Codes. +type Encoding byte + +const ( + // Auto will choose ths best matching encoding + Auto Encoding = iota + // Numeric encoding only encodes numbers [0-9] + Numeric + // AlphaNumeric encoding only encodes uppercase letters, numbers and [Space], $, %, *, +, -, ., /, : + AlphaNumeric + // Unicode encoding encodes the string as utf-8 + Unicode + // only for testing purpose + unknownEncoding +) + +func (e Encoding) getEncoder() encodeFn { + switch e { + case Auto: + return encodeAuto + case Numeric: + return encodeNumeric + case AlphaNumeric: + return encodeAlphaNumeric + case Unicode: + return encodeUnicode + } + return nil +} + +func (e Encoding) String() string { + switch e { + case Auto: + return "Auto" + case Numeric: + return "Numeric" + case AlphaNumeric: + return "AlphaNumeric" + case Unicode: + return "Unicode" + } + return "" +} + +// Encode returns a QR barcode with the given content, error correction level and uses the given encoding +func Encode(content string, level ErrorCorrectionLevel, mode Encoding) (barcode.Barcode, error) { + bits, vi, err := mode.getEncoder()(content, level) + if err != nil { + return nil, err + } + + blocks := splitToBlocks(bits.IterateBytes(), vi) + data := blocks.interleave(vi) + result := render(data, vi) + result.content = content + return result, nil +} + +func render(data []byte, vi *versionInfo) *qrcode { + dim := vi.modulWidth() + results := make([]*qrcode, 8) + for i := 0; i < 8; i++ { + results[i] = newBarcode(dim) + } + + occupied := newBarcode(dim) + + setAll := func(x int, y int, val bool) { + occupied.Set(x, y, true) + for i := 0; i < 8; i++ { + results[i].Set(x, y, val) + } + } + + drawFinderPatterns(vi, setAll) + drawAlignmentPatterns(occupied, vi, setAll) + + //Timing Pattern: + var i int + for i = 0; i < dim; i++ { + if !occupied.Get(i, 6) { + setAll(i, 6, i%2 == 0) + } + if !occupied.Get(6, i) { + setAll(6, i, i%2 == 0) + } + } + // Dark Module + setAll(8, dim-8, true) + + drawVersionInfo(vi, setAll) + drawFormatInfo(vi, -1, occupied.Set) + for i := 0; i < 8; i++ { + drawFormatInfo(vi, i, results[i].Set) + } + + // Write the data + var curBitNo int + + for pos := range iterateModules(occupied) { + var curBit bool + if curBitNo < len(data)*8 { + curBit = ((data[curBitNo/8] >> uint(7-(curBitNo%8))) & 1) == 1 + } else { + curBit = false + } + + for i := 0; i < 8; i++ { + setMasked(pos.X, pos.Y, curBit, i, results[i].Set) + } + curBitNo++ + } + + lowestPenalty := ^uint(0) + lowestPenaltyIdx := -1 + for i := 0; i < 8; i++ { + p := results[i].calcPenalty() + if p < lowestPenalty { + lowestPenalty = p + lowestPenaltyIdx = i + } + } + return results[lowestPenaltyIdx] +} + +func setMasked(x, y int, val bool, mask int, set func(int, int, bool)) { + switch mask { + case 0: + val = val != (((y + x) % 2) == 0) + break + case 1: + val = val != ((y % 2) == 0) + break + case 2: + val = val != ((x % 3) == 0) + break + case 3: + val = val != (((y + x) % 3) == 0) + break + case 4: + val = val != (((y/2 + x/3) % 2) == 0) + break + case 5: + val = val != (((y*x)%2)+((y*x)%3) == 0) + break + case 6: + val = val != ((((y*x)%2)+((y*x)%3))%2 == 0) + break + case 7: + val = val != ((((y+x)%2)+((y*x)%3))%2 == 0) + } + set(x, y, val) +} + +func iterateModules(occupied *qrcode) <-chan image.Point { + result := make(chan image.Point) + allPoints := make(chan image.Point) + go func() { + curX := occupied.dimension - 1 + curY := occupied.dimension - 1 + isUpward := true + + for true { + if isUpward { + allPoints <- image.Pt(curX, curY) + allPoints <- image.Pt(curX-1, curY) + curY-- + if curY < 0 { + curY = 0 + curX -= 2 + if curX == 6 { + curX-- + } + if curX < 0 { + break + } + isUpward = false + } + } else { + allPoints <- image.Pt(curX, curY) + allPoints <- image.Pt(curX-1, curY) + curY++ + if curY >= occupied.dimension { + curY = occupied.dimension - 1 + curX -= 2 + if curX == 6 { + curX-- + } + isUpward = true + if curX < 0 { + break + } + } + } + } + + close(allPoints) + }() + go func() { + for pt := range allPoints { + if !occupied.Get(pt.X, pt.Y) { + result <- pt + } + } + close(result) + }() + return result +} + +func drawFinderPatterns(vi *versionInfo, set func(int, int, bool)) { + dim := vi.modulWidth() + drawPattern := func(xoff int, yoff int) { + for x := -1; x < 8; x++ { + for y := -1; y < 8; y++ { + val := (x == 0 || x == 6 || y == 0 || y == 6 || (x > 1 && x < 5 && y > 1 && y < 5)) && (x <= 6 && y <= 6 && x >= 0 && y >= 0) + + if x+xoff >= 0 && x+xoff < dim && y+yoff >= 0 && y+yoff < dim { + set(x+xoff, y+yoff, val) + } + } + } + } + drawPattern(0, 0) + drawPattern(0, dim-7) + drawPattern(dim-7, 0) +} + +func drawAlignmentPatterns(occupied *qrcode, vi *versionInfo, set func(int, int, bool)) { + drawPattern := func(xoff int, yoff int) { + for x := -2; x <= 2; x++ { + for y := -2; y <= 2; y++ { + val := x == -2 || x == 2 || y == -2 || y == 2 || (x == 0 && y == 0) + set(x+xoff, y+yoff, val) + } + } + } + positions := vi.alignmentPatternPlacements() + + for _, x := range positions { + for _, y := range positions { + if occupied.Get(x, y) { + continue + } + drawPattern(x, y) + } + } +} + +var formatInfos = map[ErrorCorrectionLevel]map[int][]bool{ + L: { + 0: []bool{true, true, true, false, true, true, true, true, true, false, false, false, true, false, false}, + 1: []bool{true, true, true, false, false, true, false, true, true, true, true, false, false, true, true}, + 2: []bool{true, true, true, true, true, false, true, true, false, true, false, true, false, true, false}, + 3: []bool{true, true, true, true, false, false, false, true, false, false, true, true, true, false, true}, + 4: []bool{true, true, false, false, true, true, false, false, false, true, false, true, true, true, true}, + 5: []bool{true, true, false, false, false, true, true, false, false, false, true, true, false, false, false}, + 6: []bool{true, true, false, true, true, false, false, false, true, false, false, false, false, false, true}, + 7: []bool{true, true, false, true, false, false, true, false, true, true, true, false, true, true, false}, + }, + M: { + 0: []bool{true, false, true, false, true, false, false, false, false, false, true, false, false, true, false}, + 1: []bool{true, false, true, false, false, false, true, false, false, true, false, false, true, false, true}, + 2: []bool{true, false, true, true, true, true, false, false, true, true, true, true, true, false, false}, + 3: []bool{true, false, true, true, false, true, true, false, true, false, false, true, false, true, true}, + 4: []bool{true, false, false, false, true, false, true, true, true, true, true, true, false, false, true}, + 5: []bool{true, false, false, false, false, false, false, true, true, false, false, true, true, true, false}, + 6: []bool{true, false, false, true, true, true, true, true, false, false, true, false, true, true, true}, + 7: []bool{true, false, false, true, false, true, false, true, false, true, false, false, false, false, false}, + }, + Q: { + 0: []bool{false, true, true, false, true, false, true, false, true, false, true, true, true, true, true}, + 1: []bool{false, true, true, false, false, false, false, false, true, true, false, true, false, false, false}, + 2: []bool{false, true, true, true, true, true, true, false, false, true, true, false, false, false, true}, + 3: []bool{false, true, true, true, false, true, false, false, false, false, false, false, true, true, false}, + 4: []bool{false, true, false, false, true, false, false, true, false, true, true, false, true, false, false}, + 5: []bool{false, true, false, false, false, false, true, true, false, false, false, false, false, true, true}, + 6: []bool{false, true, false, true, true, true, false, true, true, false, true, true, false, true, false}, + 7: []bool{false, true, false, true, false, true, true, true, true, true, false, true, true, false, true}, + }, + H: { + 0: []bool{false, false, true, false, true, true, false, true, false, false, false, true, false, false, true}, + 1: []bool{false, false, true, false, false, true, true, true, false, true, true, true, true, true, false}, + 2: []bool{false, false, true, true, true, false, false, true, true, true, false, false, true, true, true}, + 3: []bool{false, false, true, true, false, false, true, true, true, false, true, false, false, false, false}, + 4: []bool{false, false, false, false, true, true, true, false, true, true, false, false, false, true, false}, + 5: []bool{false, false, false, false, false, true, false, false, true, false, true, false, true, false, true}, + 6: []bool{false, false, false, true, true, false, true, false, false, false, false, true, true, false, false}, + 7: []bool{false, false, false, true, false, false, false, false, false, true, true, true, false, true, true}, + }, +} + +func drawFormatInfo(vi *versionInfo, usedMask int, set func(int, int, bool)) { + var formatInfo []bool + + if usedMask == -1 { + formatInfo = []bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true} // Set all to true cause -1 --> occupied mask. + } else { + formatInfo = formatInfos[vi.Level][usedMask] + } + + if len(formatInfo) == 15 { + dim := vi.modulWidth() + set(0, 8, formatInfo[0]) + set(1, 8, formatInfo[1]) + set(2, 8, formatInfo[2]) + set(3, 8, formatInfo[3]) + set(4, 8, formatInfo[4]) + set(5, 8, formatInfo[5]) + set(7, 8, formatInfo[6]) + set(8, 8, formatInfo[7]) + set(8, 7, formatInfo[8]) + set(8, 5, formatInfo[9]) + set(8, 4, formatInfo[10]) + set(8, 3, formatInfo[11]) + set(8, 2, formatInfo[12]) + set(8, 1, formatInfo[13]) + set(8, 0, formatInfo[14]) + + set(8, dim-1, formatInfo[0]) + set(8, dim-2, formatInfo[1]) + set(8, dim-3, formatInfo[2]) + set(8, dim-4, formatInfo[3]) + set(8, dim-5, formatInfo[4]) + set(8, dim-6, formatInfo[5]) + set(8, dim-7, formatInfo[6]) + set(dim-8, 8, formatInfo[7]) + set(dim-7, 8, formatInfo[8]) + set(dim-6, 8, formatInfo[9]) + set(dim-5, 8, formatInfo[10]) + set(dim-4, 8, formatInfo[11]) + set(dim-3, 8, formatInfo[12]) + set(dim-2, 8, formatInfo[13]) + set(dim-1, 8, formatInfo[14]) + } +} + +var versionInfoBitsByVersion = map[byte][]bool{ + 7: []bool{false, false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false}, + 8: []bool{false, false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false}, + 9: []bool{false, false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true}, + 10: []bool{false, false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true}, + 11: []bool{false, false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false}, + 12: []bool{false, false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false}, + 13: []bool{false, false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true}, + 14: []bool{false, false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true}, + 15: []bool{false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false}, + 16: []bool{false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false}, + 17: []bool{false, true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true}, + 18: []bool{false, true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true}, + 19: []bool{false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false}, + 20: []bool{false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true, false}, + 21: []bool{false, true, false, true, false, true, false, true, true, false, true, false, false, false, false, false, true, true}, + 22: []bool{false, true, false, true, true, false, true, false, false, false, true, true, false, false, true, false, false, true}, + 23: []bool{false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false, false}, + 24: []bool{false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false, false}, + 25: []bool{false, true, true, false, false, true, false, false, false, true, true, true, true, false, false, false, false, true}, + 26: []bool{false, true, true, false, true, false, true, true, true, true, true, false, true, false, true, false, true, true}, + 27: []bool{false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true, false}, + 28: []bool{false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true, false}, + 29: []bool{false, true, true, true, false, true, false, false, true, true, false, false, true, true, true, true, true, true}, + 30: []bool{false, true, true, true, true, false, true, true, false, true, false, true, true, true, false, true, false, true}, + 31: []bool{false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false, false}, + 32: []bool{true, false, false, false, false, false, true, false, false, true, true, true, false, true, false, true, false, true}, + 33: []bool{true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false, false}, + 34: []bool{true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true, false}, + 35: []bool{true, false, false, false, true, true, false, true, true, true, true, false, false, true, true, true, true, true}, + 36: []bool{true, false, false, true, false, false, true, false, true, true, false, false, false, false, true, false, true, true}, + 37: []bool{true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true, false}, + 38: []bool{true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false, false}, + 39: []bool{true, false, false, true, true, true, false, true, false, true, false, true, false, false, false, false, false, true}, + 40: []bool{true, false, true, false, false, false, true, true, false, false, false, true, true, false, true, false, false, true}, +} + +func drawVersionInfo(vi *versionInfo, set func(int, int, bool)) { + versionInfoBits, ok := versionInfoBitsByVersion[vi.Version] + + if ok && len(versionInfoBits) > 0 { + for i := 0; i < len(versionInfoBits); i++ { + x := (vi.modulWidth() - 11) + i%3 + y := i / 3 + set(x, y, versionInfoBits[len(versionInfoBits)-i-1]) + set(y, x, versionInfoBits[len(versionInfoBits)-i-1]) + } + } + +} + +func addPaddingAndTerminator(bl *utils.BitList, vi *versionInfo) { + for i := 0; i < 4 && bl.Len() < vi.totalDataBytes()*8; i++ { + bl.AddBit(false) + } + + for bl.Len()%8 != 0 { + bl.AddBit(false) + } + + for i := 0; bl.Len() < vi.totalDataBytes()*8; i++ { + if i%2 == 0 { + bl.AddByte(236) + } else { + bl.AddByte(17) + } + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/encoder_test.go b/vendor/github.com/boombuler/barcode/qr/encoder_test.go new file mode 100644 index 0000000..60cd6d3 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/encoder_test.go @@ -0,0 +1,134 @@ +package qr + +import ( + "fmt" + "image/png" + "os" + "testing" + + "github.com/boombuler/barcode" +) + +type test struct { + Text string + Mode Encoding + ECL ErrorCorrectionLevel + Result string +} + +var tests = []test{ + test{ + Text: "hello world", + Mode: Unicode, + ECL: H, + Result: ` ++++++++.+.+.+...+.+++++++ ++.....+.++...+++..+.....+ ++.+++.+.+.+.++.++.+.+++.+ ++.+++.+....++.++..+.+++.+ ++.+++.+..+...++.+.+.+++.+ ++.....+.+..+..+++.+.....+ ++++++++.+.+.+.+.+.+++++++ +........++..+..+......... +..+++.+.+++.+.++++++..+++ ++++..+..+...++.+...+..+.. ++...+.++++....++.+..++.++ +++.+.+.++...+...+.+....++ +..+..+++.+.+++++.++++++++ ++.+++...+..++..++..+..+.. ++.....+..+.+.....+++++.++ ++.+++.....+...+.+.+++...+ ++.+..+++...++.+.+++++++.. +........+....++.+...+.+.. ++++++++......++++.+.+.+++ ++.....+....+...++...++.+. ++.+++.+.+.+...+++++++++.. ++.+++.+.++...++...+.++..+ ++.+++.+.++.+++++..++.+..+ ++.....+..+++..++.+.++...+ ++++++++....+..+.+..+..+++`, + }, +} + +func Test_GetUnknownEncoder(t *testing.T) { + if unknownEncoding.getEncoder() != nil { + t.Fail() + } +} + +func Test_EncodingStringer(t *testing.T) { + tests := map[Encoding]string{ + Auto: "Auto", + Numeric: "Numeric", + AlphaNumeric: "AlphaNumeric", + Unicode: "Unicode", + unknownEncoding: "", + } + + for enc, str := range tests { + if enc.String() != str { + t.Fail() + } + } +} + +func Test_InvalidEncoding(t *testing.T) { + _, err := Encode("hello world", H, Numeric) + if err == nil { + t.Fail() + } +} + +func imgStrToBools(str string) []bool { + res := make([]bool, 0, len(str)) + for _, r := range str { + if r == '+' { + res = append(res, true) + } else if r == '.' { + res = append(res, false) + } + } + return res +} + +func Test_Encode(t *testing.T) { + for _, tst := range tests { + res, err := Encode(tst.Text, tst.ECL, tst.Mode) + if err != nil { + t.Error(err) + } + qrCode, ok := res.(*qrcode) + if !ok { + t.Fail() + } + testRes := imgStrToBools(tst.Result) + if (qrCode.dimension * qrCode.dimension) != len(testRes) { + t.Fail() + } + t.Logf("dim %d", qrCode.dimension) + for i := 0; i < len(testRes); i++ { + x := i % qrCode.dimension + y := i / qrCode.dimension + if qrCode.Get(x, y) != testRes[i] { + t.Errorf("Failed at index %d", i) + } + } + } +} + +func ExampleEncode() { + f, _ := os.Create("qrcode.png") + defer f.Close() + + qrcode, err := Encode("hello world", L, Auto) + if err != nil { + fmt.Println(err) + } else { + qrcode, err = barcode.Scale(qrcode, 100, 100) + if err != nil { + fmt.Println(err) + } else { + png.Encode(f, qrcode) + } + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/errorcorrection.go b/vendor/github.com/boombuler/barcode/qr/errorcorrection.go new file mode 100644 index 0000000..08ebf0c --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/errorcorrection.go @@ -0,0 +1,29 @@ +package qr + +import ( + "github.com/boombuler/barcode/utils" +) + +type errorCorrection struct { + rs *utils.ReedSolomonEncoder +} + +var ec = newErrorCorrection() + +func newErrorCorrection() *errorCorrection { + fld := utils.NewGaloisField(285, 256, 0) + return &errorCorrection{utils.NewReedSolomonEncoder(fld)} +} + +func (ec *errorCorrection) calcECC(data []byte, eccCount byte) []byte { + dataInts := make([]int, len(data)) + for i := 0; i < len(data); i++ { + dataInts[i] = int(data[i]) + } + res := ec.rs.Encode(dataInts, int(eccCount)) + result := make([]byte, len(res)) + for i := 0; i < len(res); i++ { + result[i] = byte(res[i]) + } + return result +} diff --git a/vendor/github.com/boombuler/barcode/qr/errorcorrection_test.go b/vendor/github.com/boombuler/barcode/qr/errorcorrection_test.go new file mode 100644 index 0000000..e88d92c --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/errorcorrection_test.go @@ -0,0 +1,60 @@ +package qr + +import ( + "bytes" + "testing" +) + +func Test_ErrorCorrection(t *testing.T) { + doTest := func(b []byte, ecc []byte) { + cnt := byte(len(ecc)) + res := ec.calcECC(b, cnt) + if bytes.Compare(res, ecc) != 0 { + t.Errorf("ECC error!\nGot: %v\nExpected:%v", res, ecc) + } + } + // Issue #5 + doTest([]byte{66, 196, 148, 21, 99, 19, 151, 151, 53, 149, 54, 195, 4, 133, 87, 84, 115, 85, 22, 148, 52, 71, 102, 68, 134, 182, 247, 119, 22, 68, 117, 134, 35, 4, 134, 38, 21, 84, 21, 117, 87, 164, 135, 115, 211, 208, 236, 17, 236, 17, 236, 17, 236, 17, 236}, []byte{187, 187, 171, 253, 164, 129, 104, 133, 3, 75, 87, 98, 241, 146, 138}) + + // Other tests + doTest([]byte{17, 168, 162, 241, 255, 205, 240, 179, 88, 101, 71, 130, 2, 54, 147, 111, 232, 58, 202, 171, 85, 22, 229, 187}, []byte{30, 142, 171, 131, 189}) + doTest([]byte{36, 153, 55, 100, 228, 252, 0, 35, 85, 7, 237, 117, 182, 73, 83, 244, 8, 64, 55, 252, 200, 250, 72, 92, 97, 125, 96}, []byte{129, 124, 218, 148, 49, 108, 68, 255, 58, 212, 56, 60, 142, 45, 216, 124, 253, 214, 206, 208, 145, 169, 43}) + doTest([]byte{250, 195, 230, 128, 31, 168, 86, 123, 244, 129, 74, 130, 222, 225, 140, 129, 114, 132, 128, 88, 96, 13, 165, 132, 116, 22, 42, 81, 219, 3, 102, 156, 69, 70, 90, 68, 7, 245, 150, 160, 252, 121, 20}, []byte{124, 23, 233, 71, 200, 211, 54, 141, 10, 23, 206, 147, 116, 35, 45, 218, 158, 193, 80, 194, 129, 147, 8, 78, 229, 112, 89, 161, 167, 203, 11, 245, 186, 187, 17, 7, 175}) + doTest([]byte{121, 234, 24, 188, 218, 238, 248, 223, 98, 124, 237, 30, 98, 12, 9, 126, 5, 160, 240, 27, 174, 60, 152, 134, 71, 122, 125, 238, 223, 91, 231, 248, 230, 152, 250, 44, 17, 149, 0, 20, 109, 188, 227, 202}, []byte{209, 71, 225, 216, 240, 127, 111, 98, 194, 133, 114, 63, 35, 167, 184, 4, 209, 211, 40, 14, 74, 37, 21, 76, 95, 206, 90, 152, 110, 64, 6, 92, 80, 255, 127, 35, 111, 25, 1, 73}) + doTest([]byte{165, 233, 141, 34, 247, 216, 35, 163, 61, 61, 81, 146, 116, 96, 113, 10, 0, 6, 148, 244, 55, 201, 17, 220, 109, 111}, []byte{93, 173, 231, 160}) + doTest([]byte{173, 242, 89, 205, 24, 33, 213, 147, 96, 189, 100, 15, 213, 67, 91, 189, 218, 127, 32, 160, 162, 99, 187, 221, 53, 121, 238, 219, 215, 176, 181, 135, 56, 71, 246, 74, 228}, []byte{194, 130, 43, 168, 223, 144, 223, 49, 5, 162, 62, 218, 50, 205, 249, 84, 188, 25, 109, 110, 49, 224, 194, 244, 83, 221, 236, 71, 197, 159, 182}) + doTest([]byte{82, 138, 221, 169, 67, 161, 132, 31, 243, 110, 83, 1, 238, 79, 255, 57, 74, 54, 123, 151, 159, 50, 250, 188, 176, 8, 221, 215, 141, 77, 16}, []byte{197, 122, 225, 65, 40, 69, 153, 100, 73, 245, 150, 213, 104, 127, 3}) + doTest([]byte{5, 206, 21, 196, 185, 120, 60, 177, 90, 251, 109, 131, 174, 199, 55, 56, 14, 171, 19, 104, 236, 218, 31, 144, 33, 249, 58, 195, 173, 145, 166, 93, 122, 171, 232, 128, 233, 116, 144, 189, 62, 230, 68, 55, 140, 56, 1, 65, 165, 158, 127}, []byte{73, 141, 230, 252, 225, 173, 251, 194, 150, 98, 141, 241, 246, 11, 16, 8, 42}) + doTest([]byte{112, 106, 43, 174, 133, 163, 192, 61, 121, 3, 200, 84, 15, 9, 3, 222, 183, 78, 153, 26, 85, 41, 5, 149, 232, 3, 233, 247, 249, 29, 15, 18, 4, 96, 9, 64, 188, 210}, []byte{16, 254, 143, 110, 63, 167, 213, 242, 95, 78, 215, 145, 231, 59, 158, 36, 149, 247, 123, 114, 247, 202, 15, 56, 229, 163, 186, 73, 82, 230, 111, 108, 111, 182, 193, 46, 116}) + doTest([]byte{208, 128, 197, 227, 124, 226, 125, 46, 253, 98, 238, 80, 229, 134, 167, 70, 101, 150, 198, 130, 185, 200, 68, 91}, []byte{229, 167, 187, 39, 92, 90, 210, 25, 206, 237, 90, 194, 206, 39, 2, 11, 78, 48, 247}) + doTest([]byte{79, 175, 255, 194, 34, 229, 234, 200, 74, 213, 100, 33, 24, 5, 133, 186, 249, 151, 46, 190, 44, 126, 184, 195, 219, 37, 11, 225, 23, 8, 59, 106, 239, 198, 146, 205, 47, 59, 63, 9, 102, 29, 60, 209, 226, 67, 126, 193, 252, 255, 206, 172, 44, 53, 137, 209, 246}, []byte{237, 8, 12, 44, 90, 243, 24, 100, 123, 216, 185, 91, 182, 60, 9, 145, 126, 254, 139, 24, 211, 150, 219, 28, 138, 197, 13, 109, 227, 31, 60, 128, 237, 181, 183, 2, 138, 232, 112, 5}) + doTest([]byte{253, 217, 8, 176, 66, 153, 249, 49, 82, 114, 184, 139, 190, 87}, []byte{28, 55, 193, 193, 179, 246, 222, 5, 95, 96, 13, 242}) + doTest([]byte{15, 65, 231, 224, 151, 167, 74, 228, 23}, []byte{200, 90, 82}) + doTest([]byte{61, 186, 61, 193, 215, 243, 84, 66, 48, 93, 108, 249, 55, 232}, []byte{0, 180, 53, 152, 134, 252, 165, 168}) + doTest([]byte{78, 68, 116, 15, 85}, []byte{36}) + doTest([]byte{122, 143}, []byte{245}) + doTest([]byte{78, 85, 143, 35}, []byte{226, 85}) + doTest([]byte{11, 188, 118, 21, 177, 224, 151, 105, 21, 245, 251, 162, 72, 175, 248, 134, 123, 251, 160, 163, 42, 57, 53, 222, 195, 49, 199, 151, 5, 236, 160, 57, 212, 241, 44, 43}, []byte{186, 106}) + doTest([]byte{157, 99, 220, 166, 63, 18, 225, 215, 71, 95, 99, 200, 218, 147, 131, 245, 222, 209, 135, 152, 82, 128, 24, 0, 100, 40, 84, 193, 205, 86, 130, 204, 235, 100, 94, 61}, []byte{41, 171, 66, 233}) + doTest([]byte{249, 34, 253, 235, 233, 104, 52, 60, 17, 13, 182, 223, 19, 91, 164, 2, 196, 29, 74, 219, 65, 23, 190, 31, 10, 241, 221, 150, 221, 118, 53, 69, 45, 90, 215, 100, 155, 102, 150, 176, 203, 39, 22, 70, 10, 238}, []byte{161, 49, 179, 149, 178, 146, 208, 144, 19, 158, 180, 152, 243, 138, 143, 243, 82, 112, 229, 10, 113, 255, 139, 246}) + doTest([]byte{39, 232, 159, 64, 242, 235, 66, 226, 100, 221, 225, 247, 139, 157, 95, 155}, []byte{41, 9, 244}) + doTest([]byte{177, 185, 131, 64, 103, 93, 134, 153, 15, 26, 0, 119, 21, 27, 174, 181, 111, 245, 214, 244, 83, 66, 24, 244, 255, 189, 133, 158, 37, 46, 199, 123, 110, 153, 61, 137, 163, 231, 129, 65, 186, 89, 219, 39, 226, 236, 199, 197, 73, 213}, []byte{37, 59, 125, 211, 249, 177, 107, 79, 107, 47, 242, 168, 49, 38, 168, 198, 199, 91, 212, 22, 107, 244}) + doTest([]byte{196, 226, 29, 110, 161, 143, 64, 169, 216, 231, 115}, []byte{253, 93, 218, 129, 37}) + doTest([]byte{133, 8, 124, 221, 36, 17, 135, 115, 149, 58, 250, 103, 241, 18, 19, 246, 191, 85, 80, 255, 93, 182, 140, 123, 206, 232, 20, 166, 216, 105, 210, 229, 249, 212, 93, 227, 75, 231, 36, 195, 166, 246, 47, 168, 35, 7, 176, 124, 44, 179, 24, 145}, []byte{78, 57, 134, 181, 215, 149, 111, 51, 172, 58, 114, 3, 140, 186, 126, 40, 190}) + doTest([]byte{245, 206, 124, 0, 15, 59, 253, 225, 155}, []byte{65, 14, 188, 213, 18, 113, 161, 16}) + doTest([]byte{20, 109, 28, 180, 48, 170, 216, 48, 140, 89, 103}, []byte{193, 147, 50, 209, 160}) + doTest([]byte{87, 198, 56, 151, 121, 37, 81, 64, 193, 24, 222, 142, 102, 74, 216, 233, 198, 197, 90, 4, 65, 14, 154, 147, 200, 252, 8, 64, 97, 150, 136, 141}, []byte{231, 190, 32, 90, 100, 40, 41, 103, 200, 200, 243, 75, 177, 7, 93, 28, 83, 47, 188, 236, 20, 95, 69, 104, 155, 102, 110, 197}) + doTest([]byte{168, 72, 2, 101, 103, 118, 218, 38, 82, 85, 62, 37, 201, 96, 255, 71, 198}, []byte{129, 33, 28, 228, 195, 120, 101, 46, 119, 126}) + doTest([]byte{130, 162, 73, 44, 165, 207, 124, 28, 17, 223, 43, 143, 81, 70, 205, 161, 143, 230, 97, 94, 228, 41, 26, 187, 69, 85, 162, 51, 168, 64, 26, 207, 245, 128}, []byte{6, 171}) + doTest([]byte{95, 28, 93, 149, 234, 89, 201, 71, 39, 197, 236, 223, 251, 190, 112, 96, 101, 53, 40, 88, 136, 141, 230, 80, 45, 73, 116, 208, 197, 91, 154, 209, 128, 214, 66, 114, 137, 204, 115, 139, 96, 211, 148, 127, 104, 194}, []byte{10, 102, 57, 95, 61, 212, 130, 71, 74, 58, 82, 115, 238, 213, 251, 184, 203, 250, 55, 186, 37, 16, 71, 247, 146, 194, 74, 208, 221, 6, 81, 172, 204, 73, 102, 40, 247, 174, 213, 37, 225, 246, 8, 58}) + doTest([]byte{207, 185, 106, 191, 87, 109, 110, 210, 54, 12, 103, 161, 228}, []byte{214, 138, 159, 195, 154, 236, 33, 243, 53, 79, 227}) + doTest([]byte{203, 43, 26, 94, 37, 123, 254, 215, 153, 193, 157, 248, 180, 249, 103, 232, 107, 17, 138, 0, 11, 240, 218, 122, 19, 103, 112, 60, 125, 100, 209, 166, 103, 81, 200, 84, 77, 100, 18, 110, 209, 225, 209, 254, 185, 116, 186, 216, 206, 36, 252, 144, 90, 247, 117, 219, 81, 160}, []byte{185, 176, 106, 253, 76, 153, 185, 211, 187, 153, 210, 31, 99, 4, 46, 145, 221, 99, 236, 19, 126, 138, 66, 26, 40, 217, 170, 217, 147}) + doTest([]byte{11, 193, 90, 52, 239, 247, 144, 99, 48, 19, 154, 6, 255, 28, 47, 41, 30, 220}, []byte{235, 165, 125, 82, 28, 116, 21, 133, 243, 222, 241, 20, 134}) + doTest([]byte{173, 151, 109, 88, 104, 65, 76, 111, 219, 237, 2, 173, 25, 84, 98, 16, 135, 157, 14, 194, 228, 86, 167, 187, 137, 245, 144, 61, 200, 76, 188, 117, 223, 172, 16, 116, 84, 1, 203, 173, 170, 32, 135, 67, 16}, []byte{150, 31, 11, 211, 82, 221, 251, 84, 254, 121, 68, 34, 211, 142, 197, 246, 138, 204, 60, 197, 210, 238, 142, 234, 187, 200, 179, 228}) + doTest([]byte{171, 185, 30, 162, 129, 205, 254, 186, 86, 239, 178, 206, 115, 177, 14, 166, 143, 48, 141, 205, 109, 67, 238, 187, 134, 210, 96, 23, 195, 206, 100, 171, 156, 8, 229, 131, 169, 169, 59, 167, 224, 241, 185, 132, 162, 50, 87, 252, 156, 122, 248, 19, 130, 31, 127}, []byte{62, 42, 216, 109, 23, 176, 255, 137, 139, 90, 7, 186, 175, 243, 160, 206, 37, 94, 157, 217, 11, 169, 126, 41, 73, 133, 212, 232, 249, 117, 70, 147, 137, 156, 43, 243, 234, 155, 94, 38, 59, 211, 218, 165, 3, 33, 231, 237, 92, 16, 128}) + doTest([]byte{98, 28, 174, 108, 231, 247, 135, 139, 6, 50, 107, 203, 138, 252, 229, 245, 230, 236, 124, 138, 105, 25, 83, 122}, []byte{97, 214, 25, 2, 14, 48, 65, 212, 241, 200, 81, 57, 176, 59, 16, 55, 20, 91, 66}) + doTest([]byte{73, 214, 80, 41, 125, 136, 126, 184, 70, 141, 140, 58, 249, 250, 49, 249, 155, 0, 236, 49, 17, 125, 18, 29}, []byte{128, 16, 47, 235, 125, 128, 97, 245, 177, 210, 219, 195}) + doTest([]byte{3, 220, 98, 73, 200, 52, 8, 107, 173, 177, 58, 221, 180, 226, 76, 210, 182, 88, 104, 171, 243, 129, 88, 112, 126, 83, 141, 50, 106, 204, 195, 51, 141, 75, 132, 161}, []byte{110, 178, 213, 174, 1, 241, 95}) + doTest([]byte{196, 88, 50, 142, 76, 128, 190, 189, 76, 9, 228, 62, 198, 186, 180, 240, 62, 130, 132, 242}, []byte{244, 89, 17, 143, 3, 180, 150, 242, 167, 214, 209, 133, 120, 213, 173, 59, 25, 158, 251}) + doTest([]byte{166, 214, 1, 225, 237, 7, 80, 104, 94, 170, 125, 184, 148, 16, 121, 101, 52, 216, 177, 192, 6, 132, 77, 44, 5, 9, 126, 156, 12, 2, 29, 99, 51, 78, 177, 92, 140, 107, 146, 183, 109, 227, 171, 57, 193, 14, 37}, []byte{245, 46, 189, 11, 202, 195, 89, 53, 215, 172, 132, 196, 145, 141, 239, 160, 242, 7, 85, 251, 193, 85}) +} diff --git a/vendor/github.com/boombuler/barcode/qr/numeric.go b/vendor/github.com/boombuler/barcode/qr/numeric.go new file mode 100644 index 0000000..49b44cc --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/numeric.go @@ -0,0 +1,56 @@ +package qr + +import ( + "errors" + "fmt" + "strconv" + + "github.com/boombuler/barcode/utils" +) + +func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { + contentBitCount := (len(content) / 3) * 10 + switch len(content) % 3 { + case 1: + contentBitCount += 4 + case 2: + contentBitCount += 7 + } + vi := findSmallestVersionInfo(ecl, numericMode, contentBitCount) + if vi == nil { + return nil, nil, errors.New("To much data to encode") + } + res := new(utils.BitList) + res.AddBits(int(numericMode), 4) + res.AddBits(len(content), vi.charCountBits(numericMode)) + + for pos := 0; pos < len(content); pos += 3 { + var curStr string + if pos+3 <= len(content) { + curStr = content[pos : pos+3] + } else { + curStr = content[pos:] + } + + i, err := strconv.Atoi(curStr) + if err != nil || i < 0 { + return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, Numeric) + } + var bitCnt byte + switch len(curStr) % 3 { + case 0: + bitCnt = 10 + case 1: + bitCnt = 4 + break + case 2: + bitCnt = 7 + break + } + + res.AddBits(i, bitCnt) + } + + addPaddingAndTerminator(res, vi) + return res, vi, nil +} diff --git a/vendor/github.com/boombuler/barcode/qr/numeric_test.go b/vendor/github.com/boombuler/barcode/qr/numeric_test.go new file mode 100644 index 0000000..21aa9e3 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/numeric_test.go @@ -0,0 +1,26 @@ +package qr + +import ( + "bytes" + "testing" +) + +func Test_NumericEncoding(t *testing.T) { + encode := Numeric.getEncoder() + x, vi, err := encode("01234567", H) + if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{16, 32, 12, 86, 97, 128, 236, 17, 236}) != 0 { + t.Error("\"01234567\" failed to encode") + } + x, vi, err = encode("0123456789012345", H) + if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{16, 64, 12, 86, 106, 110, 20, 234, 80}) != 0 { + t.Error("\"0123456789012345\" failed to encode") + } + x, vi, err = encode("foo", H) + if err == nil { + t.Error("Numeric encoding should not be able to encode \"foo\"") + } + x, vi, err = encode(makeString(14297, "1"), H) + if x != nil || vi != nil || err == nil { + t.Fail() + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/qrcode.go b/vendor/github.com/boombuler/barcode/qr/qrcode.go new file mode 100644 index 0000000..1360760 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/qrcode.go @@ -0,0 +1,166 @@ +package qr + +import ( + "image" + "image/color" + "math" + + "github.com/boombuler/barcode" + "github.com/boombuler/barcode/utils" +) + +type qrcode struct { + dimension int + data *utils.BitList + content string +} + +func (qr *qrcode) Content() string { + return qr.content +} + +func (qr *qrcode) Metadata() barcode.Metadata { + return barcode.Metadata{barcode.TypeQR, 2} +} + +func (qr *qrcode) ColorModel() color.Model { + return color.Gray16Model +} + +func (qr *qrcode) Bounds() image.Rectangle { + return image.Rect(0, 0, qr.dimension, qr.dimension) +} + +func (qr *qrcode) At(x, y int) color.Color { + if qr.Get(x, y) { + return color.Black + } + return color.White +} + +func (qr *qrcode) Get(x, y int) bool { + return qr.data.GetBit(x*qr.dimension + y) +} + +func (qr *qrcode) Set(x, y int, val bool) { + qr.data.SetBit(x*qr.dimension+y, val) +} + +func (qr *qrcode) calcPenalty() uint { + return qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4() +} + +func (qr *qrcode) calcPenaltyRule1() uint { + var result uint + for x := 0; x < qr.dimension; x++ { + checkForX := false + var cntX uint + checkForY := false + var cntY uint + + for y := 0; y < qr.dimension; y++ { + if qr.Get(x, y) == checkForX { + cntX++ + } else { + checkForX = !checkForX + if cntX >= 5 { + result += cntX - 2 + } + cntX = 1 + } + + if qr.Get(y, x) == checkForY { + cntY++ + } else { + checkForY = !checkForY + if cntY >= 5 { + result += cntY - 2 + } + cntY = 1 + } + } + + if cntX >= 5 { + result += cntX - 2 + } + if cntY >= 5 { + result += cntY - 2 + } + } + + return result +} + +func (qr *qrcode) calcPenaltyRule2() uint { + var result uint + for x := 0; x < qr.dimension-1; x++ { + for y := 0; y < qr.dimension-1; y++ { + check := qr.Get(x, y) + if qr.Get(x, y+1) == check && qr.Get(x+1, y) == check && qr.Get(x+1, y+1) == check { + result += 3 + } + } + } + return result +} + +func (qr *qrcode) calcPenaltyRule3() uint { + pattern1 := []bool{true, false, true, true, true, false, true, false, false, false, false} + pattern2 := []bool{false, false, false, false, true, false, true, true, true, false, true} + + var result uint + for x := 0; x <= qr.dimension-len(pattern1); x++ { + for y := 0; y < qr.dimension; y++ { + pattern1XFound := true + pattern2XFound := true + pattern1YFound := true + pattern2YFound := true + + for i := 0; i < len(pattern1); i++ { + iv := qr.Get(x+i, y) + if iv != pattern1[i] { + pattern1XFound = false + } + if iv != pattern2[i] { + pattern2XFound = false + } + iv = qr.Get(y, x+i) + if iv != pattern1[i] { + pattern1YFound = false + } + if iv != pattern2[i] { + pattern2YFound = false + } + } + if pattern1XFound || pattern2XFound { + result += 40 + } + if pattern1YFound || pattern2YFound { + result += 40 + } + } + } + + return result +} + +func (qr *qrcode) calcPenaltyRule4() uint { + totalNum := qr.data.Len() + trueCnt := 0 + for i := 0; i < totalNum; i++ { + if qr.data.GetBit(i) { + trueCnt++ + } + } + percDark := float64(trueCnt) * 100 / float64(totalNum) + floor := math.Abs(math.Floor(percDark/5) - 10) + ceil := math.Abs(math.Ceil(percDark/5) - 10) + return uint(math.Min(floor, ceil) * 10) +} + +func newBarcode(dim int) *qrcode { + res := new(qrcode) + res.dimension = dim + res.data = utils.NewBitList(dim * dim) + return res +} diff --git a/vendor/github.com/boombuler/barcode/qr/qrcode_test.go b/vendor/github.com/boombuler/barcode/qr/qrcode_test.go new file mode 100644 index 0000000..8cc17e3 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/qrcode_test.go @@ -0,0 +1,126 @@ +package qr + +import ( + "image/color" + "testing" +) + +func Test_NewQRCode(t *testing.T) { + bc := newBarcode(2) + if bc == nil { + t.Fail() + } + if bc.data.Len() != 4 { + t.Fail() + } + if bc.dimension != 2 { + t.Fail() + } +} + +func Test_QRBasics(t *testing.T) { + qr := newBarcode(10) + if qr.ColorModel() != color.Gray16Model { + t.Fail() + } + code, _ := Encode("test", L, Unicode) + if code.Content() != "test" { + t.Fail() + } + if code.Metadata().Dimensions != 2 { + t.Fail() + } + bounds := code.Bounds() + if bounds.Min.X != 0 || bounds.Min.Y != 0 || bounds.Max.X != 21 || bounds.Max.Y != 21 { + t.Fail() + } + if code.At(0, 0) != color.Black || code.At(0, 7) != color.White { + t.Fail() + } + qr = code.(*qrcode) + if !qr.Get(0, 0) || qr.Get(0, 7) { + t.Fail() + } + sum := qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4() + if qr.calcPenalty() != sum { + t.Fail() + } +} + +func Test_Penalty1(t *testing.T) { + qr := newBarcode(7) + if qr.calcPenaltyRule1() != 70 { + t.Fail() + } + qr.Set(0, 0, true) + if qr.calcPenaltyRule1() != 68 { + t.Fail() + } + qr.Set(0, 6, true) + if qr.calcPenaltyRule1() != 66 { + t.Fail() + } +} + +func Test_Penalty2(t *testing.T) { + qr := newBarcode(3) + if qr.calcPenaltyRule2() != 12 { + t.Fail() + } + qr.Set(0, 0, true) + qr.Set(1, 1, true) + qr.Set(2, 0, true) + if qr.calcPenaltyRule2() != 0 { + t.Fail() + } + qr.Set(1, 1, false) + if qr.calcPenaltyRule2() != 6 { + t.Fail() + } +} + +func Test_Penalty3(t *testing.T) { + runTest := func(content string, result uint) { + code, _ := Encode(content, L, AlphaNumeric) + qr := code.(*qrcode) + if qr.calcPenaltyRule3() != result { + t.Errorf("Failed Penalty Rule 3 for content \"%s\" got %d but expected %d", content, qr.calcPenaltyRule3(), result) + } + } + runTest("A", 80) + runTest("FOO", 40) + runTest("0815", 0) +} + +func Test_Penalty4(t *testing.T) { + qr := newBarcode(3) + if qr.calcPenaltyRule4() != 100 { + t.Fail() + } + qr.Set(0, 0, true) + if qr.calcPenaltyRule4() != 70 { + t.Fail() + } + qr.Set(0, 1, true) + if qr.calcPenaltyRule4() != 50 { + t.Fail() + } + qr.Set(0, 2, true) + if qr.calcPenaltyRule4() != 30 { + t.Fail() + } + qr.Set(1, 0, true) + if qr.calcPenaltyRule4() != 10 { + t.Fail() + } + qr.Set(1, 1, true) + if qr.calcPenaltyRule4() != 10 { + t.Fail() + } + qr = newBarcode(2) + qr.Set(0, 0, true) + qr.Set(1, 0, true) + if qr.calcPenaltyRule4() != 0 { + t.Fail() + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/unicode.go b/vendor/github.com/boombuler/barcode/qr/unicode.go new file mode 100644 index 0000000..a9135ab --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/unicode.go @@ -0,0 +1,27 @@ +package qr + +import ( + "errors" + + "github.com/boombuler/barcode/utils" +) + +func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { + data := []byte(content) + + vi := findSmallestVersionInfo(ecl, byteMode, len(data)*8) + if vi == nil { + return nil, nil, errors.New("To much data to encode") + } + + // It's not correct to add the unicode bytes to the result directly but most readers can't handle the + // required ECI header... + res := new(utils.BitList) + res.AddBits(int(byteMode), 4) + res.AddBits(len(content), vi.charCountBits(byteMode)) + for _, b := range data { + res.AddByte(b) + } + addPaddingAndTerminator(res, vi) + return res, vi, nil +} diff --git a/vendor/github.com/boombuler/barcode/qr/unicode_test.go b/vendor/github.com/boombuler/barcode/qr/unicode_test.go new file mode 100644 index 0000000..76e5fbf --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/unicode_test.go @@ -0,0 +1,18 @@ +package qr + +import ( + "bytes" + "testing" +) + +func Test_UnicodeEncoding(t *testing.T) { + encode := Unicode.getEncoder() + x, vi, err := encode("A", H) // 65 + if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{64, 20, 16, 236, 17, 236, 17, 236, 17}) != 0 { + t.Errorf("\"A\" failed to encode: %s", err) + } + _, _, err = encode(makeString(3000, "A"), H) + if err == nil { + t.Error("Unicode encoding should not be able to encode a 3kb string") + } +} diff --git a/vendor/github.com/boombuler/barcode/qr/versioninfo.go b/vendor/github.com/boombuler/barcode/qr/versioninfo.go new file mode 100644 index 0000000..6852a57 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/versioninfo.go @@ -0,0 +1,310 @@ +package qr + +import "math" + +// ErrorCorrectionLevel indicates the amount of "backup data" stored in the QR code +type ErrorCorrectionLevel byte + +const ( + // L recovers 7% of data + L ErrorCorrectionLevel = iota + // M recovers 15% of data + M + // Q recovers 25% of data + Q + // H recovers 30% of data + H +) + +func (ecl ErrorCorrectionLevel) String() string { + switch ecl { + case L: + return "L" + case M: + return "M" + case Q: + return "Q" + case H: + return "H" + } + return "unknown" +} + +type encodingMode byte + +const ( + numericMode encodingMode = 1 + alphaNumericMode encodingMode = 2 + byteMode encodingMode = 4 + kanjiMode encodingMode = 8 +) + +type versionInfo struct { + Version byte + Level ErrorCorrectionLevel + ErrorCorrectionCodewordsPerBlock byte + NumberOfBlocksInGroup1 byte + DataCodeWordsPerBlockInGroup1 byte + NumberOfBlocksInGroup2 byte + DataCodeWordsPerBlockInGroup2 byte +} + +var versionInfos = []*versionInfo{ + &versionInfo{1, L, 7, 1, 19, 0, 0}, + &versionInfo{1, M, 10, 1, 16, 0, 0}, + &versionInfo{1, Q, 13, 1, 13, 0, 0}, + &versionInfo{1, H, 17, 1, 9, 0, 0}, + &versionInfo{2, L, 10, 1, 34, 0, 0}, + &versionInfo{2, M, 16, 1, 28, 0, 0}, + &versionInfo{2, Q, 22, 1, 22, 0, 0}, + &versionInfo{2, H, 28, 1, 16, 0, 0}, + &versionInfo{3, L, 15, 1, 55, 0, 0}, + &versionInfo{3, M, 26, 1, 44, 0, 0}, + &versionInfo{3, Q, 18, 2, 17, 0, 0}, + &versionInfo{3, H, 22, 2, 13, 0, 0}, + &versionInfo{4, L, 20, 1, 80, 0, 0}, + &versionInfo{4, M, 18, 2, 32, 0, 0}, + &versionInfo{4, Q, 26, 2, 24, 0, 0}, + &versionInfo{4, H, 16, 4, 9, 0, 0}, + &versionInfo{5, L, 26, 1, 108, 0, 0}, + &versionInfo{5, M, 24, 2, 43, 0, 0}, + &versionInfo{5, Q, 18, 2, 15, 2, 16}, + &versionInfo{5, H, 22, 2, 11, 2, 12}, + &versionInfo{6, L, 18, 2, 68, 0, 0}, + &versionInfo{6, M, 16, 4, 27, 0, 0}, + &versionInfo{6, Q, 24, 4, 19, 0, 0}, + &versionInfo{6, H, 28, 4, 15, 0, 0}, + &versionInfo{7, L, 20, 2, 78, 0, 0}, + &versionInfo{7, M, 18, 4, 31, 0, 0}, + &versionInfo{7, Q, 18, 2, 14, 4, 15}, + &versionInfo{7, H, 26, 4, 13, 1, 14}, + &versionInfo{8, L, 24, 2, 97, 0, 0}, + &versionInfo{8, M, 22, 2, 38, 2, 39}, + &versionInfo{8, Q, 22, 4, 18, 2, 19}, + &versionInfo{8, H, 26, 4, 14, 2, 15}, + &versionInfo{9, L, 30, 2, 116, 0, 0}, + &versionInfo{9, M, 22, 3, 36, 2, 37}, + &versionInfo{9, Q, 20, 4, 16, 4, 17}, + &versionInfo{9, H, 24, 4, 12, 4, 13}, + &versionInfo{10, L, 18, 2, 68, 2, 69}, + &versionInfo{10, M, 26, 4, 43, 1, 44}, + &versionInfo{10, Q, 24, 6, 19, 2, 20}, + &versionInfo{10, H, 28, 6, 15, 2, 16}, + &versionInfo{11, L, 20, 4, 81, 0, 0}, + &versionInfo{11, M, 30, 1, 50, 4, 51}, + &versionInfo{11, Q, 28, 4, 22, 4, 23}, + &versionInfo{11, H, 24, 3, 12, 8, 13}, + &versionInfo{12, L, 24, 2, 92, 2, 93}, + &versionInfo{12, M, 22, 6, 36, 2, 37}, + &versionInfo{12, Q, 26, 4, 20, 6, 21}, + &versionInfo{12, H, 28, 7, 14, 4, 15}, + &versionInfo{13, L, 26, 4, 107, 0, 0}, + &versionInfo{13, M, 22, 8, 37, 1, 38}, + &versionInfo{13, Q, 24, 8, 20, 4, 21}, + &versionInfo{13, H, 22, 12, 11, 4, 12}, + &versionInfo{14, L, 30, 3, 115, 1, 116}, + &versionInfo{14, M, 24, 4, 40, 5, 41}, + &versionInfo{14, Q, 20, 11, 16, 5, 17}, + &versionInfo{14, H, 24, 11, 12, 5, 13}, + &versionInfo{15, L, 22, 5, 87, 1, 88}, + &versionInfo{15, M, 24, 5, 41, 5, 42}, + &versionInfo{15, Q, 30, 5, 24, 7, 25}, + &versionInfo{15, H, 24, 11, 12, 7, 13}, + &versionInfo{16, L, 24, 5, 98, 1, 99}, + &versionInfo{16, M, 28, 7, 45, 3, 46}, + &versionInfo{16, Q, 24, 15, 19, 2, 20}, + &versionInfo{16, H, 30, 3, 15, 13, 16}, + &versionInfo{17, L, 28, 1, 107, 5, 108}, + &versionInfo{17, M, 28, 10, 46, 1, 47}, + &versionInfo{17, Q, 28, 1, 22, 15, 23}, + &versionInfo{17, H, 28, 2, 14, 17, 15}, + &versionInfo{18, L, 30, 5, 120, 1, 121}, + &versionInfo{18, M, 26, 9, 43, 4, 44}, + &versionInfo{18, Q, 28, 17, 22, 1, 23}, + &versionInfo{18, H, 28, 2, 14, 19, 15}, + &versionInfo{19, L, 28, 3, 113, 4, 114}, + &versionInfo{19, M, 26, 3, 44, 11, 45}, + &versionInfo{19, Q, 26, 17, 21, 4, 22}, + &versionInfo{19, H, 26, 9, 13, 16, 14}, + &versionInfo{20, L, 28, 3, 107, 5, 108}, + &versionInfo{20, M, 26, 3, 41, 13, 42}, + &versionInfo{20, Q, 30, 15, 24, 5, 25}, + &versionInfo{20, H, 28, 15, 15, 10, 16}, + &versionInfo{21, L, 28, 4, 116, 4, 117}, + &versionInfo{21, M, 26, 17, 42, 0, 0}, + &versionInfo{21, Q, 28, 17, 22, 6, 23}, + &versionInfo{21, H, 30, 19, 16, 6, 17}, + &versionInfo{22, L, 28, 2, 111, 7, 112}, + &versionInfo{22, M, 28, 17, 46, 0, 0}, + &versionInfo{22, Q, 30, 7, 24, 16, 25}, + &versionInfo{22, H, 24, 34, 13, 0, 0}, + &versionInfo{23, L, 30, 4, 121, 5, 122}, + &versionInfo{23, M, 28, 4, 47, 14, 48}, + &versionInfo{23, Q, 30, 11, 24, 14, 25}, + &versionInfo{23, H, 30, 16, 15, 14, 16}, + &versionInfo{24, L, 30, 6, 117, 4, 118}, + &versionInfo{24, M, 28, 6, 45, 14, 46}, + &versionInfo{24, Q, 30, 11, 24, 16, 25}, + &versionInfo{24, H, 30, 30, 16, 2, 17}, + &versionInfo{25, L, 26, 8, 106, 4, 107}, + &versionInfo{25, M, 28, 8, 47, 13, 48}, + &versionInfo{25, Q, 30, 7, 24, 22, 25}, + &versionInfo{25, H, 30, 22, 15, 13, 16}, + &versionInfo{26, L, 28, 10, 114, 2, 115}, + &versionInfo{26, M, 28, 19, 46, 4, 47}, + &versionInfo{26, Q, 28, 28, 22, 6, 23}, + &versionInfo{26, H, 30, 33, 16, 4, 17}, + &versionInfo{27, L, 30, 8, 122, 4, 123}, + &versionInfo{27, M, 28, 22, 45, 3, 46}, + &versionInfo{27, Q, 30, 8, 23, 26, 24}, + &versionInfo{27, H, 30, 12, 15, 28, 16}, + &versionInfo{28, L, 30, 3, 117, 10, 118}, + &versionInfo{28, M, 28, 3, 45, 23, 46}, + &versionInfo{28, Q, 30, 4, 24, 31, 25}, + &versionInfo{28, H, 30, 11, 15, 31, 16}, + &versionInfo{29, L, 30, 7, 116, 7, 117}, + &versionInfo{29, M, 28, 21, 45, 7, 46}, + &versionInfo{29, Q, 30, 1, 23, 37, 24}, + &versionInfo{29, H, 30, 19, 15, 26, 16}, + &versionInfo{30, L, 30, 5, 115, 10, 116}, + &versionInfo{30, M, 28, 19, 47, 10, 48}, + &versionInfo{30, Q, 30, 15, 24, 25, 25}, + &versionInfo{30, H, 30, 23, 15, 25, 16}, + &versionInfo{31, L, 30, 13, 115, 3, 116}, + &versionInfo{31, M, 28, 2, 46, 29, 47}, + &versionInfo{31, Q, 30, 42, 24, 1, 25}, + &versionInfo{31, H, 30, 23, 15, 28, 16}, + &versionInfo{32, L, 30, 17, 115, 0, 0}, + &versionInfo{32, M, 28, 10, 46, 23, 47}, + &versionInfo{32, Q, 30, 10, 24, 35, 25}, + &versionInfo{32, H, 30, 19, 15, 35, 16}, + &versionInfo{33, L, 30, 17, 115, 1, 116}, + &versionInfo{33, M, 28, 14, 46, 21, 47}, + &versionInfo{33, Q, 30, 29, 24, 19, 25}, + &versionInfo{33, H, 30, 11, 15, 46, 16}, + &versionInfo{34, L, 30, 13, 115, 6, 116}, + &versionInfo{34, M, 28, 14, 46, 23, 47}, + &versionInfo{34, Q, 30, 44, 24, 7, 25}, + &versionInfo{34, H, 30, 59, 16, 1, 17}, + &versionInfo{35, L, 30, 12, 121, 7, 122}, + &versionInfo{35, M, 28, 12, 47, 26, 48}, + &versionInfo{35, Q, 30, 39, 24, 14, 25}, + &versionInfo{35, H, 30, 22, 15, 41, 16}, + &versionInfo{36, L, 30, 6, 121, 14, 122}, + &versionInfo{36, M, 28, 6, 47, 34, 48}, + &versionInfo{36, Q, 30, 46, 24, 10, 25}, + &versionInfo{36, H, 30, 2, 15, 64, 16}, + &versionInfo{37, L, 30, 17, 122, 4, 123}, + &versionInfo{37, M, 28, 29, 46, 14, 47}, + &versionInfo{37, Q, 30, 49, 24, 10, 25}, + &versionInfo{37, H, 30, 24, 15, 46, 16}, + &versionInfo{38, L, 30, 4, 122, 18, 123}, + &versionInfo{38, M, 28, 13, 46, 32, 47}, + &versionInfo{38, Q, 30, 48, 24, 14, 25}, + &versionInfo{38, H, 30, 42, 15, 32, 16}, + &versionInfo{39, L, 30, 20, 117, 4, 118}, + &versionInfo{39, M, 28, 40, 47, 7, 48}, + &versionInfo{39, Q, 30, 43, 24, 22, 25}, + &versionInfo{39, H, 30, 10, 15, 67, 16}, + &versionInfo{40, L, 30, 19, 118, 6, 119}, + &versionInfo{40, M, 28, 18, 47, 31, 48}, + &versionInfo{40, Q, 30, 34, 24, 34, 25}, + &versionInfo{40, H, 30, 20, 15, 61, 16}, +} + +func (vi *versionInfo) totalDataBytes() int { + g1Data := int(vi.NumberOfBlocksInGroup1) * int(vi.DataCodeWordsPerBlockInGroup1) + g2Data := int(vi.NumberOfBlocksInGroup2) * int(vi.DataCodeWordsPerBlockInGroup2) + return (g1Data + g2Data) +} + +func (vi *versionInfo) charCountBits(m encodingMode) byte { + switch m { + case numericMode: + if vi.Version < 10 { + return 10 + } else if vi.Version < 27 { + return 12 + } + return 14 + + case alphaNumericMode: + if vi.Version < 10 { + return 9 + } else if vi.Version < 27 { + return 11 + } + return 13 + + case byteMode: + if vi.Version < 10 { + return 8 + } + return 16 + + case kanjiMode: + if vi.Version < 10 { + return 8 + } else if vi.Version < 27 { + return 10 + } + return 12 + default: + return 0 + } +} + +func (vi *versionInfo) modulWidth() int { + return ((int(vi.Version) - 1) * 4) + 21 +} + +func (vi *versionInfo) alignmentPatternPlacements() []int { + if vi.Version == 1 { + return make([]int, 0) + } + + first := 6 + last := vi.modulWidth() - 7 + space := float64(last - first) + count := int(math.Ceil(space/28)) + 1 + + result := make([]int, count) + result[0] = first + result[len(result)-1] = last + if count > 2 { + step := int(math.Ceil(float64(last-first) / float64(count-1))) + if step%2 == 1 { + frac := float64(last-first) / float64(count-1) + _, x := math.Modf(frac) + if x >= 0.5 { + frac = math.Ceil(frac) + } else { + frac = math.Floor(frac) + } + + if int(frac)%2 == 0 { + step-- + } else { + step++ + } + } + + for i := 1; i <= count-2; i++ { + result[i] = last - (step * (count - 1 - i)) + } + } + + return result +} + +func findSmallestVersionInfo(ecl ErrorCorrectionLevel, mode encodingMode, dataBits int) *versionInfo { + dataBits = dataBits + 4 // mode indicator + for _, vi := range versionInfos { + if vi.Level == ecl { + if (vi.totalDataBytes() * 8) >= (dataBits + int(vi.charCountBits(mode))) { + return vi + } + } + } + return nil +} diff --git a/vendor/github.com/boombuler/barcode/qr/versioninfo_test.go b/vendor/github.com/boombuler/barcode/qr/versioninfo_test.go new file mode 100644 index 0000000..f41aa37 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/qr/versioninfo_test.go @@ -0,0 +1,157 @@ +package qr + +import "testing" + +var testvi = &versionInfo{7, M, 0, 1, 10, 2, 5} // Fake versionInfo to run some of the tests + +func Test_ErrorCorrectionStringer(t *testing.T) { + tests := map[ErrorCorrectionLevel]string{ + L: "L", M: "M", Q: "Q", H: "H", ErrorCorrectionLevel(99): "unknown", + } + for ecl, str := range tests { + if ecl.String() != str { + t.Fail() + } + } +} + +func Test_CharCountBits(t *testing.T) { + v1 := &versionInfo{5, M, 0, 0, 0, 0, 0} + v2 := &versionInfo{15, M, 0, 0, 0, 0, 0} + v3 := &versionInfo{30, M, 0, 0, 0, 0, 0} + + if v1.charCountBits(numericMode) != 10 { + t.Fail() + } + if v1.charCountBits(alphaNumericMode) != 9 { + t.Fail() + } + if v1.charCountBits(byteMode) != 8 { + t.Fail() + } + if v1.charCountBits(kanjiMode) != 8 { + t.Fail() + } + if v2.charCountBits(numericMode) != 12 { + t.Fail() + } + if v2.charCountBits(alphaNumericMode) != 11 { + t.Fail() + } + if v2.charCountBits(byteMode) != 16 { + t.Fail() + } + if v2.charCountBits(kanjiMode) != 10 { + t.Fail() + } + if v3.charCountBits(numericMode) != 14 { + t.Fail() + } + if v3.charCountBits(alphaNumericMode) != 13 { + t.Fail() + } + if v3.charCountBits(byteMode) != 16 { + t.Fail() + } + if v3.charCountBits(kanjiMode) != 12 { + t.Fail() + } + if v1.charCountBits(encodingMode(3)) != 0 { + t.Fail() + } +} + +func Test_TotalDataBytes(t *testing.T) { + if testvi.totalDataBytes() != 20 { + t.Fail() + } +} + +func Test_ModulWidth(t *testing.T) { + if testvi.modulWidth() != 45 { + t.Fail() + } +} + +func Test_FindSmallestVersionInfo(t *testing.T) { + if findSmallestVersionInfo(H, alphaNumericMode, 10208) != nil { + t.Error("there should be no version with this capacity") + } + test := func(cap int, tVersion byte) { + v := findSmallestVersionInfo(H, alphaNumericMode, cap) + if v == nil || v.Version != tVersion { + t.Errorf("version %d should be returned.", tVersion) + } + } + test(10191, 40) + test(5591, 29) + test(5592, 30) + test(190, 3) + test(200, 4) +} + +type aligmnentTest struct { + version byte + patterns []int +} + +var allAligmnentTests = []*aligmnentTest{ + &aligmnentTest{1, []int{}}, + &aligmnentTest{2, []int{6, 18}}, + &aligmnentTest{3, []int{6, 22}}, + &aligmnentTest{4, []int{6, 26}}, + &aligmnentTest{5, []int{6, 30}}, + &aligmnentTest{6, []int{6, 34}}, + &aligmnentTest{7, []int{6, 22, 38}}, + &aligmnentTest{8, []int{6, 24, 42}}, + &aligmnentTest{9, []int{6, 26, 46}}, + &aligmnentTest{10, []int{6, 28, 50}}, + &aligmnentTest{11, []int{6, 30, 54}}, + &aligmnentTest{12, []int{6, 32, 58}}, + &aligmnentTest{13, []int{6, 34, 62}}, + &aligmnentTest{14, []int{6, 26, 46, 66}}, + &aligmnentTest{15, []int{6, 26, 48, 70}}, + &aligmnentTest{16, []int{6, 26, 50, 74}}, + &aligmnentTest{17, []int{6, 30, 54, 78}}, + &aligmnentTest{18, []int{6, 30, 56, 82}}, + &aligmnentTest{19, []int{6, 30, 58, 86}}, + &aligmnentTest{20, []int{6, 34, 62, 90}}, + &aligmnentTest{21, []int{6, 28, 50, 72, 94}}, + &aligmnentTest{22, []int{6, 26, 50, 74, 98}}, + &aligmnentTest{23, []int{6, 30, 54, 78, 102}}, + &aligmnentTest{24, []int{6, 28, 54, 80, 106}}, + &aligmnentTest{25, []int{6, 32, 58, 84, 110}}, + &aligmnentTest{26, []int{6, 30, 58, 86, 114}}, + &aligmnentTest{27, []int{6, 34, 62, 90, 118}}, + &aligmnentTest{28, []int{6, 26, 50, 74, 98, 122}}, + &aligmnentTest{29, []int{6, 30, 54, 78, 102, 126}}, + &aligmnentTest{30, []int{6, 26, 52, 78, 104, 130}}, + &aligmnentTest{31, []int{6, 30, 56, 82, 108, 134}}, + &aligmnentTest{32, []int{6, 34, 60, 86, 112, 138}}, + &aligmnentTest{33, []int{6, 30, 58, 86, 114, 142}}, + &aligmnentTest{34, []int{6, 34, 62, 90, 118, 146}}, + &aligmnentTest{35, []int{6, 30, 54, 78, 102, 126, 150}}, + &aligmnentTest{36, []int{6, 24, 50, 76, 102, 128, 154}}, + &aligmnentTest{37, []int{6, 28, 54, 80, 106, 132, 158}}, + &aligmnentTest{38, []int{6, 32, 58, 84, 110, 136, 162}}, + &aligmnentTest{39, []int{6, 26, 54, 82, 110, 138, 166}}, + &aligmnentTest{40, []int{6, 30, 58, 86, 114, 142, 170}}, +} + +func Test_AlignmentPatternPlacements(t *testing.T) { + for _, at := range allAligmnentTests { + vi := &versionInfo{at.version, M, 0, 0, 0, 0, 0} + + res := vi.alignmentPatternPlacements() + if len(res) != len(at.patterns) { + t.Errorf("number of alignmentpatterns missmatch for version %d", at.version) + } + for i := 0; i < len(res); i++ { + if res[i] != at.patterns[i] { + t.Errorf("alignmentpatterns for version %d missmatch on index %d", at.version, i) + } + } + + } + +} diff --git a/vendor/github.com/boombuler/barcode/scaledbarcode.go b/vendor/github.com/boombuler/barcode/scaledbarcode.go new file mode 100644 index 0000000..152b180 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/scaledbarcode.go @@ -0,0 +1,134 @@ +package barcode + +import ( + "errors" + "fmt" + "image" + "image/color" + "math" +) + +type wrapFunc func(x, y int) color.Color + +type scaledBarcode struct { + wrapped Barcode + wrapperFunc wrapFunc + rect image.Rectangle +} + +type intCSscaledBC struct { + scaledBarcode +} + +func (bc *scaledBarcode) Content() string { + return bc.wrapped.Content() +} + +func (bc *scaledBarcode) Metadata() Metadata { + return bc.wrapped.Metadata() +} + +func (bc *scaledBarcode) ColorModel() color.Model { + return bc.wrapped.ColorModel() +} + +func (bc *scaledBarcode) Bounds() image.Rectangle { + return bc.rect +} + +func (bc *scaledBarcode) At(x, y int) color.Color { + return bc.wrapperFunc(x, y) +} + +func (bc *intCSscaledBC) CheckSum() int { + if cs, ok := bc.wrapped.(BarcodeIntCS); ok { + return cs.CheckSum() + } + return 0 +} + +// Scale returns a resized barcode with the given width and height. +func Scale(bc Barcode, width, height int) (Barcode, error) { + switch bc.Metadata().Dimensions { + case 1: + return scale1DCode(bc, width, height) + case 2: + return scale2DCode(bc, width, height) + } + + return nil, errors.New("unsupported barcode format") +} + +func newScaledBC(wrapped Barcode, wrapperFunc wrapFunc, rect image.Rectangle) Barcode { + result := &scaledBarcode{ + wrapped: wrapped, + wrapperFunc: wrapperFunc, + rect: rect, + } + + if _, ok := wrapped.(BarcodeIntCS); ok { + return &intCSscaledBC{*result} + } + return result +} + +func scale2DCode(bc Barcode, width, height int) (Barcode, error) { + orgBounds := bc.Bounds() + orgWidth := orgBounds.Max.X - orgBounds.Min.X + orgHeight := orgBounds.Max.Y - orgBounds.Min.Y + + factor := int(math.Min(float64(width)/float64(orgWidth), float64(height)/float64(orgHeight))) + if factor <= 0 { + return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx%d", orgWidth, orgHeight) + } + + offsetX := (width - (orgWidth * factor)) / 2 + offsetY := (height - (orgHeight * factor)) / 2 + + wrap := func(x, y int) color.Color { + if x < offsetX || y < offsetY { + return color.White + } + x = (x - offsetX) / factor + y = (y - offsetY) / factor + if x >= orgWidth || y >= orgHeight { + return color.White + } + return bc.At(x, y) + } + + return newScaledBC( + bc, + wrap, + image.Rect(0, 0, width, height), + ), nil +} + +func scale1DCode(bc Barcode, width, height int) (Barcode, error) { + orgBounds := bc.Bounds() + orgWidth := orgBounds.Max.X - orgBounds.Min.X + factor := int(float64(width) / float64(orgWidth)) + + if factor <= 0 { + return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx1", orgWidth) + } + offsetX := (width - (orgWidth * factor)) / 2 + + wrap := func(x, y int) color.Color { + if x < offsetX { + return color.White + } + x = (x - offsetX) / factor + + if x >= orgWidth { + return color.White + } + return bc.At(x, 0) + } + + return newScaledBC( + bc, + wrap, + image.Rect(0, 0, width, height), + ), nil +} diff --git a/vendor/github.com/boombuler/barcode/utils/base1dcode.go b/vendor/github.com/boombuler/barcode/utils/base1dcode.go new file mode 100644 index 0000000..75e5004 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/base1dcode.go @@ -0,0 +1,57 @@ +// Package utils contain some utilities which are needed to create barcodes +package utils + +import ( + "image" + "image/color" + + "github.com/boombuler/barcode" +) + +type base1DCode struct { + *BitList + kind string + content string +} + +type base1DCodeIntCS struct { + base1DCode + checksum int +} + +func (c *base1DCode) Content() string { + return c.content +} + +func (c *base1DCode) Metadata() barcode.Metadata { + return barcode.Metadata{c.kind, 1} +} + +func (c *base1DCode) ColorModel() color.Model { + return color.Gray16Model +} + +func (c *base1DCode) Bounds() image.Rectangle { + return image.Rect(0, 0, c.Len(), 1) +} + +func (c *base1DCode) At(x, y int) color.Color { + if c.GetBit(x) { + return color.Black + } + return color.White +} + +func (c *base1DCodeIntCS) CheckSum() int { + return c.checksum +} + +// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList +func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, checksum int) barcode.BarcodeIntCS { + return &base1DCodeIntCS{base1DCode{bars, codeKind, content}, checksum} +} + +// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList +func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode { + return &base1DCode{bars, codeKind, content} +} diff --git a/vendor/github.com/boombuler/barcode/utils/bitlist.go b/vendor/github.com/boombuler/barcode/utils/bitlist.go new file mode 100644 index 0000000..bb05e53 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/bitlist.go @@ -0,0 +1,119 @@ +package utils + +// BitList is a list that contains bits +type BitList struct { + count int + data []int32 +} + +// NewBitList returns a new BitList with the given length +// all bits are initialize with false +func NewBitList(capacity int) *BitList { + bl := new(BitList) + bl.count = capacity + x := 0 + if capacity%32 != 0 { + x = 1 + } + bl.data = make([]int32, capacity/32+x) + return bl +} + +// Len returns the number of contained bits +func (bl *BitList) Len() int { + return bl.count +} + +func (bl *BitList) grow() { + growBy := len(bl.data) + if growBy < 128 { + growBy = 128 + } else if growBy >= 1024 { + growBy = 1024 + } + + nd := make([]int32, len(bl.data)+growBy) + copy(nd, bl.data) + bl.data = nd +} + +// AddBit appends the given bits to the end of the list +func (bl *BitList) AddBit(bits ...bool) { + for _, bit := range bits { + itmIndex := bl.count / 32 + for itmIndex >= len(bl.data) { + bl.grow() + } + bl.SetBit(bl.count, bit) + bl.count++ + } +} + +// SetBit sets the bit at the given index to the given value +func (bl *BitList) SetBit(index int, value bool) { + itmIndex := index / 32 + itmBitShift := 31 - (index % 32) + if value { + bl.data[itmIndex] = bl.data[itmIndex] | 1<> uint(itmBitShift)) & 1) == 1 +} + +// AddByte appends all 8 bits of the given byte to the end of the list +func (bl *BitList) AddByte(b byte) { + for i := 7; i >= 0; i-- { + bl.AddBit(((b >> uint(i)) & 1) == 1) + } +} + +// AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list +func (bl *BitList) AddBits(b int, count byte) { + for i := int(count) - 1; i >= 0; i-- { + bl.AddBit(((b >> uint(i)) & 1) == 1) + } +} + +// GetBytes returns all bits of the BitList as a []byte +func (bl *BitList) GetBytes() []byte { + len := bl.count >> 3 + if (bl.count % 8) != 0 { + len++ + } + result := make([]byte, len) + for i := 0; i < len; i++ { + shift := (3 - (i % 4)) * 8 + result[i] = (byte)((bl.data[i/4] >> uint(shift)) & 0xFF) + } + return result +} + +// IterateBytes iterates through all bytes contained in the BitList +func (bl *BitList) IterateBytes() <-chan byte { + res := make(chan byte) + + go func() { + c := bl.count + shift := 24 + i := 0 + for c > 0 { + res <- byte((bl.data[i] >> uint(shift)) & 0xFF) + shift -= 8 + if shift < 0 { + shift = 24 + i++ + } + c -= 8 + } + close(res) + }() + + return res +} diff --git a/vendor/github.com/boombuler/barcode/utils/galoisfield.go b/vendor/github.com/boombuler/barcode/utils/galoisfield.go new file mode 100644 index 0000000..68726fb --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/galoisfield.go @@ -0,0 +1,65 @@ +package utils + +// GaloisField encapsulates galois field arithmetics +type GaloisField struct { + Size int + Base int + ALogTbl []int + LogTbl []int +} + +// NewGaloisField creates a new galois field +func NewGaloisField(pp, fieldSize, b int) *GaloisField { + result := new(GaloisField) + + result.Size = fieldSize + result.Base = b + result.ALogTbl = make([]int, fieldSize) + result.LogTbl = make([]int, fieldSize) + + x := 1 + for i := 0; i < fieldSize; i++ { + result.ALogTbl[i] = x + x = x * 2 + if x >= fieldSize { + x = (x ^ pp) & (fieldSize - 1) + } + } + + for i := 0; i < fieldSize; i++ { + result.LogTbl[result.ALogTbl[i]] = int(i) + } + + return result +} + +func (gf *GaloisField) Zero() *GFPoly { + return NewGFPoly(gf, []int{0}) +} + +// AddOrSub add or substract two numbers +func (gf *GaloisField) AddOrSub(a, b int) int { + return a ^ b +} + +// Multiply multiplys two numbers +func (gf *GaloisField) Multiply(a, b int) int { + if a == 0 || b == 0 { + return 0 + } + return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%(gf.Size-1)] +} + +// Divide divides two numbers +func (gf *GaloisField) Divide(a, b int) int { + if b == 0 { + panic("divide by zero") + } else if a == 0 { + return 0 + } + return gf.ALogTbl[(gf.LogTbl[a]-gf.LogTbl[b])%(gf.Size-1)] +} + +func (gf *GaloisField) Invers(num int) int { + return gf.ALogTbl[(gf.Size-1)-gf.LogTbl[num]] +} diff --git a/vendor/github.com/boombuler/barcode/utils/galoisfield_test.go b/vendor/github.com/boombuler/barcode/utils/galoisfield_test.go new file mode 100644 index 0000000..4a32656 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/galoisfield_test.go @@ -0,0 +1,59 @@ +package utils + +import ( + "testing" +) + +func Test_GF(t *testing.T) { + log := []int{ + 0, 255, 1, 240, 2, 225, 241, 53, 3, 38, 226, 133, 242, 43, 54, 210, + 4, 195, 39, 114, 227, 106, 134, 28, 243, 140, 44, 23, 55, 118, 211, 234, + 5, 219, 196, 96, 40, 222, 115, 103, 228, 78, 107, 125, 135, 8, 29, 162, + 244, 186, 141, 180, 45, 99, 24, 49, 56, 13, 119, 153, 212, 199, 235, 91, + 6, 76, 220, 217, 197, 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193, + 229, 86, 79, 171, 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84, + 245, 173, 187, 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207, + 57, 147, 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176, + 7, 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179, + 42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194, 113, + 230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127, 247, 146, 66, + 137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73, 164, 144, 85, 170, + 246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82, 72, 182, 215, 191, 251, + 47, 178, 89, 151, 101, 94, 160, 123, 26, 112, 232, 21, 51, 238, 208, 131, + 58, 69, 148, 18, 15, 16, 68, 17, 121, 149, 129, 19, 155, 59, 249, 70, + 214, 250, 168, 71, 201, 156, 64, 60, 237, 130, 111, 20, 93, 122, 177, 150, + } + + alog := []int{ + 1, 2, 4, 8, 16, 32, 64, 128, 45, 90, 180, 69, 138, 57, 114, 228, + 229, 231, 227, 235, 251, 219, 155, 27, 54, 108, 216, 157, 23, 46, 92, 184, + 93, 186, 89, 178, 73, 146, 9, 18, 36, 72, 144, 13, 26, 52, 104, 208, + 141, 55, 110, 220, 149, 7, 14, 28, 56, 112, 224, 237, 247, 195, 171, 123, + 246, 193, 175, 115, 230, 225, 239, 243, 203, 187, 91, 182, 65, 130, 41, 82, + 164, 101, 202, 185, 95, 190, 81, 162, 105, 210, 137, 63, 126, 252, 213, 135, + 35, 70, 140, 53, 106, 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250, + 217, 159, 19, 38, 76, 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172, + 117, 234, 249, 223, 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200, + 189, 87, 174, 113, 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107, + 214, 129, 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169, + 127, 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206, + 177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161, 111, + 222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132, 37, 74, + 148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248, 221, 151, + 3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75, 150, 1, + } + + gf := NewGaloisField(301, 256, 1) + if len(gf.LogTbl) != len(gf.ALogTbl) || len(gf.LogTbl) != len(log) { + t.Fail() + } + for i := 0; i < len(log); i++ { + if gf.LogTbl[i] != log[i] { + t.Error("Invalid Log Table") + } + if gf.ALogTbl[i] != alog[i] { + t.Error("Invalid ALog Table") + } + } + +} diff --git a/vendor/github.com/boombuler/barcode/utils/gfpoly.go b/vendor/github.com/boombuler/barcode/utils/gfpoly.go new file mode 100644 index 0000000..c56bb40 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/gfpoly.go @@ -0,0 +1,103 @@ +package utils + +type GFPoly struct { + gf *GaloisField + Coefficients []int +} + +func (gp *GFPoly) Degree() int { + return len(gp.Coefficients) - 1 +} + +func (gp *GFPoly) Zero() bool { + return gp.Coefficients[0] == 0 +} + +// GetCoefficient returns the coefficient of x ^ degree +func (gp *GFPoly) GetCoefficient(degree int) int { + return gp.Coefficients[gp.Degree()-degree] +} + +func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly { + if gp.Zero() { + return other + } else if other.Zero() { + return gp + } + smallCoeff := gp.Coefficients + largeCoeff := other.Coefficients + if len(smallCoeff) > len(largeCoeff) { + largeCoeff, smallCoeff = smallCoeff, largeCoeff + } + sumDiff := make([]int, len(largeCoeff)) + lenDiff := len(largeCoeff) - len(smallCoeff) + copy(sumDiff, largeCoeff[:lenDiff]) + for i := lenDiff; i < len(largeCoeff); i++ { + sumDiff[i] = int(gp.gf.AddOrSub(int(smallCoeff[i-lenDiff]), int(largeCoeff[i]))) + } + return NewGFPoly(gp.gf, sumDiff) +} + +func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly { + if coeff == 0 { + return gp.gf.Zero() + } + size := len(gp.Coefficients) + result := make([]int, size+degree) + for i := 0; i < size; i++ { + result[i] = int(gp.gf.Multiply(int(gp.Coefficients[i]), int(coeff))) + } + return NewGFPoly(gp.gf, result) +} + +func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly { + if gp.Zero() || other.Zero() { + return gp.gf.Zero() + } + aCoeff := gp.Coefficients + aLen := len(aCoeff) + bCoeff := other.Coefficients + bLen := len(bCoeff) + product := make([]int, aLen+bLen-1) + for i := 0; i < aLen; i++ { + ac := int(aCoeff[i]) + for j := 0; j < bLen; j++ { + bc := int(bCoeff[j]) + product[i+j] = int(gp.gf.AddOrSub(int(product[i+j]), gp.gf.Multiply(ac, bc))) + } + } + return NewGFPoly(gp.gf, product) +} + +func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *GFPoly) { + quotient = gp.gf.Zero() + remainder = gp + fld := gp.gf + denomLeadTerm := other.GetCoefficient(other.Degree()) + inversDenomLeadTerm := fld.Invers(int(denomLeadTerm)) + for remainder.Degree() >= other.Degree() && !remainder.Zero() { + degreeDiff := remainder.Degree() - other.Degree() + scale := int(fld.Multiply(int(remainder.GetCoefficient(remainder.Degree())), inversDenomLeadTerm)) + term := other.MultByMonominal(degreeDiff, scale) + itQuot := NewMonominalPoly(fld, degreeDiff, scale) + quotient = quotient.AddOrSubstract(itQuot) + remainder = remainder.AddOrSubstract(term) + } + return +} + +func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly { + if coeff == 0 { + return field.Zero() + } + result := make([]int, degree+1) + result[0] = coeff + return NewGFPoly(field, result) +} + +func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly { + for len(coefficients) > 1 && coefficients[0] == 0 { + coefficients = coefficients[1:] + } + return &GFPoly{field, coefficients} +} diff --git a/vendor/github.com/boombuler/barcode/utils/reedsolomon.go b/vendor/github.com/boombuler/barcode/utils/reedsolomon.go new file mode 100644 index 0000000..53af91a --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/reedsolomon.go @@ -0,0 +1,44 @@ +package utils + +import ( + "sync" +) + +type ReedSolomonEncoder struct { + gf *GaloisField + polynomes []*GFPoly + m *sync.Mutex +} + +func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder { + return &ReedSolomonEncoder{ + gf, []*GFPoly{NewGFPoly(gf, []int{1})}, new(sync.Mutex), + } +} + +func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly { + rs.m.Lock() + defer rs.m.Unlock() + + if degree >= len(rs.polynomes) { + last := rs.polynomes[len(rs.polynomes)-1] + for d := len(rs.polynomes); d <= degree; d++ { + next := last.Multiply(NewGFPoly(rs.gf, []int{1, rs.gf.ALogTbl[d-1+rs.gf.Base]})) + rs.polynomes = append(rs.polynomes, next) + last = next + } + } + return rs.polynomes[degree] +} + +func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int { + generator := rs.getPolynomial(eccCount) + info := NewGFPoly(rs.gf, data) + info = info.MultByMonominal(eccCount, 1) + _, remainder := info.Divide(generator) + + result := make([]int, eccCount) + numZero := int(eccCount) - len(remainder.Coefficients) + copy(result[numZero:], remainder.Coefficients) + return result +} diff --git a/vendor/github.com/boombuler/barcode/utils/runeint.go b/vendor/github.com/boombuler/barcode/utils/runeint.go new file mode 100644 index 0000000..d2e5e61 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/runeint.go @@ -0,0 +1,19 @@ +package utils + +// RuneToInt converts a rune between '0' and '9' to an integer between 0 and 9 +// If the rune is outside of this range -1 is returned. +func RuneToInt(r rune) int { + if r >= '0' && r <= '9' { + return int(r - '0') + } + return -1 +} + +// IntToRune converts a digit 0 - 9 to the rune '0' - '9'. If the given int is outside +// of this range 'F' is returned! +func IntToRune(i int) rune { + if i >= 0 && i <= 9 { + return rune(i + '0') + } + return 'F' +} diff --git a/vendor/github.com/boombuler/barcode/utils/runeint_test.go b/vendor/github.com/boombuler/barcode/utils/runeint_test.go new file mode 100644 index 0000000..f1fdbc5 --- /dev/null +++ b/vendor/github.com/boombuler/barcode/utils/runeint_test.go @@ -0,0 +1,24 @@ +package utils + +import "testing" + +func Test_RuneToIntIntToRune(t *testing.T) { + if IntToRune(0) != '0' { + t.Errorf("failed IntToRune(0) returned %d", string(IntToRune(0))) + } + if IntToRune(9) != '9' { + t.Errorf("failed IntToRune(9) returned %d", IntToRune(9)) + } + if IntToRune(10) != 'F' { + t.Errorf("failed IntToRune(10) returned %d", IntToRune(10)) + } + if RuneToInt('0') != 0 { + t.Error("failed RuneToInt('0') returned %d", RuneToInt(0)) + } + if RuneToInt('9') != 9 { + t.Error("failed RuneToInt('9') returned %d", RuneToInt(9)) + } + if RuneToInt('F') != -1 { + t.Error("failed RuneToInt('F') returned %d", RuneToInt('F')) + } +} diff --git a/vendor/github.com/cenkalti/backoff/.gitignore b/vendor/github.com/cenkalti/backoff/.gitignore new file mode 100644 index 0000000..0026861 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/cenkalti/backoff/.travis.yml b/vendor/github.com/cenkalti/backoff/.travis.yml new file mode 100644 index 0000000..1040404 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.3.3 + - tip +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/cenkalti/backoff/LICENSE b/vendor/github.com/cenkalti/backoff/LICENSE new file mode 100644 index 0000000..89b8179 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Cenk Altı + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/cenkalti/backoff/README.md b/vendor/github.com/cenkalti/backoff/README.md new file mode 100644 index 0000000..13b347f --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/README.md @@ -0,0 +1,30 @@ +# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls] + +This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. + +[Exponential backoff][exponential backoff wiki] +is an algorithm that uses feedback to multiplicatively decrease the rate of some process, +in order to gradually find an acceptable rate. +The retries exponentially increase and stop increasing when a certain threshold is met. + +## Usage + +See https://godoc.org/github.com/cenkalti/backoff#pkg-examples + +## Contributing + +* I would like to keep this library as small as possible. +* Please don't send a PR without opening an issue and discussing it first. +* If proposed change is not a common use case, I will probably not accept it. + +[godoc]: https://godoc.org/github.com/cenkalti/backoff +[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png +[travis]: https://travis-ci.org/cenkalti/backoff +[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master +[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master +[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master + +[google-http-java-client]: https://github.com/google/google-http-java-client +[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff + +[advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_ diff --git a/vendor/github.com/cenkalti/backoff/backoff.go b/vendor/github.com/cenkalti/backoff/backoff.go new file mode 100644 index 0000000..2102c5f --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/backoff.go @@ -0,0 +1,66 @@ +// Package backoff implements backoff algorithms for retrying operations. +// +// Use Retry function for retrying operations that may fail. +// If Retry does not meet your needs, +// copy/paste the function into your project and modify as you wish. +// +// There is also Ticker type similar to time.Ticker. +// You can use it if you need to work with channels. +// +// See Examples section below for usage examples. +package backoff + +import "time" + +// BackOff is a backoff policy for retrying an operation. +type BackOff interface { + // NextBackOff returns the duration to wait before retrying the operation, + // or backoff.Stop to indicate that no more retries should be made. + // + // Example usage: + // + // duration := backoff.NextBackOff(); + // if (duration == backoff.Stop) { + // // Do not retry operation. + // } else { + // // Sleep for duration and retry operation. + // } + // + NextBackOff() time.Duration + + // Reset to initial state. + Reset() +} + +// Stop indicates that no more retries should be made for use in NextBackOff(). +const Stop time.Duration = -1 + +// ZeroBackOff is a fixed backoff policy whose backoff time is always zero, +// meaning that the operation is retried immediately without waiting, indefinitely. +type ZeroBackOff struct{} + +func (b *ZeroBackOff) Reset() {} + +func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } + +// StopBackOff is a fixed backoff policy that always returns backoff.Stop for +// NextBackOff(), meaning that the operation should never be retried. +type StopBackOff struct{} + +func (b *StopBackOff) Reset() {} + +func (b *StopBackOff) NextBackOff() time.Duration { return Stop } + +// ConstantBackOff is a backoff policy that always returns the same backoff delay. +// This is in contrast to an exponential backoff policy, +// which returns a delay that grows longer as you call NextBackOff() over and over again. +type ConstantBackOff struct { + Interval time.Duration +} + +func (b *ConstantBackOff) Reset() {} +func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } + +func NewConstantBackOff(d time.Duration) *ConstantBackOff { + return &ConstantBackOff{Interval: d} +} diff --git a/vendor/github.com/cenkalti/backoff/backoff_test.go b/vendor/github.com/cenkalti/backoff/backoff_test.go new file mode 100644 index 0000000..91f27c4 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/backoff_test.go @@ -0,0 +1,27 @@ +package backoff + +import ( + "testing" + "time" +) + +func TestNextBackOffMillis(t *testing.T) { + subtestNextBackOff(t, 0, new(ZeroBackOff)) + subtestNextBackOff(t, Stop, new(StopBackOff)) +} + +func subtestNextBackOff(t *testing.T, expectedValue time.Duration, backOffPolicy BackOff) { + for i := 0; i < 10; i++ { + next := backOffPolicy.NextBackOff() + if next != expectedValue { + t.Errorf("got: %d expected: %d", next, expectedValue) + } + } +} + +func TestConstantBackOff(t *testing.T) { + backoff := NewConstantBackOff(time.Second) + if backoff.NextBackOff() != time.Second { + t.Error("invalid interval") + } +} diff --git a/vendor/github.com/cenkalti/backoff/context.go b/vendor/github.com/cenkalti/backoff/context.go new file mode 100644 index 0000000..5d15709 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/context.go @@ -0,0 +1,60 @@ +package backoff + +import ( + "time" + + "golang.org/x/net/context" +) + +// BackOffContext is a backoff policy that stops retrying after the context +// is canceled. +type BackOffContext interface { + BackOff + Context() context.Context +} + +type backOffContext struct { + BackOff + ctx context.Context +} + +// WithContext returns a BackOffContext with context ctx +// +// ctx must not be nil +func WithContext(b BackOff, ctx context.Context) BackOffContext { + if ctx == nil { + panic("nil context") + } + + if b, ok := b.(*backOffContext); ok { + return &backOffContext{ + BackOff: b.BackOff, + ctx: ctx, + } + } + + return &backOffContext{ + BackOff: b, + ctx: ctx, + } +} + +func ensureContext(b BackOff) BackOffContext { + if cb, ok := b.(BackOffContext); ok { + return cb + } + return WithContext(b, context.Background()) +} + +func (b *backOffContext) Context() context.Context { + return b.ctx +} + +func (b *backOffContext) NextBackOff() time.Duration { + select { + case <-b.Context().Done(): + return Stop + default: + return b.BackOff.NextBackOff() + } +} diff --git a/vendor/github.com/cenkalti/backoff/context_test.go b/vendor/github.com/cenkalti/backoff/context_test.go new file mode 100644 index 0000000..993fa61 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/context_test.go @@ -0,0 +1,26 @@ +package backoff + +import ( + "testing" + "time" + + "golang.org/x/net/context" +) + +func TestContext(t *testing.T) { + b := NewConstantBackOff(time.Millisecond) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cb := WithContext(b, ctx) + + if cb.Context() != ctx { + t.Error("invalid context") + } + + cancel() + + if cb.NextBackOff() != Stop { + t.Error("invalid next back off") + } +} diff --git a/vendor/github.com/cenkalti/backoff/example_test.go b/vendor/github.com/cenkalti/backoff/example_test.go new file mode 100644 index 0000000..d97a8db --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/example_test.go @@ -0,0 +1,73 @@ +package backoff + +import ( + "log" + + "golang.org/x/net/context" +) + +func ExampleRetry() { + // An operation that may fail. + operation := func() error { + return nil // or an error + } + + err := Retry(operation, NewExponentialBackOff()) + if err != nil { + // Handle error. + return + } + + // Operation is successful. +} + +func ExampleRetryContext() { + // A context + ctx := context.Background() + + // An operation that may fail. + operation := func() error { + return nil // or an error + } + + b := WithContext(NewExponentialBackOff(), ctx) + + err := Retry(operation, b) + if err != nil { + // Handle error. + return + } + + // Operation is successful. +} + +func ExampleTicker() { + // An operation that may fail. + operation := func() error { + return nil // or an error + } + + ticker := NewTicker(NewExponentialBackOff()) + + var err error + + // Ticks will continue to arrive when the previous operation is still running, + // so operations that take a while to fail could run in quick succession. + for _ = range ticker.C { + if err = operation(); err != nil { + log.Println(err, "will retry...") + continue + } + + ticker.Stop() + break + } + + if err != nil { + // Operation has failed. + return + } + + // Operation is successful. + return +} diff --git a/vendor/github.com/cenkalti/backoff/exponential.go b/vendor/github.com/cenkalti/backoff/exponential.go new file mode 100644 index 0000000..9a6addf --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/exponential.go @@ -0,0 +1,156 @@ +package backoff + +import ( + "math/rand" + "time" +) + +/* +ExponentialBackOff is a backoff implementation that increases the backoff +period for each retry attempt using a randomization function that grows exponentially. + +NextBackOff() is calculated using the following formula: + + randomized interval = + RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) + +In other words NextBackOff() will range between the randomization factor +percentage below and above the retry interval. + +For example, given the following parameters: + + RetryInterval = 2 + RandomizationFactor = 0.5 + Multiplier = 2 + +the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, +multiplied by the exponential, that is, between 2 and 6 seconds. + +Note: MaxInterval caps the RetryInterval and not the randomized interval. + +If the time elapsed since an ExponentialBackOff instance is created goes past the +MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop. + +The elapsed time can be reset by calling Reset(). + +Example: Given the following default arguments, for 10 tries the sequence will be, +and assuming we go over the MaxElapsedTime on the 10th try: + + Request # RetryInterval (seconds) Randomized Interval (seconds) + + 1 0.5 [0.25, 0.75] + 2 0.75 [0.375, 1.125] + 3 1.125 [0.562, 1.687] + 4 1.687 [0.8435, 2.53] + 5 2.53 [1.265, 3.795] + 6 3.795 [1.897, 5.692] + 7 5.692 [2.846, 8.538] + 8 8.538 [4.269, 12.807] + 9 12.807 [6.403, 19.210] + 10 19.210 backoff.Stop + +Note: Implementation is not thread-safe. +*/ +type ExponentialBackOff struct { + InitialInterval time.Duration + RandomizationFactor float64 + Multiplier float64 + MaxInterval time.Duration + // After MaxElapsedTime the ExponentialBackOff stops. + // It never stops if MaxElapsedTime == 0. + MaxElapsedTime time.Duration + Clock Clock + + currentInterval time.Duration + startTime time.Time + random *rand.Rand +} + +// Clock is an interface that returns current time for BackOff. +type Clock interface { + Now() time.Time +} + +// Default values for ExponentialBackOff. +const ( + DefaultInitialInterval = 500 * time.Millisecond + DefaultRandomizationFactor = 0.5 + DefaultMultiplier = 1.5 + DefaultMaxInterval = 60 * time.Second + DefaultMaxElapsedTime = 15 * time.Minute +) + +// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. +func NewExponentialBackOff() *ExponentialBackOff { + b := &ExponentialBackOff{ + InitialInterval: DefaultInitialInterval, + RandomizationFactor: DefaultRandomizationFactor, + Multiplier: DefaultMultiplier, + MaxInterval: DefaultMaxInterval, + MaxElapsedTime: DefaultMaxElapsedTime, + Clock: SystemClock, + random: rand.New(rand.NewSource(time.Now().UnixNano())), + } + b.Reset() + return b +} + +type systemClock struct{} + +func (t systemClock) Now() time.Time { + return time.Now() +} + +// SystemClock implements Clock interface that uses time.Now(). +var SystemClock = systemClock{} + +// Reset the interval back to the initial retry interval and restarts the timer. +func (b *ExponentialBackOff) Reset() { + b.currentInterval = b.InitialInterval + b.startTime = b.Clock.Now() +} + +// NextBackOff calculates the next backoff interval using the formula: +// Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval) +func (b *ExponentialBackOff) NextBackOff() time.Duration { + // Make sure we have not gone over the maximum elapsed time. + if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime { + return Stop + } + defer b.incrementCurrentInterval() + if b.random == nil { + b.random = rand.New(rand.NewSource(time.Now().UnixNano())) + } + return getRandomValueFromInterval(b.RandomizationFactor, b.random.Float64(), b.currentInterval) +} + +// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance +// is created and is reset when Reset() is called. +// +// The elapsed time is computed using time.Now().UnixNano(). +func (b *ExponentialBackOff) GetElapsedTime() time.Duration { + return b.Clock.Now().Sub(b.startTime) +} + +// Increments the current interval by multiplying it with the multiplier. +func (b *ExponentialBackOff) incrementCurrentInterval() { + // Check for overflow, if overflow is detected set the current interval to the max interval. + if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { + b.currentInterval = b.MaxInterval + } else { + b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) + } +} + +// Returns a random value from the following interval: +// [randomizationFactor * currentInterval, randomizationFactor * currentInterval]. +func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { + var delta = randomizationFactor * float64(currentInterval) + var minInterval = float64(currentInterval) - delta + var maxInterval = float64(currentInterval) + delta + + // Get a random value from the range [minInterval, maxInterval]. + // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then + // we want a 33% chance for selecting either 1, 2 or 3. + return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) +} diff --git a/vendor/github.com/cenkalti/backoff/exponential_test.go b/vendor/github.com/cenkalti/backoff/exponential_test.go new file mode 100644 index 0000000..11b95e4 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/exponential_test.go @@ -0,0 +1,108 @@ +package backoff + +import ( + "math" + "testing" + "time" +) + +func TestBackOff(t *testing.T) { + var ( + testInitialInterval = 500 * time.Millisecond + testRandomizationFactor = 0.1 + testMultiplier = 2.0 + testMaxInterval = 5 * time.Second + testMaxElapsedTime = 15 * time.Minute + ) + + exp := NewExponentialBackOff() + exp.InitialInterval = testInitialInterval + exp.RandomizationFactor = testRandomizationFactor + exp.Multiplier = testMultiplier + exp.MaxInterval = testMaxInterval + exp.MaxElapsedTime = testMaxElapsedTime + exp.Reset() + + var expectedResults = []time.Duration{500, 1000, 2000, 4000, 5000, 5000, 5000, 5000, 5000, 5000} + for i, d := range expectedResults { + expectedResults[i] = d * time.Millisecond + } + + for _, expected := range expectedResults { + assertEquals(t, expected, exp.currentInterval) + // Assert that the next backoff falls in the expected range. + var minInterval = expected - time.Duration(testRandomizationFactor*float64(expected)) + var maxInterval = expected + time.Duration(testRandomizationFactor*float64(expected)) + var actualInterval = exp.NextBackOff() + if !(minInterval <= actualInterval && actualInterval <= maxInterval) { + t.Error("error") + } + } +} + +func TestGetRandomizedInterval(t *testing.T) { + // 33% chance of being 1. + assertEquals(t, 1, getRandomValueFromInterval(0.5, 0, 2)) + assertEquals(t, 1, getRandomValueFromInterval(0.5, 0.33, 2)) + // 33% chance of being 2. + assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.34, 2)) + assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.66, 2)) + // 33% chance of being 3. + assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.67, 2)) + assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.99, 2)) +} + +type TestClock struct { + i time.Duration + start time.Time +} + +func (c *TestClock) Now() time.Time { + t := c.start.Add(c.i) + c.i += time.Second + return t +} + +func TestGetElapsedTime(t *testing.T) { + var exp = NewExponentialBackOff() + exp.Clock = &TestClock{} + exp.Reset() + + var elapsedTime = exp.GetElapsedTime() + if elapsedTime != time.Second { + t.Errorf("elapsedTime=%d", elapsedTime) + } +} + +func TestMaxElapsedTime(t *testing.T) { + var exp = NewExponentialBackOff() + exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)} + // Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater + // than the max elapsed time. + exp.startTime = time.Time{} + assertEquals(t, Stop, exp.NextBackOff()) +} + +func TestBackOffOverflow(t *testing.T) { + var ( + testInitialInterval time.Duration = math.MaxInt64 / 2 + testMaxInterval time.Duration = math.MaxInt64 + testMultiplier = 2.1 + ) + + exp := NewExponentialBackOff() + exp.InitialInterval = testInitialInterval + exp.Multiplier = testMultiplier + exp.MaxInterval = testMaxInterval + exp.Reset() + + exp.NextBackOff() + // Assert that when an overflow is possible the current varerval time.Duration is set to the max varerval time.Duration . + assertEquals(t, testMaxInterval, exp.currentInterval) +} + +func assertEquals(t *testing.T, expected, value time.Duration) { + if expected != value { + t.Errorf("got: %d, expected: %d", value, expected) + } +} diff --git a/vendor/github.com/cenkalti/backoff/retry.go b/vendor/github.com/cenkalti/backoff/retry.go new file mode 100644 index 0000000..5dbd825 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/retry.go @@ -0,0 +1,78 @@ +package backoff + +import "time" + +// An Operation is executing by Retry() or RetryNotify(). +// The operation will be retried using a backoff policy if it returns an error. +type Operation func() error + +// Notify is a notify-on-error function. It receives an operation error and +// backoff delay if the operation failed (with an error). +// +// NOTE that if the backoff policy stated to stop retrying, +// the notify function isn't called. +type Notify func(error, time.Duration) + +// Retry the operation o until it does not return error or BackOff stops. +// o is guaranteed to be run at least once. +// It is the caller's responsibility to reset b after Retry returns. +// +// If o returns a *PermanentError, the operation is not retried, and the +// wrapped error is returned. +// +// Retry sleeps the goroutine for the duration returned by BackOff after a +// failed operation returns. +func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) } + +// RetryNotify calls notify function with the error and wait duration +// for each failed attempt before sleep. +func RetryNotify(operation Operation, b BackOff, notify Notify) error { + var err error + var next time.Duration + + cb := ensureContext(b) + + b.Reset() + for { + if err = operation(); err == nil { + return nil + } + + if permanent, ok := err.(*PermanentError); ok { + return permanent.Err + } + + if next = b.NextBackOff(); next == Stop { + return err + } + + if notify != nil { + notify(err, next) + } + + t := time.NewTimer(next) + + select { + case <-cb.Context().Done(): + t.Stop() + return err + case <-t.C: + } + } +} + +// PermanentError signals that the operation should not be retried. +type PermanentError struct { + Err error +} + +func (e *PermanentError) Error() string { + return e.Err.Error() +} + +// Permanent wraps the given err in a *PermanentError. +func Permanent(err error) *PermanentError { + return &PermanentError{ + Err: err, + } +} diff --git a/vendor/github.com/cenkalti/backoff/retry_test.go b/vendor/github.com/cenkalti/backoff/retry_test.go new file mode 100644 index 0000000..5af2888 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/retry_test.go @@ -0,0 +1,99 @@ +package backoff + +import ( + "errors" + "fmt" + "log" + "testing" + "time" + + "golang.org/x/net/context" +) + +func TestRetry(t *testing.T) { + const successOn = 3 + var i = 0 + + // This function is successful on "successOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + if i == successOn { + log.Println("OK") + return nil + } + + log.Println("error") + return errors.New("error") + } + + err := Retry(f, NewExponentialBackOff()) + if err != nil { + t.Errorf("unexpected error: %s", err.Error()) + } + if i != successOn { + t.Errorf("invalid number of retries: %d", i) + } +} + +func TestRetryContext(t *testing.T) { + var cancelOn = 3 + var i = 0 + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // This function cancels context on "cancelOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + // cancelling the context in the operation function is not a typical + // use-case, however it allows to get predictable test results. + if i == cancelOn { + cancel() + } + + log.Println("error") + return fmt.Errorf("error (%d)", i) + } + + err := Retry(f, WithContext(NewConstantBackOff(time.Millisecond), ctx)) + if err == nil { + t.Errorf("error is unexpectedly nil") + } + if err.Error() != "error (3)" { + t.Errorf("unexpected error: %s", err.Error()) + } + if i != cancelOn { + t.Errorf("invalid number of retries: %d", i) + } +} + +func TestRetryPermenent(t *testing.T) { + const permanentOn = 3 + var i = 0 + + // This function fails permanently after permanentOn tries + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + if i == permanentOn { + log.Println("permanent error") + return Permanent(errors.New("permanent error")) + } + + log.Println("error") + return errors.New("error") + } + + err := Retry(f, NewExponentialBackOff()) + if err == nil || err.Error() != "permanent error" { + t.Errorf("unexpected error: %s", err) + } + if i != permanentOn { + t.Errorf("invalid number of retries: %d", i) + } +} diff --git a/vendor/github.com/cenkalti/backoff/ticker.go b/vendor/github.com/cenkalti/backoff/ticker.go new file mode 100644 index 0000000..49a9971 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/ticker.go @@ -0,0 +1,81 @@ +package backoff + +import ( + "runtime" + "sync" + "time" +) + +// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. +// +// Ticks will continue to arrive when the previous operation is still running, +// so operations that take a while to fail could run in quick succession. +type Ticker struct { + C <-chan time.Time + c chan time.Time + b BackOffContext + stop chan struct{} + stopOnce sync.Once +} + +// NewTicker returns a new Ticker containing a channel that will send the time at times +// specified by the BackOff argument. Ticker is guaranteed to tick at least once. +// The channel is closed when Stop method is called or BackOff stops. +func NewTicker(b BackOff) *Ticker { + c := make(chan time.Time) + t := &Ticker{ + C: c, + c: c, + b: ensureContext(b), + stop: make(chan struct{}), + } + go t.run() + runtime.SetFinalizer(t, (*Ticker).Stop) + return t +} + +// Stop turns off a ticker. After Stop, no more ticks will be sent. +func (t *Ticker) Stop() { + t.stopOnce.Do(func() { close(t.stop) }) +} + +func (t *Ticker) run() { + c := t.c + defer close(c) + t.b.Reset() + + // Ticker is guaranteed to tick at least once. + afterC := t.send(time.Now()) + + for { + if afterC == nil { + return + } + + select { + case tick := <-afterC: + afterC = t.send(tick) + case <-t.stop: + t.c = nil // Prevent future ticks from being sent to the channel. + return + case <-t.b.Context().Done(): + return + } + } +} + +func (t *Ticker) send(tick time.Time) <-chan time.Time { + select { + case t.c <- tick: + case <-t.stop: + return nil + } + + next := t.b.NextBackOff() + if next == Stop { + t.Stop() + return nil + } + + return time.After(next) +} diff --git a/vendor/github.com/cenkalti/backoff/ticker_test.go b/vendor/github.com/cenkalti/backoff/ticker_test.go new file mode 100644 index 0000000..085828c --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/ticker_test.go @@ -0,0 +1,94 @@ +package backoff + +import ( + "errors" + "fmt" + "log" + "testing" + "time" + + "golang.org/x/net/context" +) + +func TestTicker(t *testing.T) { + const successOn = 3 + var i = 0 + + // This function is successful on "successOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + if i == successOn { + log.Println("OK") + return nil + } + + log.Println("error") + return errors.New("error") + } + + b := NewExponentialBackOff() + ticker := NewTicker(b) + + var err error + for _ = range ticker.C { + if err = f(); err != nil { + t.Log(err) + continue + } + + break + } + if err != nil { + t.Errorf("unexpected error: %s", err.Error()) + } + if i != successOn { + t.Errorf("invalid number of retries: %d", i) + } +} + +func TestTickerContext(t *testing.T) { + const cancelOn = 3 + var i = 0 + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // This function cancels context on "cancelOn" calls. + f := func() error { + i++ + log.Printf("function is called %d. time\n", i) + + // cancelling the context in the operation function is not a typical + // use-case, however it allows to get predictable test results. + if i == cancelOn { + cancel() + } + + log.Println("error") + return fmt.Errorf("error (%d)", i) + } + + b := WithContext(NewConstantBackOff(time.Millisecond), ctx) + ticker := NewTicker(b) + + var err error + for _ = range ticker.C { + if err = f(); err != nil { + t.Log(err) + continue + } + + break + } + if err == nil { + t.Errorf("error is unexpectedly nil") + } + if err.Error() != "error (3)" { + t.Errorf("unexpected error: %s", err.Error()) + } + if i != cancelOn { + t.Errorf("invalid number of retries: %d", i) + } +} diff --git a/vendor/github.com/cenkalti/backoff/tries.go b/vendor/github.com/cenkalti/backoff/tries.go new file mode 100644 index 0000000..d2da730 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/tries.go @@ -0,0 +1,35 @@ +package backoff + +import "time" + +/* +WithMaxTries creates a wrapper around another BackOff, which will +return Stop if NextBackOff() has been called too many times since +the last time Reset() was called + +Note: Implementation is not thread-safe. +*/ +func WithMaxTries(b BackOff, max uint64) BackOff { + return &backOffTries{delegate: b, maxTries: max} +} + +type backOffTries struct { + delegate BackOff + maxTries uint64 + numTries uint64 +} + +func (b *backOffTries) NextBackOff() time.Duration { + if b.maxTries > 0 { + if b.maxTries <= b.numTries { + return Stop + } + b.numTries++ + } + return b.delegate.NextBackOff() +} + +func (b *backOffTries) Reset() { + b.numTries = 0 + b.delegate.Reset() +} diff --git a/vendor/github.com/cenkalti/backoff/tries_test.go b/vendor/github.com/cenkalti/backoff/tries_test.go new file mode 100644 index 0000000..bd10211 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/tries_test.go @@ -0,0 +1,55 @@ +package backoff + +import ( + "math/rand" + "testing" + "time" +) + +func TestMaxTriesHappy(t *testing.T) { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + max := 17 + r.Intn(13) + bo := WithMaxTries(&ZeroBackOff{}, uint64(max)) + + // Load up the tries count, but reset should clear the record + for ix := 0; ix < max/2; ix++ { + bo.NextBackOff() + } + bo.Reset() + + // Now fill the tries count all the way up + for ix := 0; ix < max; ix++ { + d := bo.NextBackOff() + if d == Stop { + t.Errorf("returned Stop on try %d", ix) + } + } + + // We have now called the BackOff max number of times, we expect + // the next result to be Stop, even if we try it multiple times + for ix := 0; ix < 7; ix++ { + d := bo.NextBackOff() + if d != Stop { + t.Error("invalid next back off") + } + } + + // Reset makes it all work again + bo.Reset() + d := bo.NextBackOff() + if d == Stop { + t.Error("returned Stop after reset") + } + +} + +func TestMaxTriesZero(t *testing.T) { + // It might not make sense, but its okay to send a zero + bo := WithMaxTries(&ZeroBackOff{}, uint64(0)) + for ix := 0; ix < 11; ix++ { + d := bo.NextBackOff() + if d == Stop { + t.Errorf("returned Stop on try %d", ix) + } + } +} diff --git a/vendor/github.com/codahale/hdrhistogram/.travis.yml b/vendor/github.com/codahale/hdrhistogram/.travis.yml new file mode 100644 index 0000000..7960fc9 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/.travis.yml @@ -0,0 +1,5 @@ +language: go +go: + - 1.5 + - 1.6 + - tip diff --git a/vendor/github.com/codahale/hdrhistogram/LICENSE b/vendor/github.com/codahale/hdrhistogram/LICENSE new file mode 100644 index 0000000..f9835c2 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Coda Hale + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/codahale/hdrhistogram/README.md b/vendor/github.com/codahale/hdrhistogram/README.md new file mode 100644 index 0000000..614b197 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/README.md @@ -0,0 +1,15 @@ +hdrhistogram +============ + +[![Build Status](https://travis-ci.org/codahale/hdrhistogram.png?branch=master)](https://travis-ci.org/codahale/hdrhistogram) + +A pure Go implementation of the [HDR Histogram](https://github.com/HdrHistogram/HdrHistogram). + +> A Histogram that supports recording and analyzing sampled data value counts +> across a configurable integer value range with configurable value precision +> within the range. Value precision is expressed as the number of significant +> digits in the value recording, and provides control over value quantization +> behavior across the value range and the subsequent value resolution at any +> given level. + +For documentation, check [godoc](http://godoc.org/github.com/codahale/hdrhistogram). diff --git a/vendor/github.com/codahale/hdrhistogram/hdr.go b/vendor/github.com/codahale/hdrhistogram/hdr.go new file mode 100644 index 0000000..c978429 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/hdr.go @@ -0,0 +1,564 @@ +// Package hdrhistogram provides an implementation of Gil Tene's HDR Histogram +// data structure. The HDR Histogram allows for fast and accurate analysis of +// the extreme ranges of data with non-normal distributions, like latency. +package hdrhistogram + +import ( + "fmt" + "math" +) + +// A Bracket is a part of a cumulative distribution. +type Bracket struct { + Quantile float64 + Count, ValueAt int64 +} + +// A Snapshot is an exported view of a Histogram, useful for serializing them. +// A Histogram can be constructed from it by passing it to Import. +type Snapshot struct { + LowestTrackableValue int64 + HighestTrackableValue int64 + SignificantFigures int64 + Counts []int64 +} + +// A Histogram is a lossy data structure used to record the distribution of +// non-normally distributed data (like latency) with a high degree of accuracy +// and a bounded degree of precision. +type Histogram struct { + lowestTrackableValue int64 + highestTrackableValue int64 + unitMagnitude int64 + significantFigures int64 + subBucketHalfCountMagnitude int32 + subBucketHalfCount int32 + subBucketMask int64 + subBucketCount int32 + bucketCount int32 + countsLen int32 + totalCount int64 + counts []int64 +} + +// New returns a new Histogram instance capable of tracking values in the given +// range and with the given amount of precision. +func New(minValue, maxValue int64, sigfigs int) *Histogram { + if sigfigs < 1 || 5 < sigfigs { + panic(fmt.Errorf("sigfigs must be [1,5] (was %d)", sigfigs)) + } + + largestValueWithSingleUnitResolution := 2 * math.Pow10(sigfigs) + subBucketCountMagnitude := int32(math.Ceil(math.Log2(float64(largestValueWithSingleUnitResolution)))) + + subBucketHalfCountMagnitude := subBucketCountMagnitude + if subBucketHalfCountMagnitude < 1 { + subBucketHalfCountMagnitude = 1 + } + subBucketHalfCountMagnitude-- + + unitMagnitude := int32(math.Floor(math.Log2(float64(minValue)))) + if unitMagnitude < 0 { + unitMagnitude = 0 + } + + subBucketCount := int32(math.Pow(2, float64(subBucketHalfCountMagnitude)+1)) + + subBucketHalfCount := subBucketCount / 2 + subBucketMask := int64(subBucketCount-1) << uint(unitMagnitude) + + // determine exponent range needed to support the trackable value with no + // overflow: + smallestUntrackableValue := int64(subBucketCount) << uint(unitMagnitude) + bucketsNeeded := int32(1) + for smallestUntrackableValue < maxValue { + smallestUntrackableValue <<= 1 + bucketsNeeded++ + } + + bucketCount := bucketsNeeded + countsLen := (bucketCount + 1) * (subBucketCount / 2) + + return &Histogram{ + lowestTrackableValue: minValue, + highestTrackableValue: maxValue, + unitMagnitude: int64(unitMagnitude), + significantFigures: int64(sigfigs), + subBucketHalfCountMagnitude: subBucketHalfCountMagnitude, + subBucketHalfCount: subBucketHalfCount, + subBucketMask: subBucketMask, + subBucketCount: subBucketCount, + bucketCount: bucketCount, + countsLen: countsLen, + totalCount: 0, + counts: make([]int64, countsLen), + } +} + +// ByteSize returns an estimate of the amount of memory allocated to the +// histogram in bytes. +// +// N.B.: This does not take into account the overhead for slices, which are +// small, constant, and specific to the compiler version. +func (h *Histogram) ByteSize() int { + return 6*8 + 5*4 + len(h.counts)*8 +} + +// Merge merges the data stored in the given histogram with the receiver, +// returning the number of recorded values which had to be dropped. +func (h *Histogram) Merge(from *Histogram) (dropped int64) { + i := from.rIterator() + for i.next() { + v := i.valueFromIdx + c := i.countAtIdx + + if h.RecordValues(v, c) != nil { + dropped += c + } + } + + return +} + +// TotalCount returns total number of values recorded. +func (h *Histogram) TotalCount() int64 { + return h.totalCount +} + +// Max returns the approximate maximum recorded value. +func (h *Histogram) Max() int64 { + var max int64 + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 { + max = i.highestEquivalentValue + } + } + return h.highestEquivalentValue(max) +} + +// Min returns the approximate minimum recorded value. +func (h *Histogram) Min() int64 { + var min int64 + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 && min == 0 { + min = i.highestEquivalentValue + break + } + } + return h.lowestEquivalentValue(min) +} + +// Mean returns the approximate arithmetic mean of the recorded values. +func (h *Histogram) Mean() float64 { + if h.totalCount == 0 { + return 0 + } + var total int64 + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 { + total += i.countAtIdx * h.medianEquivalentValue(i.valueFromIdx) + } + } + return float64(total) / float64(h.totalCount) +} + +// StdDev returns the approximate standard deviation of the recorded values. +func (h *Histogram) StdDev() float64 { + if h.totalCount == 0 { + return 0 + } + + mean := h.Mean() + geometricDevTotal := 0.0 + + i := h.iterator() + for i.next() { + if i.countAtIdx != 0 { + dev := float64(h.medianEquivalentValue(i.valueFromIdx)) - mean + geometricDevTotal += (dev * dev) * float64(i.countAtIdx) + } + } + + return math.Sqrt(geometricDevTotal / float64(h.totalCount)) +} + +// Reset deletes all recorded values and restores the histogram to its original +// state. +func (h *Histogram) Reset() { + h.totalCount = 0 + for i := range h.counts { + h.counts[i] = 0 + } +} + +// RecordValue records the given value, returning an error if the value is out +// of range. +func (h *Histogram) RecordValue(v int64) error { + return h.RecordValues(v, 1) +} + +// RecordCorrectedValue records the given value, correcting for stalls in the +// recording process. This only works for processes which are recording values +// at an expected interval (e.g., doing jitter analysis). Processes which are +// recording ad-hoc values (e.g., latency for incoming requests) can't take +// advantage of this. +func (h *Histogram) RecordCorrectedValue(v, expectedInterval int64) error { + if err := h.RecordValue(v); err != nil { + return err + } + + if expectedInterval <= 0 || v <= expectedInterval { + return nil + } + + missingValue := v - expectedInterval + for missingValue >= expectedInterval { + if err := h.RecordValue(missingValue); err != nil { + return err + } + missingValue -= expectedInterval + } + + return nil +} + +// RecordValues records n occurrences of the given value, returning an error if +// the value is out of range. +func (h *Histogram) RecordValues(v, n int64) error { + idx := h.countsIndexFor(v) + if idx < 0 || int(h.countsLen) <= idx { + return fmt.Errorf("value %d is too large to be recorded", v) + } + h.counts[idx] += n + h.totalCount += n + + return nil +} + +// ValueAtQuantile returns the recorded value at the given quantile (0..100). +func (h *Histogram) ValueAtQuantile(q float64) int64 { + if q > 100 { + q = 100 + } + + total := int64(0) + countAtPercentile := int64(((q / 100) * float64(h.totalCount)) + 0.5) + + i := h.iterator() + for i.next() { + total += i.countAtIdx + if total >= countAtPercentile { + return h.highestEquivalentValue(i.valueFromIdx) + } + } + + return 0 +} + +// CumulativeDistribution returns an ordered list of brackets of the +// distribution of recorded values. +func (h *Histogram) CumulativeDistribution() []Bracket { + var result []Bracket + + i := h.pIterator(1) + for i.next() { + result = append(result, Bracket{ + Quantile: i.percentile, + Count: i.countToIdx, + ValueAt: i.highestEquivalentValue, + }) + } + + return result +} + +// SignificantFigures returns the significant figures used to create the +// histogram +func (h *Histogram) SignificantFigures() int64 { + return h.significantFigures +} + +// LowestTrackableValue returns the lower bound on values that will be added +// to the histogram +func (h *Histogram) LowestTrackableValue() int64 { + return h.lowestTrackableValue +} + +// HighestTrackableValue returns the upper bound on values that will be added +// to the histogram +func (h *Histogram) HighestTrackableValue() int64 { + return h.highestTrackableValue +} + +// Histogram bar for plotting +type Bar struct { + From, To, Count int64 +} + +// Pretty print as csv for easy plotting +func (b Bar) String() string { + return fmt.Sprintf("%v, %v, %v\n", b.From, b.To, b.Count) +} + +// Distribution returns an ordered list of bars of the +// distribution of recorded values, counts can be normalized to a probability +func (h *Histogram) Distribution() (result []Bar) { + i := h.iterator() + for i.next() { + result = append(result, Bar{ + Count: i.countAtIdx, + From: h.lowestEquivalentValue(i.valueFromIdx), + To: i.highestEquivalentValue, + }) + } + + return result +} + +// Equals returns true if the two Histograms are equivalent, false if not. +func (h *Histogram) Equals(other *Histogram) bool { + switch { + case + h.lowestTrackableValue != other.lowestTrackableValue, + h.highestTrackableValue != other.highestTrackableValue, + h.unitMagnitude != other.unitMagnitude, + h.significantFigures != other.significantFigures, + h.subBucketHalfCountMagnitude != other.subBucketHalfCountMagnitude, + h.subBucketHalfCount != other.subBucketHalfCount, + h.subBucketMask != other.subBucketMask, + h.subBucketCount != other.subBucketCount, + h.bucketCount != other.bucketCount, + h.countsLen != other.countsLen, + h.totalCount != other.totalCount: + return false + default: + for i, c := range h.counts { + if c != other.counts[i] { + return false + } + } + } + return true +} + +// Export returns a snapshot view of the Histogram. This can be later passed to +// Import to construct a new Histogram with the same state. +func (h *Histogram) Export() *Snapshot { + return &Snapshot{ + LowestTrackableValue: h.lowestTrackableValue, + HighestTrackableValue: h.highestTrackableValue, + SignificantFigures: h.significantFigures, + Counts: append([]int64(nil), h.counts...), // copy + } +} + +// Import returns a new Histogram populated from the Snapshot data (which the +// caller must stop accessing). +func Import(s *Snapshot) *Histogram { + h := New(s.LowestTrackableValue, s.HighestTrackableValue, int(s.SignificantFigures)) + h.counts = s.Counts + totalCount := int64(0) + for i := int32(0); i < h.countsLen; i++ { + countAtIndex := h.counts[i] + if countAtIndex > 0 { + totalCount += countAtIndex + } + } + h.totalCount = totalCount + return h +} + +func (h *Histogram) iterator() *iterator { + return &iterator{ + h: h, + subBucketIdx: -1, + } +} + +func (h *Histogram) rIterator() *rIterator { + return &rIterator{ + iterator: iterator{ + h: h, + subBucketIdx: -1, + }, + } +} + +func (h *Histogram) pIterator(ticksPerHalfDistance int32) *pIterator { + return &pIterator{ + iterator: iterator{ + h: h, + subBucketIdx: -1, + }, + ticksPerHalfDistance: ticksPerHalfDistance, + } +} + +func (h *Histogram) sizeOfEquivalentValueRange(v int64) int64 { + bucketIdx := h.getBucketIndex(v) + subBucketIdx := h.getSubBucketIdx(v, bucketIdx) + adjustedBucket := bucketIdx + if subBucketIdx >= h.subBucketCount { + adjustedBucket++ + } + return int64(1) << uint(h.unitMagnitude+int64(adjustedBucket)) +} + +func (h *Histogram) valueFromIndex(bucketIdx, subBucketIdx int32) int64 { + return int64(subBucketIdx) << uint(int64(bucketIdx)+h.unitMagnitude) +} + +func (h *Histogram) lowestEquivalentValue(v int64) int64 { + bucketIdx := h.getBucketIndex(v) + subBucketIdx := h.getSubBucketIdx(v, bucketIdx) + return h.valueFromIndex(bucketIdx, subBucketIdx) +} + +func (h *Histogram) nextNonEquivalentValue(v int64) int64 { + return h.lowestEquivalentValue(v) + h.sizeOfEquivalentValueRange(v) +} + +func (h *Histogram) highestEquivalentValue(v int64) int64 { + return h.nextNonEquivalentValue(v) - 1 +} + +func (h *Histogram) medianEquivalentValue(v int64) int64 { + return h.lowestEquivalentValue(v) + (h.sizeOfEquivalentValueRange(v) >> 1) +} + +func (h *Histogram) getCountAtIndex(bucketIdx, subBucketIdx int32) int64 { + return h.counts[h.countsIndex(bucketIdx, subBucketIdx)] +} + +func (h *Histogram) countsIndex(bucketIdx, subBucketIdx int32) int32 { + bucketBaseIdx := (bucketIdx + 1) << uint(h.subBucketHalfCountMagnitude) + offsetInBucket := subBucketIdx - h.subBucketHalfCount + return bucketBaseIdx + offsetInBucket +} + +func (h *Histogram) getBucketIndex(v int64) int32 { + pow2Ceiling := bitLen(v | h.subBucketMask) + return int32(pow2Ceiling - int64(h.unitMagnitude) - + int64(h.subBucketHalfCountMagnitude+1)) +} + +func (h *Histogram) getSubBucketIdx(v int64, idx int32) int32 { + return int32(v >> uint(int64(idx)+int64(h.unitMagnitude))) +} + +func (h *Histogram) countsIndexFor(v int64) int { + bucketIdx := h.getBucketIndex(v) + subBucketIdx := h.getSubBucketIdx(v, bucketIdx) + return int(h.countsIndex(bucketIdx, subBucketIdx)) +} + +type iterator struct { + h *Histogram + bucketIdx, subBucketIdx int32 + countAtIdx, countToIdx, valueFromIdx int64 + highestEquivalentValue int64 +} + +func (i *iterator) next() bool { + if i.countToIdx >= i.h.totalCount { + return false + } + + // increment bucket + i.subBucketIdx++ + if i.subBucketIdx >= i.h.subBucketCount { + i.subBucketIdx = i.h.subBucketHalfCount + i.bucketIdx++ + } + + if i.bucketIdx >= i.h.bucketCount { + return false + } + + i.countAtIdx = i.h.getCountAtIndex(i.bucketIdx, i.subBucketIdx) + i.countToIdx += i.countAtIdx + i.valueFromIdx = i.h.valueFromIndex(i.bucketIdx, i.subBucketIdx) + i.highestEquivalentValue = i.h.highestEquivalentValue(i.valueFromIdx) + + return true +} + +type rIterator struct { + iterator + countAddedThisStep int64 +} + +func (r *rIterator) next() bool { + for r.iterator.next() { + if r.countAtIdx != 0 { + r.countAddedThisStep = r.countAtIdx + return true + } + } + return false +} + +type pIterator struct { + iterator + seenLastValue bool + ticksPerHalfDistance int32 + percentileToIteratorTo float64 + percentile float64 +} + +func (p *pIterator) next() bool { + if !(p.countToIdx < p.h.totalCount) { + if p.seenLastValue { + return false + } + + p.seenLastValue = true + p.percentile = 100 + + return true + } + + if p.subBucketIdx == -1 && !p.iterator.next() { + return false + } + + var done = false + for !done { + currentPercentile := (100.0 * float64(p.countToIdx)) / float64(p.h.totalCount) + if p.countAtIdx != 0 && p.percentileToIteratorTo <= currentPercentile { + p.percentile = p.percentileToIteratorTo + halfDistance := math.Trunc(math.Pow(2, math.Trunc(math.Log2(100.0/(100.0-p.percentileToIteratorTo)))+1)) + percentileReportingTicks := float64(p.ticksPerHalfDistance) * halfDistance + p.percentileToIteratorTo += 100.0 / percentileReportingTicks + return true + } + done = !p.iterator.next() + } + + return true +} + +func bitLen(x int64) (n int64) { + for ; x >= 0x8000; x >>= 16 { + n += 16 + } + if x >= 0x80 { + x >>= 8 + n += 8 + } + if x >= 0x8 { + x >>= 4 + n += 4 + } + if x >= 0x2 { + x >>= 2 + n += 2 + } + if x >= 0x1 { + n++ + } + return +} diff --git a/vendor/github.com/codahale/hdrhistogram/hdr_test.go b/vendor/github.com/codahale/hdrhistogram/hdr_test.go new file mode 100644 index 0000000..309f0ea --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/hdr_test.go @@ -0,0 +1,388 @@ +package hdrhistogram_test + +import ( + "math" + "reflect" + "testing" + + "github.com/codahale/hdrhistogram" +) + +func TestHighSigFig(t *testing.T) { + input := []int64{ + 459876, 669187, 711612, 816326, 931423, 1033197, 1131895, 2477317, + 3964974, 12718782, + } + + hist := hdrhistogram.New(459876, 12718782, 5) + for _, sample := range input { + hist.RecordValue(sample) + } + + if v, want := hist.ValueAtQuantile(50), int64(1048575); v != want { + t.Errorf("Median was %v, but expected %v", v, want) + } +} + +func TestValueAtQuantile(t *testing.T) { + h := hdrhistogram.New(1, 10000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + data := []struct { + q float64 + v int64 + }{ + {q: 50, v: 500223}, + {q: 75, v: 750079}, + {q: 90, v: 900095}, + {q: 95, v: 950271}, + {q: 99, v: 990207}, + {q: 99.9, v: 999423}, + {q: 99.99, v: 999935}, + } + + for _, d := range data { + if v := h.ValueAtQuantile(d.q); v != d.v { + t.Errorf("P%v was %v, but expected %v", d.q, v, d.v) + } + } +} + +func TestMean(t *testing.T) { + h := hdrhistogram.New(1, 10000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + if v, want := h.Mean(), 500000.013312; v != want { + t.Errorf("Mean was %v, but expected %v", v, want) + } +} + +func TestStdDev(t *testing.T) { + h := hdrhistogram.New(1, 10000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + if v, want := h.StdDev(), 288675.1403682715; v != want { + t.Errorf("StdDev was %v, but expected %v", v, want) + } +} + +func TestTotalCount(t *testing.T) { + h := hdrhistogram.New(1, 10000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + if v, want := h.TotalCount(), int64(i+1); v != want { + t.Errorf("TotalCount was %v, but expected %v", v, want) + } + } +} + +func TestMax(t *testing.T) { + h := hdrhistogram.New(1, 10000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + if v, want := h.Max(), int64(1000447); v != want { + t.Errorf("Max was %v, but expected %v", v, want) + } +} + +func TestReset(t *testing.T) { + h := hdrhistogram.New(1, 10000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + h.Reset() + + if v, want := h.Max(), int64(0); v != want { + t.Errorf("Max was %v, but expected %v", v, want) + } +} + +func TestMerge(t *testing.T) { + h1 := hdrhistogram.New(1, 1000, 3) + h2 := hdrhistogram.New(1, 1000, 3) + + for i := 0; i < 100; i++ { + if err := h1.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + for i := 100; i < 200; i++ { + if err := h2.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + h1.Merge(h2) + + if v, want := h1.ValueAtQuantile(50), int64(99); v != want { + t.Errorf("Median was %v, but expected %v", v, want) + } +} + +func TestMin(t *testing.T) { + h := hdrhistogram.New(1, 10000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + if v, want := h.Min(), int64(0); v != want { + t.Errorf("Min was %v, but expected %v", v, want) + } +} + +func TestByteSize(t *testing.T) { + h := hdrhistogram.New(1, 100000, 3) + + if v, want := h.ByteSize(), 65604; v != want { + t.Errorf("ByteSize was %v, but expected %d", v, want) + } +} + +func TestRecordCorrectedValue(t *testing.T) { + h := hdrhistogram.New(1, 100000, 3) + + if err := h.RecordCorrectedValue(10, 100); err != nil { + t.Fatal(err) + } + + if v, want := h.ValueAtQuantile(75), int64(10); v != want { + t.Errorf("Corrected value was %v, but expected %v", v, want) + } +} + +func TestRecordCorrectedValueStall(t *testing.T) { + h := hdrhistogram.New(1, 100000, 3) + + if err := h.RecordCorrectedValue(1000, 100); err != nil { + t.Fatal(err) + } + + if v, want := h.ValueAtQuantile(75), int64(800); v != want { + t.Errorf("Corrected value was %v, but expected %v", v, want) + } +} + +func TestCumulativeDistribution(t *testing.T) { + h := hdrhistogram.New(1, 100000000, 3) + + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + actual := h.CumulativeDistribution() + expected := []hdrhistogram.Bracket{ + hdrhistogram.Bracket{Quantile: 0, Count: 1, ValueAt: 0}, + hdrhistogram.Bracket{Quantile: 50, Count: 500224, ValueAt: 500223}, + hdrhistogram.Bracket{Quantile: 75, Count: 750080, ValueAt: 750079}, + hdrhistogram.Bracket{Quantile: 87.5, Count: 875008, ValueAt: 875007}, + hdrhistogram.Bracket{Quantile: 93.75, Count: 937984, ValueAt: 937983}, + hdrhistogram.Bracket{Quantile: 96.875, Count: 969216, ValueAt: 969215}, + hdrhistogram.Bracket{Quantile: 98.4375, Count: 984576, ValueAt: 984575}, + hdrhistogram.Bracket{Quantile: 99.21875, Count: 992256, ValueAt: 992255}, + hdrhistogram.Bracket{Quantile: 99.609375, Count: 996352, ValueAt: 996351}, + hdrhistogram.Bracket{Quantile: 99.8046875, Count: 998400, ValueAt: 998399}, + hdrhistogram.Bracket{Quantile: 99.90234375, Count: 999424, ValueAt: 999423}, + hdrhistogram.Bracket{Quantile: 99.951171875, Count: 999936, ValueAt: 999935}, + hdrhistogram.Bracket{Quantile: 99.9755859375, Count: 999936, ValueAt: 999935}, + hdrhistogram.Bracket{Quantile: 99.98779296875, Count: 999936, ValueAt: 999935}, + hdrhistogram.Bracket{Quantile: 99.993896484375, Count: 1000000, ValueAt: 1000447}, + hdrhistogram.Bracket{Quantile: 100, Count: 1000000, ValueAt: 1000447}, + } + + if !reflect.DeepEqual(actual, expected) { + t.Errorf("CF was %#v, but expected %#v", actual, expected) + } +} + +func TestDistribution(t *testing.T) { + h := hdrhistogram.New(8, 1024, 3) + + for i := 0; i < 1024; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + actual := h.Distribution() + if len(actual) != 128 { + t.Errorf("Number of bars seen was %v, expected was 128", len(actual)) + } + for _, b := range actual { + if b.Count != 8 { + t.Errorf("Count per bar seen was %v, expected was 8", b.Count) + } + } +} + +func TestNaN(t *testing.T) { + h := hdrhistogram.New(1, 100000, 3) + if math.IsNaN(h.Mean()) { + t.Error("mean is NaN") + } + if math.IsNaN(h.StdDev()) { + t.Error("stddev is NaN") + } +} + +func TestSignificantFigures(t *testing.T) { + const sigFigs = 4 + h := hdrhistogram.New(1, 10, sigFigs) + if h.SignificantFigures() != sigFigs { + t.Errorf("Significant figures was %v, expected %d", h.SignificantFigures(), sigFigs) + } +} + +func TestLowestTrackableValue(t *testing.T) { + const minVal = 2 + h := hdrhistogram.New(minVal, 10, 3) + if h.LowestTrackableValue() != minVal { + t.Errorf("LowestTrackableValue figures was %v, expected %d", h.LowestTrackableValue(), minVal) + } +} + +func TestHighestTrackableValue(t *testing.T) { + const maxVal = 11 + h := hdrhistogram.New(1, maxVal, 3) + if h.HighestTrackableValue() != maxVal { + t.Errorf("HighestTrackableValue figures was %v, expected %d", h.HighestTrackableValue(), maxVal) + } +} + +func BenchmarkHistogramRecordValue(b *testing.B) { + h := hdrhistogram.New(1, 10000000, 3) + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + b.Fatal(err) + } + } + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + h.RecordValue(100) + } +} + +func BenchmarkNew(b *testing.B) { + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + hdrhistogram.New(1, 120000, 3) // this could track 1ms-2min + } +} + +func TestUnitMagnitudeOverflow(t *testing.T) { + h := hdrhistogram.New(0, 200, 4) + if err := h.RecordValue(11); err != nil { + t.Fatal(err) + } +} + +func TestSubBucketMaskOverflow(t *testing.T) { + hist := hdrhistogram.New(2e7, 1e8, 5) + for _, sample := range [...]int64{1e8, 2e7, 3e7} { + hist.RecordValue(sample) + } + + for q, want := range map[float64]int64{ + 50: 33554431, + 83.33: 33554431, + 83.34: 100663295, + 99: 100663295, + } { + if got := hist.ValueAtQuantile(q); got != want { + t.Errorf("got %d for %fth percentile. want: %d", got, q, want) + } + } +} + +func TestExportImport(t *testing.T) { + min := int64(1) + max := int64(10000000) + sigfigs := 3 + h := hdrhistogram.New(min, max, sigfigs) + for i := 0; i < 1000000; i++ { + if err := h.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + s := h.Export() + + if v := s.LowestTrackableValue; v != min { + t.Errorf("LowestTrackableValue was %v, but expected %v", v, min) + } + + if v := s.HighestTrackableValue; v != max { + t.Errorf("HighestTrackableValue was %v, but expected %v", v, max) + } + + if v := int(s.SignificantFigures); v != sigfigs { + t.Errorf("SignificantFigures was %v, but expected %v", v, sigfigs) + } + + if imported := hdrhistogram.Import(s); !imported.Equals(h) { + t.Error("Expected Histograms to be equivalent") + } + +} + +func TestEquals(t *testing.T) { + h1 := hdrhistogram.New(1, 10000000, 3) + for i := 0; i < 1000000; i++ { + if err := h1.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + h2 := hdrhistogram.New(1, 10000000, 3) + for i := 0; i < 10000; i++ { + if err := h1.RecordValue(int64(i)); err != nil { + t.Fatal(err) + } + } + + if h1.Equals(h2) { + t.Error("Expected Histograms to not be equivalent") + } + + h1.Reset() + h2.Reset() + + if !h1.Equals(h2) { + t.Error("Expected Histograms to be equivalent") + } +} diff --git a/vendor/github.com/codahale/hdrhistogram/window.go b/vendor/github.com/codahale/hdrhistogram/window.go new file mode 100644 index 0000000..dc43612 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/window.go @@ -0,0 +1,45 @@ +package hdrhistogram + +// A WindowedHistogram combines histograms to provide windowed statistics. +type WindowedHistogram struct { + idx int + h []Histogram + m *Histogram + + Current *Histogram +} + +// NewWindowed creates a new WindowedHistogram with N underlying histograms with +// the given parameters. +func NewWindowed(n int, minValue, maxValue int64, sigfigs int) *WindowedHistogram { + w := WindowedHistogram{ + idx: -1, + h: make([]Histogram, n), + m: New(minValue, maxValue, sigfigs), + } + + for i := range w.h { + w.h[i] = *New(minValue, maxValue, sigfigs) + } + w.Rotate() + + return &w +} + +// Merge returns a histogram which includes the recorded values from all the +// sections of the window. +func (w *WindowedHistogram) Merge() *Histogram { + w.m.Reset() + for _, h := range w.h { + w.m.Merge(&h) + } + return w.m +} + +// Rotate resets the oldest histogram and rotates it to be used as the current +// histogram. +func (w *WindowedHistogram) Rotate() { + w.idx++ + w.Current = &w.h[w.idx%len(w.h)] + w.Current.Reset() +} diff --git a/vendor/github.com/codahale/hdrhistogram/window_test.go b/vendor/github.com/codahale/hdrhistogram/window_test.go new file mode 100644 index 0000000..7e78758 --- /dev/null +++ b/vendor/github.com/codahale/hdrhistogram/window_test.go @@ -0,0 +1,64 @@ +package hdrhistogram_test + +import ( + "testing" + + "github.com/codahale/hdrhistogram" +) + +func TestWindowedHistogram(t *testing.T) { + w := hdrhistogram.NewWindowed(2, 1, 1000, 3) + + for i := 0; i < 100; i++ { + w.Current.RecordValue(int64(i)) + } + w.Rotate() + + for i := 100; i < 200; i++ { + w.Current.RecordValue(int64(i)) + } + w.Rotate() + + for i := 200; i < 300; i++ { + w.Current.RecordValue(int64(i)) + } + + if v, want := w.Merge().ValueAtQuantile(50), int64(199); v != want { + t.Errorf("Median was %v, but expected %v", v, want) + } +} + +func BenchmarkWindowedHistogramRecordAndRotate(b *testing.B) { + w := hdrhistogram.NewWindowed(3, 1, 10000000, 3) + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + if err := w.Current.RecordValue(100); err != nil { + b.Fatal(err) + } + + if i%100000 == 1 { + w.Rotate() + } + } +} + +func BenchmarkWindowedHistogramMerge(b *testing.B) { + w := hdrhistogram.NewWindowed(3, 1, 10000000, 3) + for i := 0; i < 10000000; i++ { + if err := w.Current.RecordValue(100); err != nil { + b.Fatal(err) + } + + if i%100000 == 1 { + w.Rotate() + } + } + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + w.Merge() + } +} diff --git a/vendor/github.com/coreos/etcd/.dockerignore b/vendor/github.com/coreos/etcd/.dockerignore new file mode 100644 index 0000000..6b8710a --- /dev/null +++ b/vendor/github.com/coreos/etcd/.dockerignore @@ -0,0 +1 @@ +.git diff --git a/vendor/github.com/coreos/etcd/.gitignore b/vendor/github.com/coreos/etcd/.gitignore new file mode 100644 index 0000000..b3c2d01 --- /dev/null +++ b/vendor/github.com/coreos/etcd/.gitignore @@ -0,0 +1,16 @@ +/agent-* +/coverage +/gopath +/gopath.proto +/go-bindata +/machine* +/bin +.vagrant +*.etcd +/etcd +*.swp +/hack/insta-discovery/.env +*.test +tools/functional-tester/docker/bin +hack/tls-setup/certs +.idea diff --git a/vendor/github.com/coreos/etcd/.godir b/vendor/github.com/coreos/etcd/.godir new file mode 100644 index 0000000..00ff6aa --- /dev/null +++ b/vendor/github.com/coreos/etcd/.godir @@ -0,0 +1 @@ +github.com/coreos/etcd diff --git a/vendor/github.com/coreos/etcd/.header b/vendor/github.com/coreos/etcd/.header new file mode 100644 index 0000000..0446af6 --- /dev/null +++ b/vendor/github.com/coreos/etcd/.header @@ -0,0 +1,13 @@ +// Copyright 2016 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. diff --git a/vendor/github.com/coreos/etcd/.semaphore.sh b/vendor/github.com/coreos/etcd/.semaphore.sh new file mode 100755 index 0000000..d44abee --- /dev/null +++ b/vendor/github.com/coreos/etcd/.semaphore.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +TEST_SUFFIX=$(date +%s | base64 | head -c 15) + +TEST_OPTS="RELEASE_TEST=y INTEGRATION=y PASSES='build unit release integration_e2e functional' MANUAL_VER=v3.2.9" +if [ "$TEST_ARCH" == "386" ]; then + TEST_OPTS="GOARCH=386 PASSES='build unit integration_e2e'" +fi + +docker run \ + --rm \ + --volume=`pwd`:/go/src/github.com/coreos/etcd \ + gcr.io/etcd-development/etcd-test:go1.8.5 \ + /bin/bash -c "${TEST_OPTS} ./test 2>&1 | tee test-${TEST_SUFFIX}.log" + +! egrep "(--- FAIL:|panic: test timed out|appears to have leaked|Too many goroutines)" -B50 -A10 test-${TEST_SUFFIX}.log diff --git a/vendor/github.com/coreos/etcd/.travis.yml b/vendor/github.com/coreos/etcd/.travis.yml new file mode 100644 index 0000000..00f2b81 --- /dev/null +++ b/vendor/github.com/coreos/etcd/.travis.yml @@ -0,0 +1,88 @@ +language: go +go_import_path: github.com/coreos/etcd + +sudo: required + +services: docker + +go: +- 1.8.5 +- tip + +notifications: + on_success: never + on_failure: never + +env: + matrix: + - TARGET=amd64 + - TARGET=amd64-go-tip + - TARGET=darwin-amd64 + - TARGET=windows-amd64 + - TARGET=arm64 + - TARGET=arm + - TARGET=386 + - TARGET=ppc64le + +matrix: + fast_finish: true + allow_failures: + - go: tip + env: TARGET=amd64-go-tip + exclude: + - go: 1.8.5 + env: TARGET=amd64-go-tip + - go: tip + env: TARGET=amd64 + - go: tip + env: TARGET=darwin-amd64 + - go: tip + env: TARGET=windows-amd64 + - go: tip + env: TARGET=arm + - go: tip + env: TARGET=arm64 + - go: tip + env: TARGET=386 + - go: tip + env: TARGET=ppc64le + +before_install: +- docker pull gcr.io/etcd-development/etcd-test:go1.8.5 + +install: +- pushd cmd/etcd && go get -t -v ./... && popd + +script: + - > + case "${TARGET}" in + amd64) + docker run --rm \ + --volume=`pwd`:/go/src/github.com/coreos/etcd gcr.io/etcd-development/etcd-test:go1.8.5 \ + /bin/bash -c "GOARCH=amd64 ./test" + ;; + amd64-go-tip) + GOARCH=amd64 ./test + ;; + darwin-amd64) + docker run --rm \ + --volume=`pwd`:/go/src/github.com/coreos/etcd gcr.io/etcd-development/etcd-test:go1.8.5 \ + /bin/bash -c "GO_BUILD_FLAGS='-a -v' GOOS=darwin GOARCH=amd64 ./build" + ;; + windows-amd64) + docker run --rm \ + --volume=`pwd`:/go/src/github.com/coreos/etcd gcr.io/etcd-development/etcd-test:go1.8.5 \ + /bin/bash -c "GO_BUILD_FLAGS='-a -v' GOOS=windows GOARCH=amd64 ./build" + ;; + 386) + docker run --rm \ + --volume=`pwd`:/go/src/github.com/coreos/etcd gcr.io/etcd-development/etcd-test:go1.8.5 \ + /bin/bash -c "GOARCH=386 PASSES='build unit' ./test" + ;; + *) + # test building out of gopath + docker run --rm \ + --volume=`pwd`:/go/src/github.com/coreos/etcd gcr.io/etcd-development/etcd-test:go1.8.5 \ + /bin/bash -c "GO_BUILD_FLAGS='-a -v' GOARCH='${TARGET}' ./build" + ;; + esac diff --git a/vendor/github.com/coreos/etcd/CONTRIBUTING.md b/vendor/github.com/coreos/etcd/CONTRIBUTING.md new file mode 100644 index 0000000..635f73a --- /dev/null +++ b/vendor/github.com/coreos/etcd/CONTRIBUTING.md @@ -0,0 +1,62 @@ +# How to contribute + +etcd is Apache 2.0 licensed and accepts contributions via GitHub pull requests. This document outlines some of the conventions on commit message formatting, contact points for developers, and other resources to help get contributions into etcd. + +# Email and chat + +- Email: [etcd-dev](https://groups.google.com/forum/?hl=en#!forum/etcd-dev) +- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org + +## Getting started + +- Fork the repository on GitHub +- Read the README.md for build instructions + +## Reporting bugs and creating issues + +Reporting bugs is one of the best ways to contribute. However, a good bug report has some very specific qualities, so please read over our short document on [reporting bugs](https://github.com/coreos/etcd/blob/master/Documentation/reporting_bugs.md) before submitting a bug report. This document might contain links to known issues, another good reason to take a look there before reporting a bug. + +## Contribution flow + +This is a rough outline of what a contributor's workflow looks like: + +- Create a topic branch from where to base the contribution. This is usually master. +- Make commits of logical units. +- Make sure commit messages are in the proper format (see below). +- Push changes in a topic branch to a personal fork of the repository. +- Submit a pull request to coreos/etcd. +- The PR must receive a LGTM from two maintainers found in the MAINTAINERS file. + +Thanks for contributing! + +### Code style + +The coding style suggested by the Golang community is used in etcd. See the [style doc](https://github.com/golang/go/wiki/CodeReviewComments) for details. + +Please follow this style to make etcd easy to review, maintain and develop. + +### Format of the commit message + +We follow a rough convention for commit messages that is designed to answer two +questions: what changed and why. The subject line should feature the what and +the body of the commit should describe the why. + +``` +scripts: add the test-cluster command + +this uses tmux to setup a test cluster that can easily be killed and started for debugging. + +Fixes #38 +``` + +The format can be described more formally as follows: + +``` +: + + + +