From e926896fc72058967b8886ac57a237dc8add91f5 Mon Sep 17 00:00:00 2001 From: Clint Date: Tue, 23 Jun 2020 06:01:39 -0500 Subject: [PATCH] VLT091 plugin testing framework stepwise (#9270) * Resolve merge conflicts and updates from running a test * move testing/_test.go over to legacy * updates * Add core of plugin test framework Stepwise (#9166) * adding stepwise testing, but there are protocol buff error :/ * move file and update sdk/go.mo * update/sync modules * update from other branch * update sdk/go.mod * some cleanups after feedback * remove enviornments from this PR * update vendor * change from running go mod tidy * change from go mod tidy * Update sdk/testing/stepwise/helpers.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * Update sdk/testing/stepwise/helpers.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * change panic to error * Update sdk/testing/stepwise/helpers.go return `nil` and not `err` at the end Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * Defer close() on successful Open of a file * document the re-creation of steps * Update sdk/testing/stepwise/stepwise.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * remove unused BarrierKeys() * Update sdk/testing/stepwise/stepwise.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * updates from feedback * fix return with bad arguments * Rename things: - StepOperation -> Operation - StepwiseEnvironment -> Environment - StepCheckFunc -> AssertionFunc - step.Check -> step.Assert * document the environment interface methods * rename EnvironmentOptions to MountOptions * rename Name to RegistryName * remove ExpectError because it's redundant * minor doc update * Update sdk/testing/stepwise/stepwise.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * add checkShouldRun function * remove redundant return * remove vestigial PreCheck function * add tt.Helper() to makeRequest * minor code formatting and document 1-based index for log output of Steps Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * minor updates * update sdk * use local reference for api, vault dep * Update sdk/testing/stepwise/stepwise.go Co-authored-by: Calvin Leung Huang * Update sdk/testing/stepwise/stepwise.go Co-authored-by: Calvin Leung Huang * cleanup some defer functions * call fatal if environment setup fails, and don't call teardown * defer re-setting client token in makeRequest * Move legacy logicaltest back to testhelpers * update mods and test files with go mod tidy * go mod vendor * remove relative replace directives * restore old logical test location * move declaration to main stepwise file * remove index var and use i+1 * add testing for write, delete paths of makeRequest * update stepwise core testing to do request counting * remove unused methods * Update sdk/testing/stepwise/stepwise.go remove dead line Co-authored-by: Alexander Bezobchuk * Update sdk/testing/stepwise/stepwise.go fix capitalization in code comment Co-authored-by: Alexander Bezobchuk * update code comments for SkipTeardown to clarify its use * update stepwise Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> Co-authored-by: Calvin Leung Huang Co-authored-by: Alexander Bezobchuk --- api/go.mod | 12 +- builtin/logical/mssql/backend_test.go | 2 +- builtin/logical/postgresql/backend_test.go | 2 +- builtin/logical/rabbitmq/backend_test.go | 2 +- builtin/logical/ssh/backend_test.go | 2 +- go.mod | 2 +- go.sum | 2 - helper/mfa/mfa_test.go | 2 +- sdk/go.mod | 46 +- sdk/go.sum | 208 +++++++- sdk/testing/stepwise/helpers.go | 51 ++ sdk/testing/stepwise/stepwise.go | 341 +++++++++++++ sdk/testing/stepwise/stepwise_test.go | 448 ++++++++++++++++++ vendor/github.com/hashicorp/vault/api/go.mod | 12 +- .../vault/sdk/testing/stepwise/helpers.go | 51 ++ .../vault/sdk/testing/stepwise/stepwise.go | 341 +++++++++++++ vendor/modules.txt | 3 +- 17 files changed, 1470 insertions(+), 57 deletions(-) create mode 100644 sdk/testing/stepwise/helpers.go create mode 100644 sdk/testing/stepwise/stepwise.go create mode 100644 sdk/testing/stepwise/stepwise_test.go create mode 100644 vendor/github.com/hashicorp/vault/sdk/testing/stepwise/helpers.go create mode 100644 vendor/github.com/hashicorp/vault/sdk/testing/stepwise/stepwise.go diff --git a/api/go.mod b/api/go.mod index 221548e432..40e8bc7dcd 100644 --- a/api/go.mod +++ b/api/go.mod @@ -5,16 +5,16 @@ go 1.13 replace github.com/hashicorp/vault/sdk => ../sdk require ( - github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 + github.com/go-test/deep v1.0.2 github.com/hashicorp/errwrap v1.0.0 github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-retryablehttp v0.6.2 - github.com/hashicorp/go-rootcerts v1.0.1 + github.com/hashicorp/go-rootcerts v1.0.2 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/vault/sdk v0.1.14-0.20200514144402-4bfac290c352 + github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 github.com/mitchellh/mapstructure v1.2.2 - golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 - golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 - gopkg.in/square/go-jose.v2 v2.3.1 + golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476 + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 + gopkg.in/square/go-jose.v2 v2.4.1 ) diff --git a/builtin/logical/mssql/backend_test.go b/builtin/logical/mssql/backend_test.go index 1c67033115..9813565735 100644 --- a/builtin/logical/mssql/backend_test.go +++ b/builtin/logical/mssql/backend_test.go @@ -8,9 +8,9 @@ import ( "testing" _ "github.com/denisenkom/go-mssqldb" - logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" mssqlhelper "github.com/hashicorp/vault/helper/testhelpers/mssql" "github.com/hashicorp/vault/sdk/logical" + logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" "github.com/mitchellh/mapstructure" ) diff --git a/builtin/logical/postgresql/backend_test.go b/builtin/logical/postgresql/backend_test.go index 739591e93e..8493a73833 100644 --- a/builtin/logical/postgresql/backend_test.go +++ b/builtin/logical/postgresql/backend_test.go @@ -10,9 +10,9 @@ import ( "reflect" "testing" - logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" postgreshelper "github.com/hashicorp/vault/helper/testhelpers/postgresql" "github.com/hashicorp/vault/sdk/logical" + logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" "github.com/lib/pq" "github.com/mitchellh/mapstructure" ) diff --git a/builtin/logical/rabbitmq/backend_test.go b/builtin/logical/rabbitmq/backend_test.go index 90963aca2c..d942c05b8f 100644 --- a/builtin/logical/rabbitmq/backend_test.go +++ b/builtin/logical/rabbitmq/backend_test.go @@ -9,10 +9,10 @@ import ( "testing" "github.com/hashicorp/vault/helper/testhelpers/docker" - logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" "github.com/hashicorp/vault/sdk/helper/base62" "github.com/hashicorp/vault/sdk/helper/jsonutil" "github.com/hashicorp/vault/sdk/logical" + logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" rabbithole "github.com/michaelklishin/rabbit-hole" "github.com/mitchellh/mapstructure" "github.com/ory/dockertest" diff --git a/builtin/logical/ssh/backend_test.go b/builtin/logical/ssh/backend_test.go index eb9f0d2d72..dd136be970 100644 --- a/builtin/logical/ssh/backend_test.go +++ b/builtin/logical/ssh/backend_test.go @@ -19,8 +19,8 @@ import ( "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/helper/testhelpers/docker" - logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" "github.com/hashicorp/vault/sdk/logical" + logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" "github.com/hashicorp/vault/vault" "github.com/mitchellh/mapstructure" "github.com/ory/dockertest" diff --git a/go.mod b/go.mod index eecc69ba2b..63b12dc1b0 100644 --- a/go.mod +++ b/go.mod @@ -92,7 +92,7 @@ require ( github.com/hashicorp/vault-plugin-secrets-mongodbatlas v0.1.2 github.com/hashicorp/vault-plugin-secrets-openldap v0.1.3 github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f - github.com/hashicorp/vault/sdk v0.1.14-0.20200615191832-d4b3c4b29c62 + github.com/hashicorp/vault/sdk v0.1.14-0.20200527182800-ad90e0b39d2f github.com/influxdata/influxdb v0.0.0-20190411212539-d24b7ba8c4c4 github.com/jcmturner/gokrb5/v8 v8.0.0 github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f diff --git a/go.sum b/go.sum index a89a513222..efc658f235 100644 --- a/go.sum +++ b/go.sum @@ -128,7 +128,6 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.27 h1:9gPjZWVDSoQrBO2AvqrWObS6KAZByfEJxQoCYo4ZfK0= github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA= @@ -459,7 +458,6 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= diff --git a/helper/mfa/mfa_test.go b/helper/mfa/mfa_test.go index 85a7d1291d..c39561fbb6 100644 --- a/helper/mfa/mfa_test.go +++ b/helper/mfa/mfa_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" + logicaltest "github.com/hashicorp/vault/sdk/testing/stepwise" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" ) diff --git a/sdk/go.mod b/sdk/go.mod index a4aeba5d46..b59b2601f7 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -3,33 +3,47 @@ module github.com/hashicorp/vault/sdk go 1.13 require ( - github.com/armon/go-metrics v0.3.0 - github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 - github.com/aws/aws-sdk-go v1.25.37 + github.com/armon/go-metrics v0.3.3 + github.com/armon/go-radix v1.0.0 + github.com/aws/aws-sdk-go v1.30.27 + github.com/fatih/color v1.9.0 // indirect github.com/fatih/structs v1.1.0 - github.com/go-ldap/ldap/v3 v3.1.3 - github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 + github.com/frankban/quicktest v1.10.0 // indirect + github.com/go-ldap/ldap/v3 v3.1.10 + github.com/go-test/deep v1.0.2 github.com/golang/protobuf v1.4.2 github.com/golang/snappy v0.0.1 github.com/hashicorp/errwrap v1.0.0 - github.com/hashicorp/go-hclog v0.12.0 - github.com/hashicorp/go-immutable-radix v1.0.0 + github.com/hashicorp/go-cleanhttp v0.5.1 + github.com/hashicorp/go-hclog v0.14.1 + github.com/hashicorp/go-immutable-radix v1.1.0 github.com/hashicorp/go-kms-wrapping/entropy v0.1.0 - github.com/hashicorp/go-multierror v1.0.0 + github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/go-plugin v1.0.1 + github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/hashicorp/go-sockaddr v1.0.2 github.com/hashicorp/go-uuid v1.0.2 - github.com/hashicorp/go-version v1.1.0 - github.com/hashicorp/golang-lru v0.5.1 + github.com/hashicorp/go-version v1.2.0 + github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/hcl v1.0.0 + github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f + github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-colorable v0.1.6 // indirect github.com/mitchellh/copystructure v1.0.0 github.com/mitchellh/go-testing-interface v1.0.0 - github.com/mitchellh/mapstructure v1.2.2 - github.com/pierrec/lz4 v2.0.5+incompatible - github.com/pkg/errors v0.8.1 + github.com/mitchellh/mapstructure v1.3.2 + github.com/mitchellh/reflectwalk v1.0.1 // indirect + github.com/pierrec/lz4 v2.5.2+incompatible + github.com/pkg/errors v0.9.1 github.com/ryanuber/go-glob v1.0.0 - golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 - golang.org/x/sys v0.0.0-20191008105621-543471e840be - google.golang.org/grpc v1.27.0 + golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 + golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect + golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 + golang.org/x/text v0.3.2 // indirect + golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect + google.golang.org/grpc v1.29.1 google.golang.org/protobuf v1.24.0 + gopkg.in/square/go-jose.v2 v2.5.1 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/sdk/go.sum b/sdk/go.sum index 2609adaadb..64b6cbcc50 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -1,46 +1,83 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/go-metrics v0.3.0 h1:B7AQgHi8QSEi4uHu7Sbsga+IJDU+CENgjxoo81vDUqU= github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= +github.com/armon/go-metrics v0.3.3 h1:a9F4rlj7EWWrbj7BYw8J8+x+ZZkJeqzNyRk8hdPF+ro= +github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.25.37 h1:gBtB/F3dophWpsUQKN/Kni+JzYEH2mGHF4hWNtfED1w= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.30.27 h1:9gPjZWVDSoQrBO2AvqrWObS6KAZByfEJxQoCYo4ZfK0= +github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE= +github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/go-asn1-ber/asn1-ber v1.3.1 h1:gvPdv/Hr++TRFCl0UbPFHC54P9N9jgsRPnmnr419Uck= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-ldap/ldap/v3 v3.1.3 h1:RIgdpHXJpsUqUK5WXwKyVsESrGFqo5BRWPk3RR4/ogQ= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8= -github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA7M0wXsI6t3PYulRTMio3SO+eKCM= +github.com/go-ldap/ldap/v3 v3.1.10 h1:7WsKqasmPThNvdl0Q5GPpbTDD/ZD98CfuawrMIuh7qQ= +github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= @@ -51,110 +88,223 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.1.0 h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc= +github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-kms-wrapping/entropy v0.1.0 h1:xuTi5ZwjimfpvpL09jDE71smCBRpnF5xfo871BSX4gs= github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.6.2 h1:bHM2aVXwBtBJWxHtkSrWuI4umABCUczs52eiUS9nSiw= +github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY= +github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= +github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8= +github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= +github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f h1:PYtnlUZzFSZxPcq7mYp5oC9N+BcJ8IKYf6/EG0GHM2Y= +github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221530-14615acda45f/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.2.2 h1:dxe5oCinTXiTIcfgmZecdCzPmAJKd46KsCWc35r0TV4= github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= +github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0 h1:YVIb/fVcOTMSqtqZWSKnHpSLBxu8DKgxq8z6RuBZwqI= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM= +golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476 h1:E7ct1C6/33eOdrGZKMoyntcEvs2dwZnDe30crG5vpYU= +golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -163,16 +313,19 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -183,5 +336,20 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= +gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/sdk/testing/stepwise/helpers.go b/sdk/testing/stepwise/helpers.go new file mode 100644 index 0000000000..ff2f135b79 --- /dev/null +++ b/sdk/testing/stepwise/helpers.go @@ -0,0 +1,51 @@ +package stepwise + +import ( + "bytes" + "crypto/sha256" + "fmt" + "io" + "os" + "os/exec" + "path" + "strings" +) + +const pluginPrefix = "vault-plugin-" + +// CompilePlugin is a helper method to compile a source plugin +// TODO refactor compile plugin input and output to be types +func CompilePlugin(name, pluginName, srcDir, tmpDir string) (string, string, string, error) { + binName := name + if !strings.HasPrefix(binName, pluginPrefix) { + binName = fmt.Sprintf("%s%s", pluginPrefix, binName) + } + binPath := path.Join(tmpDir, binName) + + cmd := exec.Command("go", "build", "-o", binPath, path.Join(srcDir, fmt.Sprintf("cmd/%s/main.go", pluginName))) + cmd.Stdout = &bytes.Buffer{} + + // match the target architecture of the docker container + cmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH=amd64") + err := cmd.Run() + if err != nil { + return "", "", "", err + } + + // calculate sha256 + f, err := os.Open(binPath) + if err != nil { + return "", "", "", err + } + + defer f.Close() + + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + return "", "", "", err + } + + sha256value := fmt.Sprintf("%x", h.Sum(nil)) + + return binName, binPath, sha256value, nil +} diff --git a/sdk/testing/stepwise/stepwise.go b/sdk/testing/stepwise/stepwise.go new file mode 100644 index 0000000000..60791a0819 --- /dev/null +++ b/sdk/testing/stepwise/stepwise.go @@ -0,0 +1,341 @@ +// Package stepwise offers types and functions to enable black-box style tests +// that are executed in defined set of steps. Stepwise utilizes "Environments" which +// setup a running instance of Vault and provide a valid API client to execute +// user defined steps against. +package stepwise + +import ( + "fmt" + "os" + "testing" + + log "github.com/hashicorp/go-hclog" + "github.com/hashicorp/vault/api" + "github.com/hashicorp/vault/sdk/helper/consts" + "github.com/hashicorp/vault/sdk/helper/logging" +) + +// TestEnvVar must be set to a non-empty value for acceptance tests to run. +const TestEnvVar = "VAULT_ACC" + +// Operation defines operations each step could perform. These are +// intentionally redefined from the logical package in the SDK, so users +// consistently use the stepwise package and not a combination of both stepwise +// and logical. +type Operation string + +const ( + WriteOperation Operation = "create" + UpdateOperation = "update" + ReadOperation = "read" + DeleteOperation = "delete" + ListOperation = "list" + HelpOperation = "help" +) + +// Environment is the interface Environments need to implement to be used in +// Case to execute each Step +type Environment interface { + // Setup is responsible for creating the Vault cluster for use in the test + // case. + Setup() error + + // Client returns a configured Vault API client to communicate with the Vault + // cluster created in Setup and managed by this Environment. + Client() (*api.Client, error) + + // Teardown is responsible for destroying any and all infrastructure created + // during Setup or otherwise over the course of executing test cases. + Teardown() error + + // Name returns the name of the environment provider, e.g. Docker, Minikube, + // et.al. + Name() string + + // MountPath returns the path the plugin is mounted at + MountPath() string + + // RootToken returns the root token of the cluster, used for making requests + // as well as administrative tasks + RootToken() string +} + +// PluginType defines the types of plugins supported +// This type re-create constants as a convienence so users don't need to import/use +// the consts package. +type PluginType consts.PluginType + +// These are originally defined in sdk/helper/consts/plugin_types.go +const ( + PluginTypeUnknown PluginType = iota + PluginTypeCredential + PluginTypeDatabase + PluginTypeSecrets +) + +func (p PluginType) String() string { + switch p { + case PluginTypeUnknown: + return "unknown" + case PluginTypeCredential: + return "auth" + case PluginTypeDatabase: + return "database" + case PluginTypeSecrets: + return "secret" + default: + return "unsupported" + } +} + +// MountOptions are a collection of options each step driver should +// support +type MountOptions struct { + // MountPathPrefix is an optional prefix to use when mounting the plugin. If + // omitted the mount path will default to the PluginName with a random suffix. + MountPathPrefix string + + // Name is used to register the plugin. This can be arbitrary but should be a + // reasonable value. For an example, if the plugin in test is a secret backend + // that generates UUIDs with the name "vault-plugin-secrets-uuid", then "uuid" + // or "test-uuid" would be reasonable. The name is used for lookups in the + // catalog. See "name" in the "Register Plugin" endpoint docs: + // - https://www.vaultproject.io/api-docs/system/plugins-catalog#register-plugin + RegistryName string + + // PluginType is the optional type of plugin. See PluginType const defined + // above + PluginType PluginType + + // PluginName represents the name of the plugin that gets compiled. In the + // standard plugin project file layout, it represents the folder under the + // cmd/ folder. In the below example UUID project, the PluginName would be + // "uuid": + // + // vault-plugin-secrets-uuid/ + // - backend.go + // - cmd/ + // ----uuid/ + // ------main.go + // - path_generate.go + // + PluginName string +} + +// Step represents a single step of a test Case +type Step struct { + // Operation defines what action is being taken in this step; write, read, + // delete, et. al. + Operation Operation + + // Path is the localized request path. The mount prefix, namespace, and + // optionally "auth" will be automatically added. + Path string + + // Arguments to pass in the request. These arguments represent payloads sent + // to the API. + Data map[string]interface{} + + // Assert is a function that is called after this step is executed in order to + // test that the step executed successfully. If this is not set, then the next + // step will be called + Assert AssertionFunc + + // Unauthenticated will make the request unauthenticated. + Unauthenticated bool +} + +// AssertionFunc is the callback used for Assert in Steps. +type AssertionFunc func(*api.Secret, error) error + +// Case represents a scenario we want to test which involves a series of +// steps to be followed sequentially, evaluating the results after each step. +type Case struct { + // Environment is used to setup the Vault instance and provide the client that + // will be used to drive the tests + Environment Environment + + // Steps are the set of operations that are run for this test case. During + // execution each step will be logged to output with a 1-based index as it is + // ran, with the first step logged as step '1' and not step '0'. + Steps []Step + + // SkipTeardown allows the Environment TeardownFunc to be skipped, leaving any + // infrastructure created after the test exists. This is useful for debugging + // during plugin development to examine the state of the Vault cluster after a + // test runs. Depending on the Environment used this could incur costs the + // user is responsible for. + SkipTeardown bool +} + +// Run performs an acceptance test on a backend with the given test case. +// +// Tests are not run unless an environmental variable "VAULT_ACC" is +// set to some non-empty value. This is to avoid test cases surprising +// a user by creating real resources. +// +// Tests will fail unless the verbose flag (`go test -v`, or explicitly +// the "-test.v" flag) is set. Because some acceptance tests take quite +// long, we require the verbose flag so users are able to see progress +// output. +func Run(tt TestT, c Case) { + tt.Helper() + // We only run acceptance tests if an env var is set because they're + // slow and generally require some outside configuration. + checkShouldRun(tt) + + if c.Environment == nil { + tt.Fatal("nil driver in acceptance test") + // return here only used during testing when using mockT type, otherwise + // Fatal will exit + return + } + + logger := logging.NewVaultLogger(log.Trace) + + if err := c.Environment.Setup(); err != nil { + tt.Fatal(err) + } + + defer func() { + if c.SkipTeardown { + logger.Info("driver Teardown skipped") + return + } + if err := c.Environment.Teardown(); err != nil { + logger.Error("error in driver teardown:", "error", err) + } + }() + + // retrieve the root client from the Environment. If this returns an error, + // fail immediately + rootClient, err := c.Environment.Client() + if err != nil { + tt.Fatal(err) + } + + // Trap the rootToken so that we can preform revocation or other tasks in the + // event any steps remove the token during testing. + rootToken := c.Environment.RootToken() + + // Defer revocation of any secrets created. We intentionally enclose the + // responses slice so in the event of a fatal error during test evaluation, we + // are still able to revoke any leases/secrets created + var responses []*api.Secret + defer func() { + // restore root token for admin tasks + rootClient.SetToken(rootToken) + // failedRevokes tracks any errors we get when attempting to revoke a lease + // to log to users at the end of the test. + var failedRevokes []*api.Secret + for _, secret := range responses { + if secret.LeaseID == "" { + continue + } + + if err := rootClient.Sys().Revoke(secret.LeaseID); err != nil { + tt.Error(fmt.Errorf("error revoking lease: %w", err)) + failedRevokes = append(failedRevokes, secret) + continue + } + } + + // If we have any failed revokes, log it. + if len(failedRevokes) > 0 { + for _, s := range failedRevokes { + tt.Error(fmt.Sprintf( + "WARNING: Revoking the following secret failed. It may\n"+ + "still exist. Please verify:\n\n%#v", + s)) + } + } + }() + + stepCount := len(c.Steps) + for i, step := range c.Steps { + if logger.IsWarn() { + // range is zero based, so add 1 for a human friendly output of steps. + progress := fmt.Sprintf("%d/%d", i+1, stepCount) + logger.Warn("Executing test step", "step_number", progress) + } + + // reset token in case it was cleared + client, err := rootClient.Clone() + if err != nil { + tt.Fatal(err) + } + + // TODO: support creating tokens with policies listed in each Step + client.SetToken(rootToken) + + resp, respErr := makeRequest(tt, c.Environment, step) + if resp != nil { + responses = append(responses, resp) + } + + // Run the associated AssertionFunc, if any. If an error was expected it is + // sent to the Assert function to validate. + if step.Assert != nil { + if err := step.Assert(resp, respErr); err != nil { + tt.Error(fmt.Errorf("failed step %d: %w", i+1, err)) + } + } + } +} + +func makeRequest(tt TestT, env Environment, step Step) (*api.Secret, error) { + tt.Helper() + client, err := env.Client() + if err != nil { + return nil, err + } + + if step.Unauthenticated { + token := client.Token() + client.ClearToken() + // restore the client token after this request completes + defer func() { + client.SetToken(token) + }() + } + + path := fmt.Sprintf("%s/%s", env.MountPath(), step.Path) + switch step.Operation { + case WriteOperation, UpdateOperation: + return client.Logical().Write(path, step.Data) + case ReadOperation: + // TODO support ReadWithData + return client.Logical().Read(path) + case ListOperation: + return client.Logical().List(path) + case DeleteOperation: + return client.Logical().Delete(path) + default: + return nil, fmt.Errorf("invalid operation: %s", step.Operation) + } +} + +func checkShouldRun(tt TestT) { + tt.Helper() + if os.Getenv(TestEnvVar) == "" { + tt.Skip(fmt.Sprintf( + "Acceptance tests skipped unless env '%s' set", + TestEnvVar)) + return + } + + // We require verbose mode so that the user knows what is going on. + if !testing.Verbose() { + tt.Fatal("Acceptance tests must be run with the -v flag on tests") + } +} + +// TestT is the interface used to handle the test lifecycle of a test. +// +// Users should just use a *testing.T object, which implements this. +type TestT interface { + Error(args ...interface{}) + Fatal(args ...interface{}) + Skip(args ...interface{}) + Helper() +} diff --git a/sdk/testing/stepwise/stepwise_test.go b/sdk/testing/stepwise/stepwise_test.go new file mode 100644 index 0000000000..799d041fdd --- /dev/null +++ b/sdk/testing/stepwise/stepwise_test.go @@ -0,0 +1,448 @@ +package stepwise + +import ( + "errors" + "fmt" + "net/http" + "net/http/httptest" + "os" + "reflect" + "sync" + "testing" + "time" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/vault/api" + "github.com/hashicorp/vault/sdk/helper/jsonutil" +) + +// testTesting is used for testing the legacy testing framework +var testTesting = false + +type testRun struct { + expectedTestT *mockT + environment *mockEnvironment + steps []Step + skipTeardown bool + requests *requestCounts +} + +// TestStepwise_Run_SkipIfNotAcc tests if the Stepwise Run function skips tests +// if the VAULT_ACC environment variable is not set. This test is seperate from +// the table tests due to the unsetting/re-setting of the environment variable, +// which is assumed/needed for all other tests. +func TestStepwise_Run_SkipIfNotAcc(t *testing.T) { + if err := os.Setenv(TestEnvVar, ""); err != nil { + t.Fatalf("err: %s", err) + } + defer os.Setenv(TestEnvVar, "1") + skipCase := Case{ + Environment: new(mockEnvironment), + Steps: []Step{Step{}}, + } + + expected := mockT{ + SkipCalled: true, + } + + testT := new(mockT) + Run(testT, skipCase) + + if testT.SkipCalled != expected.SkipCalled { + t.Fatalf("expected SkipCalled (%t), got (%t)", expected.SkipCalled, testT.SkipCalled) + } +} + +func TestStepwise_Run_Basic(t *testing.T) { + testRuns := map[string]testRun{ + "basic_list": { + steps: []Step{ + stepFunc("keys", ListOperation, false), + }, + environment: new(mockEnvironment), + requests: &requestCounts{ + listRequests: 1, + }, + }, + "basic_list_read": { + steps: []Step{ + stepFunc("keys", ListOperation, false), + stepFunc("keys/name", ReadOperation, false), + }, + environment: new(mockEnvironment), + requests: &requestCounts{ + listRequests: 1, + readRequests: 1, + revokeRequests: 1, + }, + }, + "basic_unauth": { + steps: []Step{ + stepFuncWithoutAuth("keys", ListOperation, true), + }, + expectedTestT: &mockT{ + ErrorCalled: true, + }, + environment: new(mockEnvironment), + }, + "error": { + steps: []Step{ + stepFunc("keys", ListOperation, false), + stepFunc("keys/something", ReadOperation, true), + }, + expectedTestT: &mockT{ + ErrorCalled: true, + }, + environment: new(mockEnvironment), + requests: &requestCounts{ + listRequests: 1, + }, + }, + "nil-env": { + expectedTestT: &mockT{ + FatalCalled: true, + }, + steps: []Step{ + stepFunc("keys", ListOperation, false), + }, + }, + "skipTeardown": { + steps: []Step{ + stepFunc("keys", ListOperation, false), + stepFunc("keys/name", ReadOperation, false), + stepFunc("keys/name", ReadOperation, false), + stepFunc("keys/name", DeleteOperation, false), + }, + skipTeardown: true, + environment: new(mockEnvironment), + requests: &requestCounts{ + listRequests: 1, + readRequests: 2, + revokeRequests: 2, + deleteRequests: 1, + }, + }, + } + + for name, tr := range testRuns { + t.Run(name, func(t *testing.T) { + testT := new(mockT) + expectedT := tr.expectedTestT + if expectedT == nil { + expectedT = new(mockT) + } + testCase := Case{ + Steps: tr.steps, + SkipTeardown: tr.skipTeardown, + } + + if tr.environment != nil { + testCase.Environment = tr.environment + } + + Run(testT, testCase) + + if tr.environment == nil && !testT.FatalCalled { + t.Fatal("expected FatalCalled with nil environment, but wasn't") + } + + if tr.environment != nil { + if tr.skipTeardown && tr.environment.teardownCalled { + t.Fatal("SkipTeardown is true, but Teardown was called") + } + if !tr.skipTeardown && !tr.environment.teardownCalled { + t.Fatal("SkipTeardown is false, but Teardown was not called") + } + } + + if expectedT.ErrorCalled != testT.ErrorCalled { + t.Fatalf("expected ErrorCalled (%t), got (%t)", expectedT.ErrorCalled, testT.ErrorCalled) + } + if tr.requests != nil { + if !reflect.DeepEqual(*tr.requests, tr.environment.requests) { + t.Fatalf("request counts do not match: %#v / %#v", tr.requests, tr.environment.requests) + } + } + }) + } +} + +type requestCounts struct { + writeRequests int + readRequests int + deleteRequests int + revokeRequests int + listRequests int +} + +func TestStepwise_makeRequest(t *testing.T) { + me := new(mockEnvironment) + me.Setup() + testT := new(mockT) + + type testRequest struct { + Operation Operation + Path string + ExpectedRequestID string + ExpectErr bool + UnAuth bool + } + testRequests := map[string]testRequest{ + "list": { + Operation: ListOperation, + Path: "keys", + ExpectedRequestID: "list-request", + }, + "read": { + Operation: ReadOperation, + Path: "keys/name", + ExpectedRequestID: "read-request", + }, + "write": { + Operation: WriteOperation, + Path: "keys/name", + ExpectedRequestID: "write-request", + }, + "update": { + Operation: UpdateOperation, + Path: "keys/name", + ExpectedRequestID: "write-request", + }, + "update_unauth": { + Operation: UpdateOperation, + Path: "keys/name", + UnAuth: true, + ExpectErr: true, + }, + "delete": { + Operation: DeleteOperation, + Path: "keys/name", + ExpectedRequestID: "delete-request", + }, + "error": { + Operation: ReadOperation, + Path: "error", + ExpectErr: true, + }, + } + + for name, tc := range testRequests { + t.Run(name, func(t *testing.T) { + step := Step{ + Operation: tc.Operation, + Path: tc.Path, + } + + if tc.UnAuth { + step.Unauthenticated = tc.UnAuth + } + + secret, err := makeRequest(testT, me, step) + if err != nil && !tc.ExpectErr { + t.Fatalf("unexpected error: %s", err) + } + if err == nil && tc.ExpectErr { + t.Fatal("expected error but got none:") + } + + if err != nil && tc.ExpectErr { + return + } + if secret.RequestID != tc.ExpectedRequestID { + t.Fatalf("expected (%s), got (%s)", tc.ExpectedRequestID, secret.RequestID) + } + }) + } +} + +type mockEnvironment struct { + ts *httptest.Server + client *api.Client + l sync.Mutex + + teardownCalled bool + requests requestCounts +} + +// Setup creates the mock environment, establishing a test HTTP server +func (m *mockEnvironment) Setup() error { + mux := http.NewServeMux() + // LIST + mux.HandleFunc("/v1/test/keys", func(w http.ResponseWriter, req *http.Request) { + checkAuth(w, req) + switch req.Method { + case "GET": + m.requests.listRequests++ + respondCommon("list", true, w, req) + default: + w.WriteHeader(http.StatusBadRequest) + } + }) + // lease revoke + mux.HandleFunc("/v1/sys/leases/revoke", func(w http.ResponseWriter, req *http.Request) { + checkAuth(w, req) + m.requests.revokeRequests++ + w.WriteHeader(http.StatusOK) + }) + // READ, DELETE, WRITE + mux.HandleFunc("/v1/test/keys/name", func(w http.ResponseWriter, req *http.Request) { + checkAuth(w, req) + var method string + // indicate if the common response should include a lease id + var excludeLease bool + switch req.Method { + case "GET": + m.requests.readRequests++ + method = "read" + case "POST": + case "PUT": + m.requests.writeRequests++ + method = "write" + case "DELETE": + m.requests.deleteRequests++ + excludeLease = true + method = "delete" + default: + w.WriteHeader(http.StatusBadRequest) + } + respondCommon(method, excludeLease, w, req) + }) + // fall through that rejects any other url than "/" + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + if req.URL.Path != "/" { + http.NotFound(w, req) + return + } + fmt.Fprintf(w, "{}") + }) + m.ts = httptest.NewServer(mux) + + return nil +} + +// respondCommon returns a mock secret with a request ID that matches the +// request method that was used to invoke it. A true Vault server would not +// respond with a request id / lease id for DELETE or REVOKE, but we do that +// here to verify that the makeRequest method translates the Step Operation +// and calls delete/revoke correctly +func respondCommon(id string, excludeLease bool, w http.ResponseWriter, req *http.Request) { + resp := api.Secret{ + RequestID: id + "-request", + LeaseID: "lease-id", + } + if excludeLease { + resp.LeaseID = "" + } + out, err := jsonutil.EncodeJSON(resp) + if err != nil { + panic(err) + } + w.Write(out) +} + +// Client creates a Vault API client configured to the mock environment's test +// server +func (m *mockEnvironment) Client() (*api.Client, error) { + m.l.Lock() + defer m.l.Unlock() + if m.ts == nil { + return nil, errors.New("client() called but test server is nil") + } + + if m.client != nil { + return m.client, nil + } + + cfg := api.Config{ + Address: m.ts.URL, + HttpClient: cleanhttp.DefaultPooledClient(), + Timeout: time.Second * 5, + MaxRetries: 2, + } + + client, err := api.NewClient(&cfg) + if err != nil { + return nil, err + } + + // need to set root token here to mimic an actual root token of a cluster + client.SetToken(m.RootToken()) + m.client = client + return client, nil +} + +func (m *mockEnvironment) Teardown() error { + m.teardownCalled = true + m.ts.Close() + return nil +} + +func (m *mockEnvironment) Name() string { return "" } + +func (m *mockEnvironment) MountPath() string { + return "/test/" +} + +func (m *mockEnvironment) RootToken() string { return "root-token" } + +func stepFuncWithoutAuth(path string, operation Operation, shouldError bool) Step { + return stepFuncCommon(path, operation, shouldError, true) +} + +func stepFunc(path string, operation Operation, shouldError bool) Step { + return stepFuncCommon(path, operation, shouldError, false) +} + +func stepFuncCommon(path string, operation Operation, shouldError bool, unauth bool) Step { + s := Step{ + Operation: operation, + Path: path, + Unauthenticated: unauth, + } + if shouldError { + s.Assert = func(resp *api.Secret, err error) error { + return errors.New("some error") + } + } + return s +} + +// mockT implements TestT for testing +type mockT struct { + ErrorCalled bool + ErrorArgs []interface{} + FatalCalled bool + FatalArgs []interface{} + SkipCalled bool + SkipArgs []interface{} + + f bool +} + +func (t *mockT) Error(args ...interface{}) { + t.ErrorCalled = true + t.ErrorArgs = args + t.f = true +} + +func (t *mockT) Fatal(args ...interface{}) { + t.FatalCalled = true + t.FatalArgs = args + t.f = true +} + +func (t *mockT) Skip(args ...interface{}) { + t.SkipCalled = true + t.SkipArgs = args + t.f = true +} + +func (t *mockT) Helper() {} + +// validates that X-Vault-Token is set on the requets to the mock endpoints +func checkAuth(w http.ResponseWriter, r *http.Request) { + if token := r.Header.Get("X-Vault-Token"); token == "" { + // not authenticated + w.WriteHeader(http.StatusForbidden) + } +} diff --git a/vendor/github.com/hashicorp/vault/api/go.mod b/vendor/github.com/hashicorp/vault/api/go.mod index 221548e432..40e8bc7dcd 100644 --- a/vendor/github.com/hashicorp/vault/api/go.mod +++ b/vendor/github.com/hashicorp/vault/api/go.mod @@ -5,16 +5,16 @@ go 1.13 replace github.com/hashicorp/vault/sdk => ../sdk require ( - github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 + github.com/go-test/deep v1.0.2 github.com/hashicorp/errwrap v1.0.0 github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-retryablehttp v0.6.2 - github.com/hashicorp/go-rootcerts v1.0.1 + github.com/hashicorp/go-rootcerts v1.0.2 github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/vault/sdk v0.1.14-0.20200514144402-4bfac290c352 + github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 github.com/mitchellh/mapstructure v1.2.2 - golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 - golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 - gopkg.in/square/go-jose.v2 v2.3.1 + golang.org/x/net v0.0.0-20200519113804-d87ec0cfa476 + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 + gopkg.in/square/go-jose.v2 v2.4.1 ) diff --git a/vendor/github.com/hashicorp/vault/sdk/testing/stepwise/helpers.go b/vendor/github.com/hashicorp/vault/sdk/testing/stepwise/helpers.go new file mode 100644 index 0000000000..ff2f135b79 --- /dev/null +++ b/vendor/github.com/hashicorp/vault/sdk/testing/stepwise/helpers.go @@ -0,0 +1,51 @@ +package stepwise + +import ( + "bytes" + "crypto/sha256" + "fmt" + "io" + "os" + "os/exec" + "path" + "strings" +) + +const pluginPrefix = "vault-plugin-" + +// CompilePlugin is a helper method to compile a source plugin +// TODO refactor compile plugin input and output to be types +func CompilePlugin(name, pluginName, srcDir, tmpDir string) (string, string, string, error) { + binName := name + if !strings.HasPrefix(binName, pluginPrefix) { + binName = fmt.Sprintf("%s%s", pluginPrefix, binName) + } + binPath := path.Join(tmpDir, binName) + + cmd := exec.Command("go", "build", "-o", binPath, path.Join(srcDir, fmt.Sprintf("cmd/%s/main.go", pluginName))) + cmd.Stdout = &bytes.Buffer{} + + // match the target architecture of the docker container + cmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH=amd64") + err := cmd.Run() + if err != nil { + return "", "", "", err + } + + // calculate sha256 + f, err := os.Open(binPath) + if err != nil { + return "", "", "", err + } + + defer f.Close() + + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + return "", "", "", err + } + + sha256value := fmt.Sprintf("%x", h.Sum(nil)) + + return binName, binPath, sha256value, nil +} diff --git a/vendor/github.com/hashicorp/vault/sdk/testing/stepwise/stepwise.go b/vendor/github.com/hashicorp/vault/sdk/testing/stepwise/stepwise.go new file mode 100644 index 0000000000..60791a0819 --- /dev/null +++ b/vendor/github.com/hashicorp/vault/sdk/testing/stepwise/stepwise.go @@ -0,0 +1,341 @@ +// Package stepwise offers types and functions to enable black-box style tests +// that are executed in defined set of steps. Stepwise utilizes "Environments" which +// setup a running instance of Vault and provide a valid API client to execute +// user defined steps against. +package stepwise + +import ( + "fmt" + "os" + "testing" + + log "github.com/hashicorp/go-hclog" + "github.com/hashicorp/vault/api" + "github.com/hashicorp/vault/sdk/helper/consts" + "github.com/hashicorp/vault/sdk/helper/logging" +) + +// TestEnvVar must be set to a non-empty value for acceptance tests to run. +const TestEnvVar = "VAULT_ACC" + +// Operation defines operations each step could perform. These are +// intentionally redefined from the logical package in the SDK, so users +// consistently use the stepwise package and not a combination of both stepwise +// and logical. +type Operation string + +const ( + WriteOperation Operation = "create" + UpdateOperation = "update" + ReadOperation = "read" + DeleteOperation = "delete" + ListOperation = "list" + HelpOperation = "help" +) + +// Environment is the interface Environments need to implement to be used in +// Case to execute each Step +type Environment interface { + // Setup is responsible for creating the Vault cluster for use in the test + // case. + Setup() error + + // Client returns a configured Vault API client to communicate with the Vault + // cluster created in Setup and managed by this Environment. + Client() (*api.Client, error) + + // Teardown is responsible for destroying any and all infrastructure created + // during Setup or otherwise over the course of executing test cases. + Teardown() error + + // Name returns the name of the environment provider, e.g. Docker, Minikube, + // et.al. + Name() string + + // MountPath returns the path the plugin is mounted at + MountPath() string + + // RootToken returns the root token of the cluster, used for making requests + // as well as administrative tasks + RootToken() string +} + +// PluginType defines the types of plugins supported +// This type re-create constants as a convienence so users don't need to import/use +// the consts package. +type PluginType consts.PluginType + +// These are originally defined in sdk/helper/consts/plugin_types.go +const ( + PluginTypeUnknown PluginType = iota + PluginTypeCredential + PluginTypeDatabase + PluginTypeSecrets +) + +func (p PluginType) String() string { + switch p { + case PluginTypeUnknown: + return "unknown" + case PluginTypeCredential: + return "auth" + case PluginTypeDatabase: + return "database" + case PluginTypeSecrets: + return "secret" + default: + return "unsupported" + } +} + +// MountOptions are a collection of options each step driver should +// support +type MountOptions struct { + // MountPathPrefix is an optional prefix to use when mounting the plugin. If + // omitted the mount path will default to the PluginName with a random suffix. + MountPathPrefix string + + // Name is used to register the plugin. This can be arbitrary but should be a + // reasonable value. For an example, if the plugin in test is a secret backend + // that generates UUIDs with the name "vault-plugin-secrets-uuid", then "uuid" + // or "test-uuid" would be reasonable. The name is used for lookups in the + // catalog. See "name" in the "Register Plugin" endpoint docs: + // - https://www.vaultproject.io/api-docs/system/plugins-catalog#register-plugin + RegistryName string + + // PluginType is the optional type of plugin. See PluginType const defined + // above + PluginType PluginType + + // PluginName represents the name of the plugin that gets compiled. In the + // standard plugin project file layout, it represents the folder under the + // cmd/ folder. In the below example UUID project, the PluginName would be + // "uuid": + // + // vault-plugin-secrets-uuid/ + // - backend.go + // - cmd/ + // ----uuid/ + // ------main.go + // - path_generate.go + // + PluginName string +} + +// Step represents a single step of a test Case +type Step struct { + // Operation defines what action is being taken in this step; write, read, + // delete, et. al. + Operation Operation + + // Path is the localized request path. The mount prefix, namespace, and + // optionally "auth" will be automatically added. + Path string + + // Arguments to pass in the request. These arguments represent payloads sent + // to the API. + Data map[string]interface{} + + // Assert is a function that is called after this step is executed in order to + // test that the step executed successfully. If this is not set, then the next + // step will be called + Assert AssertionFunc + + // Unauthenticated will make the request unauthenticated. + Unauthenticated bool +} + +// AssertionFunc is the callback used for Assert in Steps. +type AssertionFunc func(*api.Secret, error) error + +// Case represents a scenario we want to test which involves a series of +// steps to be followed sequentially, evaluating the results after each step. +type Case struct { + // Environment is used to setup the Vault instance and provide the client that + // will be used to drive the tests + Environment Environment + + // Steps are the set of operations that are run for this test case. During + // execution each step will be logged to output with a 1-based index as it is + // ran, with the first step logged as step '1' and not step '0'. + Steps []Step + + // SkipTeardown allows the Environment TeardownFunc to be skipped, leaving any + // infrastructure created after the test exists. This is useful for debugging + // during plugin development to examine the state of the Vault cluster after a + // test runs. Depending on the Environment used this could incur costs the + // user is responsible for. + SkipTeardown bool +} + +// Run performs an acceptance test on a backend with the given test case. +// +// Tests are not run unless an environmental variable "VAULT_ACC" is +// set to some non-empty value. This is to avoid test cases surprising +// a user by creating real resources. +// +// Tests will fail unless the verbose flag (`go test -v`, or explicitly +// the "-test.v" flag) is set. Because some acceptance tests take quite +// long, we require the verbose flag so users are able to see progress +// output. +func Run(tt TestT, c Case) { + tt.Helper() + // We only run acceptance tests if an env var is set because they're + // slow and generally require some outside configuration. + checkShouldRun(tt) + + if c.Environment == nil { + tt.Fatal("nil driver in acceptance test") + // return here only used during testing when using mockT type, otherwise + // Fatal will exit + return + } + + logger := logging.NewVaultLogger(log.Trace) + + if err := c.Environment.Setup(); err != nil { + tt.Fatal(err) + } + + defer func() { + if c.SkipTeardown { + logger.Info("driver Teardown skipped") + return + } + if err := c.Environment.Teardown(); err != nil { + logger.Error("error in driver teardown:", "error", err) + } + }() + + // retrieve the root client from the Environment. If this returns an error, + // fail immediately + rootClient, err := c.Environment.Client() + if err != nil { + tt.Fatal(err) + } + + // Trap the rootToken so that we can preform revocation or other tasks in the + // event any steps remove the token during testing. + rootToken := c.Environment.RootToken() + + // Defer revocation of any secrets created. We intentionally enclose the + // responses slice so in the event of a fatal error during test evaluation, we + // are still able to revoke any leases/secrets created + var responses []*api.Secret + defer func() { + // restore root token for admin tasks + rootClient.SetToken(rootToken) + // failedRevokes tracks any errors we get when attempting to revoke a lease + // to log to users at the end of the test. + var failedRevokes []*api.Secret + for _, secret := range responses { + if secret.LeaseID == "" { + continue + } + + if err := rootClient.Sys().Revoke(secret.LeaseID); err != nil { + tt.Error(fmt.Errorf("error revoking lease: %w", err)) + failedRevokes = append(failedRevokes, secret) + continue + } + } + + // If we have any failed revokes, log it. + if len(failedRevokes) > 0 { + for _, s := range failedRevokes { + tt.Error(fmt.Sprintf( + "WARNING: Revoking the following secret failed. It may\n"+ + "still exist. Please verify:\n\n%#v", + s)) + } + } + }() + + stepCount := len(c.Steps) + for i, step := range c.Steps { + if logger.IsWarn() { + // range is zero based, so add 1 for a human friendly output of steps. + progress := fmt.Sprintf("%d/%d", i+1, stepCount) + logger.Warn("Executing test step", "step_number", progress) + } + + // reset token in case it was cleared + client, err := rootClient.Clone() + if err != nil { + tt.Fatal(err) + } + + // TODO: support creating tokens with policies listed in each Step + client.SetToken(rootToken) + + resp, respErr := makeRequest(tt, c.Environment, step) + if resp != nil { + responses = append(responses, resp) + } + + // Run the associated AssertionFunc, if any. If an error was expected it is + // sent to the Assert function to validate. + if step.Assert != nil { + if err := step.Assert(resp, respErr); err != nil { + tt.Error(fmt.Errorf("failed step %d: %w", i+1, err)) + } + } + } +} + +func makeRequest(tt TestT, env Environment, step Step) (*api.Secret, error) { + tt.Helper() + client, err := env.Client() + if err != nil { + return nil, err + } + + if step.Unauthenticated { + token := client.Token() + client.ClearToken() + // restore the client token after this request completes + defer func() { + client.SetToken(token) + }() + } + + path := fmt.Sprintf("%s/%s", env.MountPath(), step.Path) + switch step.Operation { + case WriteOperation, UpdateOperation: + return client.Logical().Write(path, step.Data) + case ReadOperation: + // TODO support ReadWithData + return client.Logical().Read(path) + case ListOperation: + return client.Logical().List(path) + case DeleteOperation: + return client.Logical().Delete(path) + default: + return nil, fmt.Errorf("invalid operation: %s", step.Operation) + } +} + +func checkShouldRun(tt TestT) { + tt.Helper() + if os.Getenv(TestEnvVar) == "" { + tt.Skip(fmt.Sprintf( + "Acceptance tests skipped unless env '%s' set", + TestEnvVar)) + return + } + + // We require verbose mode so that the user knows what is going on. + if !testing.Verbose() { + tt.Fatal("Acceptance tests must be run with the -v flag on tests") + } +} + +// TestT is the interface used to handle the test lifecycle of a test. +// +// Users should just use a *testing.T object, which implements this. +type TestT interface { + Error(args ...interface{}) + Fatal(args ...interface{}) + Skip(args ...interface{}) + Helper() +} diff --git a/vendor/modules.txt b/vendor/modules.txt index e3ef76198c..71ef581e6f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -457,7 +457,7 @@ github.com/hashicorp/vault-plugin-secrets-openldap github.com/hashicorp/vault-plugin-secrets-openldap/client # github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f => ./api github.com/hashicorp/vault/api -# github.com/hashicorp/vault/sdk v0.1.14-0.20200615191832-d4b3c4b29c62 => ./sdk +# github.com/hashicorp/vault/sdk v0.1.14-0.20200527182800-ad90e0b39d2f => ./sdk github.com/hashicorp/vault/sdk/database/dbplugin github.com/hashicorp/vault/sdk/database/helper/connutil github.com/hashicorp/vault/sdk/database/helper/credsutil @@ -503,6 +503,7 @@ github.com/hashicorp/vault/sdk/plugin github.com/hashicorp/vault/sdk/plugin/mock github.com/hashicorp/vault/sdk/plugin/pb github.com/hashicorp/vault/sdk/queue +github.com/hashicorp/vault/sdk/testing/stepwise github.com/hashicorp/vault/sdk/version # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux