From d59efd390c3f275285c0ce53e0e8be34832a65d0 Mon Sep 17 00:00:00 2001 From: "R.B. Boyer" <4903+rboyer@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:34:27 -0600 Subject: [PATCH] test: general cleanup and fixes for the container integration test suite (#15959) - remove dep on consul main module - use 'consul tls' subcommands instead of tlsutil - use direct json config construction instead of agent/config structs - merge libcluster and libagent packages together - more widely use BuildContext - get the OSS/ENT runner stuff working properly - reduce some flakiness - fix some correctness related to http/https API --- .circleci/config.yml | 9 +- GNUmakefile | 57 +- test/integration/consul-container/go.mod | 149 +---- test/integration/consul-container/go.sum | 452 ++++---------- .../consul-container/libs/agent/agent.go | 31 - .../consul-container/libs/agent/builder.go | 283 --------- .../consul-container/libs/agent/container.go | 443 -------------- .../consul-container/libs/agent/encryption.go | 58 -- .../consul-container/libs/assert/service.go | 7 +- .../consul-container/libs/cluster/agent.go | 71 +++ .../consul-container/libs/cluster/app.go | 138 +++++ .../consul-container/libs/cluster/builder.go | 323 ++++++++++ .../consul-container/libs/cluster/cluster.go | 370 ++++++++---- .../consul-container/libs/cluster/config.go | 184 ++++++ .../libs/cluster/container.go | 562 ++++++++++++++++++ .../libs/cluster/encryption.go | 132 ++++ .../consul-container/libs/cluster/helpers.go | 82 --- .../libs/{agent => cluster}/log.go | 2 +- .../consul-container/libs/cluster/network.go | 5 +- .../consul-container/libs/service/connect.go | 136 ++--- .../consul-container/libs/service/examples.go | 108 ++-- .../consul-container/libs/service/gateway.go | 123 ++-- .../consul-container/libs/service/helpers.go | 106 ++-- .../consul-container/libs/service/service.go | 4 +- .../libs/topology/peering_topology.go | 210 +++++++ .../consul-container/libs/utils/debug.go | 12 + .../consul-container/libs/utils/defer.go | 28 + .../consul-container/libs/utils/docker.go | 38 ++ .../consul-container/libs/utils/utils.go | 3 + .../consul-container/libs/utils/version.go | 47 ++ .../libs/utils/version_oss.go | 14 +- .../test/basic/connect_service_test.go | 28 +- .../test/metrics/leader_test.go | 113 ++-- .../rotate_server_and_ca_then_fail_test.go | 98 ++- .../test/topology/peering_topology.go | 87 --- .../consul-container/test/upgrade/README.md | 14 +- .../test/upgrade/fullstopupgrade_test.go | 67 +-- .../test/upgrade/healthcheck_test.go | 329 +++------- .../test/upgrade/helper_test.go | 92 +++ .../test/upgrade/peers_http_test.go | 36 +- 40 files changed, 2732 insertions(+), 2319 deletions(-) delete mode 100644 test/integration/consul-container/libs/agent/agent.go delete mode 100644 test/integration/consul-container/libs/agent/builder.go delete mode 100644 test/integration/consul-container/libs/agent/container.go delete mode 100644 test/integration/consul-container/libs/agent/encryption.go create mode 100644 test/integration/consul-container/libs/cluster/agent.go create mode 100644 test/integration/consul-container/libs/cluster/app.go create mode 100644 test/integration/consul-container/libs/cluster/builder.go create mode 100644 test/integration/consul-container/libs/cluster/config.go create mode 100644 test/integration/consul-container/libs/cluster/container.go create mode 100644 test/integration/consul-container/libs/cluster/encryption.go delete mode 100644 test/integration/consul-container/libs/cluster/helpers.go rename test/integration/consul-container/libs/{agent => cluster}/log.go (96%) create mode 100644 test/integration/consul-container/libs/topology/peering_topology.go create mode 100644 test/integration/consul-container/libs/utils/debug.go create mode 100644 test/integration/consul-container/libs/utils/defer.go create mode 100644 test/integration/consul-container/libs/utils/docker.go create mode 100644 test/integration/consul-container/libs/utils/version.go delete mode 100644 test/integration/consul-container/test/topology/peering_topology.go create mode 100644 test/integration/consul-container/test/upgrade/helper_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 4b70324982..9dfeeb4677 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -221,6 +221,10 @@ jobs: name: lint sdk working_directory: sdk command: *lintcmd + - run: + name: lint container tests + working_directory: test/integration/consul-container + command: *lintcmd - run: *notify-slack-failure check-go-mod: @@ -864,7 +868,9 @@ jobs: -- \ -timeout=30m \ ./... \ + --target-image consul \ --target-version local \ + --latest-image consul \ --latest-version latest ls -lrt environment: @@ -874,9 +880,6 @@ jobs: COMPOSE_INTERACTIVE_NO_CLI: 1 # tput complains if this isn't set to something. TERM: ansi - - store_artifacts: - path: ./test/integration/consul-container/test/upgrade/workdir/logs - destination: container-logs - store_test_results: path: *TEST_RESULTS_DIR - store_artifacts: diff --git a/GNUmakefile b/GNUmakefile index 57017bbd97..116581cceb 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -34,6 +34,8 @@ DATE_FORMAT="%Y-%m-%dT%H:%M:%SZ" # it's tricky to do an RFC3339 format in a cros GIT_DATE=$(shell $(CURDIR)/build-support/scripts/build-date.sh) # we're using this for build date because it's stable across platform builds GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY) -X $(GIT_IMPORT).BuildDate=$(GIT_DATE) +GOTESTSUM_PATH?=$(shell command -v gotestsum) + ifeq ($(FORCE_REBUILD),1) NOCACHE=--no-cache else @@ -47,6 +49,12 @@ else QUIET= endif +ifeq ("$(GOTAGS)","") +CONSUL_COMPAT_TEST_IMAGE=consul +else +CONSUL_COMPAT_TEST_IMAGE=hashicorp/consul-enterprise +endif + CONSUL_DEV_IMAGE?=consul-dev GO_BUILD_TAG?=consul-build-go UI_BUILD_TAG?=consul-build-ui @@ -311,6 +319,8 @@ lint: lint-tools @golangci-lint run --build-tags '$(GOTAGS)' && \ (cd api && golangci-lint run --build-tags '$(GOTAGS)') && \ (cd sdk && golangci-lint run --build-tags '$(GOTAGS)') + @echo "--> Running golangci-lint (container tests)" + cd test/integration/consul-container && golangci-lint run --build-tags '$(GOTAGS)' @echo "--> Running lint-consul-retry" @lint-consul-retry @echo "--> Running enumcover" @@ -391,25 +401,48 @@ test-envoy-integ: $(ENVOY_INTEG_DEPS) @go test -v -timeout=30m -tags integration $(GO_TEST_FLAGS) ./test/integration/connect/envoy .PHONY: test-compat-integ -test-compat-integ: dev-docker -ifeq ("$(GOTAGS)","") - @docker tag consul-dev:latest consul:local - @docker run --rm -t consul:local consul version +test-compat-integ: test-compat-integ-setup +ifeq ("$(GOTESTSUM_PATH)","") @cd ./test/integration/consul-container && \ - go test -v -timeout=30m ./... --target-version local --latest-version latest + go test \ + -v \ + -timeout=30m \ + ./... \ + --tags $(GOTAGS) \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest else - @docker tag consul-dev:latest hashicorp/consul-enterprise:local - @docker run --rm -t hashicorp/consul-enterprise:local consul version @cd ./test/integration/consul-container && \ - go test -v -timeout=30m ./... --tags $(GOTAGS) --target-version local --latest-version latest + gotestsum \ + --format=short-verbose \ + --debug \ + --rerun-fails=3 \ + --packages="./..." \ + -- \ + --tags $(GOTAGS) \ + -timeout=30m \ + ./... \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest endif +.PHONY: test-compat-integ-setup +test-compat-integ-setup: dev-docker + @docker tag consul-dev:latest $(CONSUL_COMPAT_TEST_IMAGE):local + @docker run --rm -t $(CONSUL_COMPAT_TEST_IMAGE):local consul version + .PHONY: test-metrics-integ -test-metrics-integ: dev-docker - @docker tag consul-dev:latest consul:local - @docker run --rm -t consul:local consul version +test-metrics-integ: test-compat-integ-setup @cd ./test/integration/consul-container && \ - go test -v -timeout=7m ./metrics --target-version local + go test -v -timeout=7m ./test/metrics \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest test-connect-ca-providers: ifeq ("$(CIRCLECI)","true") diff --git a/test/integration/consul-container/go.mod b/test/integration/consul-container/go.mod index 16e98e76bb..5a0b89a022 100644 --- a/test/integration/consul-container/go.mod +++ b/test/integration/consul-container/go.mod @@ -3,182 +3,79 @@ module github.com/hashicorp/consul/test/integration/consul-container go 1.19 require ( - github.com/docker/docker v20.10.11+incompatible + github.com/docker/docker v20.10.22+incompatible github.com/docker/go-connections v0.4.0 - github.com/hashicorp/consul v1.14.1 github.com/hashicorp/consul/api v1.18.0 github.com/hashicorp/consul/sdk v0.13.0 + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/hashicorp/go-multierror v1.1.1 + github.com/hashicorp/go-uuid v1.0.2 + github.com/hashicorp/go-version v1.2.1 github.com/hashicorp/serf v0.10.1 github.com/itchyny/gojq v0.12.9 + github.com/mitchellh/copystructure v1.2.0 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.0 github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 - github.com/testcontainers/testcontainers-go v0.13.0 + github.com/testcontainers/testcontainers-go v0.15.0 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 ) require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/DataDog/datadog-go v3.2.0+incompatible // indirect - github.com/Microsoft/go-winio v0.4.17 // indirect - github.com/Microsoft/hcsshim v0.8.24 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/Microsoft/hcsshim v0.9.4 // indirect github.com/armon/go-metrics v0.3.10 // indirect - github.com/armon/go-radix v1.0.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.42.34 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/boltdb/bolt v1.3.1 // indirect - github.com/cenkalti/backoff/v4 v4.1.2 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect - github.com/circonus-labs/circonusllhist v0.1.3 // indirect - github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect - github.com/containerd/cgroups v1.0.3 // indirect - github.com/containerd/containerd v1.5.13 // indirect - github.com/coreos/go-oidc v2.1.0+incompatible // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/docker/distribution v2.7.1+incompatible // indirect - github.com/docker/go-units v0.4.0 // indirect - github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect - github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect + github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/containerd/cgroups v1.0.4 // indirect + github.com/containerd/containerd v1.6.8 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/fatih/color v1.13.0 // indirect - github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/go-logr/logr v0.2.0 // indirect - github.com/go-openapi/analysis v0.21.2 // indirect - github.com/go-openapi/errors v0.20.2 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.6 // indirect - github.com/go-openapi/loads v0.21.1 // indirect - github.com/go-openapi/runtime v0.24.1 // indirect - github.com/go-openapi/spec v0.20.4 // indirect - github.com/go-openapi/strfmt v0.21.3 // indirect - github.com/go-openapi/swag v0.21.1 // indirect - github.com/go-openapi/validate v0.21.0 // indirect - github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.1 // indirect github.com/google/btree v1.0.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/gnostic v0.4.1 // indirect - github.com/gorilla/mux v1.7.3 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 // indirect - github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 // indirect - github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 // indirect - github.com/hashicorp/consul/proto-public v0.2.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-bexpr v0.1.2 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-connlimit v0.3.0 // indirect github.com/hashicorp/go-hclog v1.2.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-memdb v1.3.4 // indirect github.com/hashicorp/go-msgpack v1.1.5 // indirect - github.com/hashicorp/go-msgpack/v2 v2.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-raftchunking v0.7.0 // indirect - github.com/hashicorp/go-retryablehttp v0.6.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/go-syslog v1.0.0 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect - github.com/hashicorp/go-version v1.2.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/hcp-scada-provider v0.2.0 // indirect - github.com/hashicorp/hcp-sdk-go v0.23.1-0.20220921131124-49168300a7dc // indirect - github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect - github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 // indirect - github.com/hashicorp/raft v1.3.11 // indirect - github.com/hashicorp/raft-autopilot v0.1.6 // indirect - github.com/hashicorp/raft-boltdb/v2 v2.2.2 // indirect - github.com/hashicorp/vault/api v1.0.5-0.20200717191844-f687267c8086 // indirect - github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 // indirect - github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect - github.com/imdario/mergo v0.3.13 // indirect github.com/itchyny/timefmt-go v0.1.4 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.10 // indirect - github.com/kr/pretty v0.3.0 // indirect - github.com/magiconair/properties v1.8.5 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.16 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/miekg/dns v1.1.41 // indirect - github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.0 // indirect - github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 // indirect - github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect - github.com/mitchellh/pointerstructure v1.2.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/sys/mount v0.2.0 // indirect - github.com/moby/sys/mountinfo v0.5.0 // indirect + github.com/moby/sys/mount v0.3.3 // indirect + github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect - github.com/oklog/ulid v1.3.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/opencontainers/runc v1.1.4 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/patrickmn/go-cache v2.1.0+incompatible // indirect - github.com/pierrec/lz4 v2.5.2+incompatible // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/prometheus/client_golang v1.7.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.10.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect - github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect - github.com/stretchr/objx v0.4.0 // indirect - github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect - go.etcd.io/bbolt v1.3.5 // indirect - go.mongodb.org/mongo-driver v1.10.0 // indirect - go.opencensus.io v0.22.4 // indirect - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect + go.opencensus.io v0.23.0 // indirect golang.org/x/net v0.4.0 // indirect - golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.3.0 // indirect - golang.org/x/term v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect - golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect - google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 // indirect google.golang.org/grpc v1.49.0 // indirect google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/square/go-jose.v2 v2.5.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.20.6 // indirect - k8s.io/apimachinery v0.20.6 // indirect - k8s.io/client-go v0.20.6 // indirect - k8s.io/klog/v2 v2.4.0 // indirect - k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.0.3 // indirect - sigs.k8s.io/yaml v1.2.0 // indirect ) replace github.com/hashicorp/consul/api => ../../../api replace github.com/hashicorp/consul/sdk => ../../../sdk -replace github.com/hashicorp/consul/proto-public => ../../../proto-public - replace github.com/hashicorp/consul => ../../.. diff --git a/test/integration/consul-container/go.sum b/test/integration/consul-container/go.sum index 4cc6c73c9c..6fe3da06a1 100644 --- a/test/integration/consul-container/go.sum +++ b/test/integration/consul-container/go.sum @@ -10,6 +10,7 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -38,8 +39,6 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -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/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -48,8 +47,9 @@ github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -57,16 +57,16 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= -github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I= +github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -75,29 +75,18 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= -github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= 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/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.42.34 h1:fqGAiKmCSRY1rEa4G9VqgkKKbNmLKYq5dKmLtQkvYi8= -github.com/aws/aws-sdk-go v1.42.34/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 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/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= @@ -105,20 +94,19 @@ github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edY github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -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/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= @@ -131,16 +119,12 @@ github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= @@ -156,8 +140,8 @@ github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4S github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= -github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= +github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= +github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= @@ -172,22 +156,22 @@ github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= -github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= -github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= +github.com/containerd/containerd v1.6.8 h1:h4dOFDwzHmqFEP754PgfgTeVXFnLiRc6kiqC7tplDJs= +github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= @@ -208,6 +192,7 @@ github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= @@ -235,7 +220,6 @@ github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -260,28 +244,34 @@ github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= 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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.11+incompatible h1:OqzI/g/W54LczvhnccGqniFoQghHx3pklbLuhfXpqGo= -github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.22+incompatible h1:6jX4yB+NtcbldT90k7vBSaWJDB3i+zkVJT9BEK8kQkk= +github.com/docker/docker v20.10.22+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= @@ -294,110 +284,45 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 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-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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/analysis v0.21.2 h1:hXFrOYFHUAMQdu6zwAiKKJHJQ8kqZs1ux/ru1P1wLJU= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2 h1:dxy7PGTqEh94zj2E3h1cUmQQWiM1+aeCROfAr02EmK8= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/loads v0.21.1 h1:Wb3nVZpdEzDTcly8S4HMkey6fjARRzb7iEaySimlDW0= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/runtime v0.24.1 h1:Sml5cgQKGYQHF+M7yYSHaH1eOjvTykrddTE/KtQVjqo= -github.com/go-openapi/runtime v0.24.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/validate v0.21.0 h1:+Wqk39yKOhfpLqNLEC0/eViCkzM5FVXVqrvt526+wcI= -github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= -github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= @@ -418,13 +343,16 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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= @@ -442,8 +370,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -454,23 +380,22 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2 h1:AtvtonGEH/fZK0XPNNBdB6swgy7Iudfx88wzyIpwqJ8= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -479,124 +404,65 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 h1:1ZEjnveDe20yFa6lSkfdQZm5BR/b271n0MsB5R2L3us= -github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706/go.mod h1:1Cs8FlmD1BfSQXJGcFLSV5FuIx1AbJP+EJGdxosoS2g= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 h1:wzWurXrxfSyG1PHskIZlfuXlTSCj1Tsyatp9DtaasuY= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69/go.mod h1:svUZZDvotY8zTODknUePc6mZ9pX8nN0ViGwWcUSOBEA= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-bexpr v0.1.2 h1:ijMXI4qERbzxbCnkxmfUtwMyjrrk3y+Vt0MxojNCbBs= -github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-connlimit v0.3.0 h1:oAojHGjFxUTTTA8c5XXnDqWJ2HLuWbDiBPTpWvNzvqM= -github.com/hashicorp/go-connlimit v0.3.0/go.mod h1:OUj9FGL1tPIhl/2RCfzYHrIiWj+VVPGNyVPnUX8AqS0= -github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= -github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= -github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= -github.com/hashicorp/go-msgpack/v2 v2.0.0 h1:c1fiLq1LNghmLOry1ipGhvLDi+/zEoaEP2JrE1oFJ9s= -github.com/hashicorp/go-msgpack/v2 v2.0.0/go.mod h1:JIxYkkFJRDDRSoWQBSh7s9QAVThq+82iWmUpmE4jKak= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= -github.com/hashicorp/go-raftchunking v0.7.0 h1:APNMnCXmTOhumkFv/GpJIbq7HteWF7EnGZ3875lRN0Y= -github.com/hashicorp/go-raftchunking v0.7.0/go.mod h1:Dg/eBOaJzE0jYKNwNLs5IA5j0OSmL5HoCUiMy3mDmrI= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= 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.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 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-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/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/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/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/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/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/hcp-scada-provider v0.2.0 h1:iD3Y+c7LTdjeaWKHq/ym6ahEdSL1R+9GHvKWBb4t+aM= -github.com/hashicorp/hcp-scada-provider v0.2.0/go.mod h1:Q0WpS2RyhBKOPD4X/8oW7AJe7jA2HXB09EwDzwRTao0= -github.com/hashicorp/hcp-sdk-go v0.23.1-0.20220921131124-49168300a7dc h1:on26TCKYnX7JzZCtwkR/LWHSqMu40PoZ6h/0e6Pq8ug= -github.com/hashicorp/hcp-sdk-go v0.23.1-0.20220921131124-49168300a7dc/go.mod h1:/9UoDY2FYYA8lFaKBb2HmM/jKYZGANmf65q9QRc/cVw= -github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 h1:n9J0rwVWXDpNd5iZnwY7w4WZyq53/rROeI7OVvLW8Ok= -github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 h1:kBpVVl1sl3MaSrs97e0+pDQhSrqJv9gVbSUrPpVfl1w= -github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0/go.mod h1:6pdNz0vo0mF0GvhwDG56O3N18qBrAz/XRIcfINfTbwo= -github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= -github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft v1.3.11 h1:p3v6gf6l3S797NnK5av3HcczOC1T5CLoaRvg0g9ys4A= -github.com/hashicorp/raft v1.3.11/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4= -github.com/hashicorp/raft-autopilot v0.1.6 h1:C1q3RNF2FfXNZfHWbvVAu0QixaQK8K5pX4O5lh+9z4I= -github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= -github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= -github.com/hashicorp/raft-boltdb v0.0.0-20210409134258-03c10cc3d4ea/go.mod h1:qRd6nFJYYS6Iqnc/8HcUmko2/2Gw8qTFEmxDLii6W5I= -github.com/hashicorp/raft-boltdb v0.0.0-20211202195631-7d34b9fb3f42 h1:Ye8SofeDHJzu9xvvaMmpMkqHELWW7rTcXwdUR0CWW48= -github.com/hashicorp/raft-boltdb/v2 v2.2.2 h1:rlkPtOllgIcKLxVT4nutqlTH2NRFn+tO1wwZk/4Dxqw= -github.com/hashicorp/raft-boltdb/v2 v2.2.2/go.mod h1:N8YgaZgNJLpZC+h+by7vDu5rzsRgONThTEeUS3zWbfY= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hashicorp/vault/api v1.0.5-0.20200717191844-f687267c8086 h1:OKsyxKi2sNmqm1Gv93adf2AID2FOBFdCbbZn9fGtIdg= -github.com/hashicorp/vault/api v1.0.5-0.20200717191844-f687267c8086/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk= -github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 h1:e1ok06zGrWJW91rzRroyl5nRNqraaBe4d5hiKcVZuHM= -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/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -604,8 +470,6 @@ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/itchyny/gojq v0.12.9 h1:biKpbKwMxVYhCU1d6mR7qMr3f0Hn9F5k5YykCVb3gmM= github.com/itchyny/gojq v0.12.9/go.mod h1:T4Ip7AETUXeGpD+436m+UEl3m3tokRgajd5pRfsR5oE= @@ -614,34 +478,22 @@ github.com/itchyny/timefmt-go v0.1.4/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2s github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -649,36 +501,29 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 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/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/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/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/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -686,9 +531,10 @@ github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peK github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -696,55 +542,36 @@ github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= -github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 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/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= -github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 h1:hOY53G+kBFhbYFpRVxHl5eS7laP6B1+Cq+Z9Dry1iMU= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= -github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= -github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= +github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= +github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= 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/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= -github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -754,21 +581,23 @@ github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -778,8 +607,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -799,59 +628,44 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -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-0.20171018195549-f15c970de5b7/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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 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.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -860,23 +674,17 @@ github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 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/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= @@ -885,15 +693,12 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -909,7 +714,6 @@ github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzu github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= @@ -925,7 +729,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= @@ -936,13 +739,10 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= -github.com/testcontainers/testcontainers-go v0.13.0 h1:OUujSlEGsXVo/ykPVZk3KanBNGN0TYb/7oKIPVn15JA= -github.com/testcontainers/testcontainers-go v0.13.0/go.mod h1:z1abufU633Eb/FmSBTzV6ntZAC1eZBYPtaFsn4nPuDk= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/testcontainers/testcontainers-go v0.15.0 h1:3Ex7PUGFv0b2bBsdOv6R42+SK2qoZnWBd21LvZYhUtQ= +github.com/testcontainers/testcontainers-go v0.15.0/go.mod h1:PkohMRH2X8Hib0IWtifVexDfLPVT+tb5E9hsf7cW12w= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -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= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -957,17 +757,11 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17 github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -976,49 +770,35 @@ github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPS github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= -go.mongodb.org/mongo-driver v1.10.0 h1:UtV6N5k14upNp4LTduX0QCufG124fSu25Wz9tu94GLg= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/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/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1057,7 +837,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/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-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1070,6 +849,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/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-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1082,7 +862,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1092,11 +872,7 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1104,15 +880,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= 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-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/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/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1125,25 +899,21 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1154,7 +924,6 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1174,6 +943,7 @@ golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1181,60 +951,52 @@ golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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= @@ -1242,24 +1004,20 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1275,10 +1033,13 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1294,13 +1055,13 @@ google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1322,18 +1083,18 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 h1:K1zaaMdYBXRyX+cwFnxj7M6zwDyumLQMZ5xqwGvjreQ= google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737/go.mod h1:2r/26NEF3bFmT3eC3aZreahSal0C3Shl8Gi6vyDYqOQ= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -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.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -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.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= @@ -1341,10 +1102,12 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1374,13 +1137,11 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -1391,21 +1152,15 @@ 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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1414,19 +1169,17 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6 h1:bgdZrW++LqgrLikWYNruIKAtltXbSCX2l5mJu11hrVE= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6 h1:R5p3SlhaABYShQSO6LpPsYHjV05Q+79eBUR0Ut/f4tk= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6 h1:nJZOfolnsVtDtbGJNCxzOtKUAu7zvXjB8+pMo9UNxZo= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= @@ -1435,21 +1188,22 @@ k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3 h1:4oyYo8NREp49LBBhKxEqCulFjg26rawYKrnCmg+Sr6c= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/test/integration/consul-container/libs/agent/agent.go b/test/integration/consul-container/libs/agent/agent.go deleted file mode 100644 index e3873e3f15..0000000000 --- a/test/integration/consul-container/libs/agent/agent.go +++ /dev/null @@ -1,31 +0,0 @@ -package agent - -import ( - "context" - - "github.com/hashicorp/consul/api" -) - -// Agent represent a Consul agent abstraction -type Agent interface { - GetAddr() (string, int) - GetClient() *api.Client - GetName() string - GetConfig() Config - GetDatacenter() string - IsServer() bool - RegisterTermination(func() error) - Terminate() error - Upgrade(ctx context.Context, config Config) error - Exec(ctx context.Context, cmd []string) (int, error) - DataDir() string -} - -// Config is a set of configurations required to create a Agent -type Config struct { - JSON string - Certs map[string]string - Image string - Version string - Cmd []string -} diff --git a/test/integration/consul-container/libs/agent/builder.go b/test/integration/consul-container/libs/agent/builder.go deleted file mode 100644 index 3db154c709..0000000000 --- a/test/integration/consul-container/libs/agent/builder.go +++ /dev/null @@ -1,283 +0,0 @@ -package agent - -import ( - "encoding/json" - "path/filepath" - - "github.com/pkg/errors" - "golang.org/x/mod/semver" - - agentconfig "github.com/hashicorp/consul/agent/config" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/tlsutil" -) - -const ( - remoteCertDirectory = "/consul/config/certs" -) - -// BuildContext provides a reusable object meant to share common configuration settings -// between agent configuration builders. -type BuildContext struct { - datacenter string - encryptKey string - caCert string - caKey string - index int // keeps track of the certificates issued for naming purposes - injectAutoEncryption bool // initialize the built-in CA and set up agents to use auto-encrpt - injectCerts bool // initializes the built-in CA and distributes client certificates to agents - injectGossipEncryption bool // setup the agents to use a gossip encryption key - consulVersion string -} - -// BuildOptions define the desired automated test setup overrides that are -// applied across agents in the cluster -type BuildOptions struct { - Datacenter string // Override datacenter for agents - InjectCerts bool // Provides a CA for all agents and (future) agent certs. - InjectAutoEncryption bool // Configures auto-encrypt for TLS and sets up certs. Overrides InjectCerts. - InjectGossipEncryption bool // Provides a gossip encryption key for all agents. - ConsulVersion string // The default Consul version for agents in the cluster when none is specified. -} - -func NewBuildContext(opts BuildOptions) (*BuildContext, error) { - ctx := &BuildContext{ - datacenter: opts.Datacenter, - injectAutoEncryption: opts.InjectAutoEncryption, - injectCerts: opts.InjectCerts, - injectGossipEncryption: opts.InjectGossipEncryption, - consulVersion: opts.ConsulVersion, - } - - if opts.ConsulVersion == "" { - ctx.consulVersion = *utils.TargetVersion - } - - if opts.InjectGossipEncryption { - serfKey, err := newSerfEncryptionKey() - if err != nil { - return nil, errors.Wrap(err, "could not generate serf encryption key") - } - ctx.encryptKey = serfKey - } - - if opts.InjectAutoEncryption || opts.InjectCerts { - // This is the same call that 'consul tls ca create` will run - caCert, caKey, err := tlsutil.GenerateCA(tlsutil.CAOpts{Domain: "consul", PermittedDNSDomains: []string{"consul", "localhost"}}) - if err != nil { - return nil, errors.Wrap(err, "could not generate built-in CA root pair") - } - ctx.caCert = caCert - ctx.caKey = caKey - } - return ctx, nil -} - -func (c *BuildContext) GetCerts() (cert string, key string) { - return c.caCert, c.caKey -} - -type Builder struct { - conf *agentconfig.Config - certs map[string]string - context *BuildContext -} - -// NewConfigBuilder instantiates a builder object with sensible defaults for a single consul instance -// This includes the following: -// * default ports with no plaintext options -// * debug logging -// * single server with bootstrap -// * bind to all interfaces, advertise on 'eth0' -// * connect enabled -func NewConfigBuilder(ctx *BuildContext) *Builder { - b := &Builder{ - certs: map[string]string{}, - conf: &agentconfig.Config{ - AdvertiseAddrLAN: utils.StringToPointer(`{{ GetInterfaceIP "eth0" }}`), - BindAddr: utils.StringToPointer("0.0.0.0"), - Bootstrap: utils.BoolToPointer(true), - ClientAddr: utils.StringToPointer("0.0.0.0"), - Connect: agentconfig.Connect{ - Enabled: utils.BoolToPointer(true), - }, - LogLevel: utils.StringToPointer("DEBUG"), - ServerMode: utils.BoolToPointer(true), - }, - context: ctx, - } - - // These are the default ports, disabling plaintext transport - b.conf.Ports = agentconfig.Ports{ - DNS: utils.IntToPointer(8600), - HTTP: nil, - HTTPS: utils.IntToPointer(8501), - GRPC: utils.IntToPointer(8502), - SerfLAN: utils.IntToPointer(8301), - SerfWAN: utils.IntToPointer(8302), - Server: utils.IntToPointer(8300), - } - - if ctx != nil && (ctx.consulVersion == "local" || semver.Compare("v"+ctx.consulVersion, "v1.14.0") >= 0) { - // Enable GRPCTLS for version after v1.14.0 - b.conf.Ports.GRPCTLS = utils.IntToPointer(8503) - } - - return b -} - -func (b *Builder) Bootstrap(servers int) *Builder { - if servers < 1 { - b.conf.Bootstrap = nil - b.conf.BootstrapExpect = nil - } else if servers == 1 { - b.conf.Bootstrap = utils.BoolToPointer(true) - b.conf.BootstrapExpect = nil - } else { - b.conf.Bootstrap = nil - b.conf.BootstrapExpect = utils.IntToPointer(servers) - } - return b -} - -func (b *Builder) Client() *Builder { - b.conf.Ports.Server = nil - b.conf.ServerMode = nil - b.conf.Bootstrap = nil - b.conf.BootstrapExpect = nil - return b -} - -func (b *Builder) Datacenter(name string) *Builder { - b.conf.Datacenter = utils.StringToPointer(name) - return b -} - -func (b *Builder) Peering(enable bool) *Builder { - b.conf.Peering = agentconfig.Peering{ - Enabled: utils.BoolToPointer(enable), - } - return b -} - -func (b *Builder) RetryJoin(names ...string) *Builder { - b.conf.RetryJoinLAN = names - return b -} - -func (b *Builder) Telemetry(statSite string) *Builder { - b.conf.Telemetry = agentconfig.Telemetry{ - StatsiteAddr: utils.StringToPointer(statSite), - } - return b -} - -// ToAgentConfig renders the builders configuration into a string -// representation of the json config file for agents. -// DANGER! Some fields may not have json tags in the Agent Config. -// You may need to add these yourself. -func (b *Builder) ToAgentConfig() (*Config, error) { - b.injectContextOptions() - - out, err := json.MarshalIndent(b.conf, "", " ") - if err != nil { - return nil, errors.Wrap(err, "could not marshall builder") - } - - conf := &Config{ - Certs: b.certs, - Cmd: []string{"agent"}, - Image: *utils.TargetImage, - JSON: string(out), - Version: *utils.TargetVersion, - } - - // Override the default version - if b.context != nil && b.context.consulVersion != "" { - conf.Version = b.context.consulVersion - } - - return conf, nil -} - -func (b *Builder) injectContextOptions() { - if b.context == nil { - return - } - - var dc string - if b.context.datacenter != "" { - b.conf.Datacenter = utils.StringToPointer(b.context.datacenter) - dc = b.context.datacenter - } - if b.conf.Datacenter == nil || *b.conf.Datacenter == "" { - dc = "dc1" - } - - server := b.conf.ServerMode != nil && *b.conf.ServerMode - - if b.context.encryptKey != "" { - b.conf.EncryptKey = utils.StringToPointer(b.context.encryptKey) - } - - // For any TLS setup, we add the CA to agent conf - if b.context.caCert != "" { - // Add the ca file to the list of certs that will be mounted to consul - filename := filepath.Join(remoteCertDirectory, "consul-agent-ca.pem") - b.certs[filename] = b.context.caCert - - b.conf.TLS = agentconfig.TLS{ - Defaults: agentconfig.TLSProtocolConfig{ - CAFile: utils.StringToPointer(filename), - VerifyOutgoing: utils.BoolToPointer(true), // Secure settings - }, - InternalRPC: agentconfig.TLSProtocolConfig{ - VerifyServerHostname: utils.BoolToPointer(true), - }, - } - } - - // Also for any TLS setup, generate server key pairs from the CA - if b.context.caCert != "" && server { - keyFileName, priv, certFileName, pub := newServerTLSKeyPair(dc, b.context) - - // Add the key pair to the list that will be mounted to consul - certFileName = filepath.Join(remoteCertDirectory, certFileName) - keyFileName = filepath.Join(remoteCertDirectory, keyFileName) - - b.certs[certFileName] = pub - b.certs[keyFileName] = priv - - b.conf.TLS.Defaults.CertFile = utils.StringToPointer(certFileName) - b.conf.TLS.Defaults.KeyFile = utils.StringToPointer(keyFileName) - b.conf.TLS.Defaults.VerifyIncoming = utils.BoolToPointer(true) // Only applies to servers for auto-encrypt - } - - // This assumes we've already gone through the CA/Cert setup in the previous conditional - if b.context.injectAutoEncryption && server { - b.conf.AutoEncrypt = agentconfig.AutoEncrypt{ - AllowTLS: utils.BoolToPointer(true), // This setting is different between client and servers - } - - b.conf.TLS.GRPC = agentconfig.TLSProtocolConfig{ - UseAutoCert: utils.BoolToPointer(true), // This is required for peering to work over the non-GRPC_TLS port - } - - // VerifyIncoming does not apply to client agents for auto-encrypt - } - - if b.context.injectAutoEncryption && !server { - b.conf.AutoEncrypt = agentconfig.AutoEncrypt{ - TLS: utils.BoolToPointer(true), // This setting is different between client and servers - } - - b.conf.TLS.GRPC = agentconfig.TLSProtocolConfig{ - UseAutoCert: utils.BoolToPointer(true), // This is required for peering to work over the non-GRPC_TLS port - } - } - - if b.context.injectCerts && !b.context.injectAutoEncryption { - panic("client certificate distribution not implemented") - } - b.context.index++ -} diff --git a/test/integration/consul-container/libs/agent/container.go b/test/integration/consul-container/libs/agent/container.go deleted file mode 100644 index 36ed60f7a9..0000000000 --- a/test/integration/consul-container/libs/agent/container.go +++ /dev/null @@ -1,443 +0,0 @@ -package agent - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "strconv" - "time" - - dockercontainer "github.com/docker/docker/api/types/container" - "github.com/pkg/errors" - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/wait" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -const bootLogLine = "Consul agent running" -const disableRYUKEnv = "TESTCONTAINERS_RYUK_DISABLED" - -// consulContainerNode implements the Agent interface by running a Consul agent -// in a container. -type consulContainerNode struct { - ctx context.Context - client *api.Client - pod testcontainers.Container - container testcontainers.Container - serverMode bool - ip string - port int - datacenter string - config Config - podReq testcontainers.ContainerRequest - consulReq testcontainers.ContainerRequest - certDir string - dataDir string - network string - id int - name string - terminateFuncs []func() error -} - -// NewConsulContainer starts a Consul agent in a container with the given config. -func NewConsulContainer(ctx context.Context, config Config, network string, index int) (Agent, error) { - license, err := readLicense() - if err != nil { - return nil, err - } - - pc, err := readSomeConfigFileFields(config.JSON) - if err != nil { - return nil, err - } - - consulType := "client" - if pc.Server { - consulType = "server" - } - name := utils.RandName(fmt.Sprintf("%s-consul-%s-%d", pc.Datacenter, consulType, index)) - - // Inject new Agent name - config.Cmd = append(config.Cmd, "-node", name) - - tmpDirData, err := os.MkdirTemp("", name) - if err != nil { - return nil, err - } - err = os.Chmod(tmpDirData, 0777) - if err != nil { - return nil, err - } - - configFile, err := createConfigFile(config.JSON) - if err != nil { - return nil, err - } - - tmpCertData, err := os.MkdirTemp("", fmt.Sprintf("%s-certs", name)) - if err != nil { - return nil, err - } - err = os.Chmod(tmpCertData, 0777) - if err != nil { - return nil, err - } - - for filename, cert := range config.Certs { - err := createCertFile(tmpCertData, filename, cert) - if err != nil { - return nil, errors.Wrapf(err, "failed to write file %s", filename) - } - } - - opts := containerOpts{ - name: name, - certDir: tmpCertData, - configFile: configFile, - dataDir: tmpDirData, - license: license, - addtionalNetworks: []string{"bridge", network}, - hostname: fmt.Sprintf("agent-%d", index), - } - podReq, consulReq := newContainerRequest(config, opts) - - podContainer, err := startContainer(ctx, podReq) - if err != nil { - return nil, err - } - - mappedPort, err := podContainer.MappedPort(ctx, "8500") - if err != nil { - return nil, err - } - - ip, err := podContainer.ContainerIP(ctx) - if err != nil { - return nil, err - } - - consulContainer, err := startContainer(ctx, consulReq) - if err != nil { - return nil, err - } - - if *utils.FollowLog { - if err := consulContainer.StartLogProducer(ctx); err != nil { - return nil, err - } - consulContainer.FollowOutput(&LogConsumer{ - Prefix: name, - }) - } - - uri, err := podContainer.Endpoint(ctx, "http") - if err != nil { - return nil, err - } - apiConfig := api.DefaultConfig() - apiConfig.Address = uri - apiClient, err := api.NewClient(apiConfig) - if err != nil { - return nil, err - } - - return &consulContainerNode{ - config: config, - pod: podContainer, - container: consulContainer, - serverMode: pc.Server, - ip: ip, - port: mappedPort.Int(), - datacenter: pc.Datacenter, - client: apiClient, - ctx: ctx, - podReq: podReq, - consulReq: consulReq, - dataDir: tmpDirData, - certDir: tmpCertData, - network: network, - id: index, - name: name, - }, nil -} - -func (c *consulContainerNode) GetName() string { - name, err := c.container.Name(c.ctx) - if err != nil { - return "" - } - return name -} - -func (c *consulContainerNode) GetConfig() Config { - return c.config -} - -func (c *consulContainerNode) GetDatacenter() string { - return c.datacenter -} - -func (c *consulContainerNode) IsServer() bool { - return c.serverMode -} - -// GetClient returns an API client that can be used to communicate with the Agent. -func (c *consulContainerNode) GetClient() *api.Client { - return c.client -} - -// GetAddr return the network address associated with the Agent. -func (c *consulContainerNode) GetAddr() (string, int) { - return c.ip, c.port -} - -func (c *consulContainerNode) RegisterTermination(f func() error) { - c.terminateFuncs = append(c.terminateFuncs, f) -} - -func (c *consulContainerNode) Exec(ctx context.Context, cmd []string) (int, error) { - return c.container.Exec(ctx, cmd) -} - -// Upgrade terminates a running container and create a new one using the provided config. -// The upgraded node will -// - use the same node name and the data dir as the old version node -func (c *consulContainerNode) Upgrade(ctx context.Context, config Config) error { - // Reuse the node name since we assume upgrade on the same node - config.Cmd = append(config.Cmd, "-node", c.name) - - file, err := createConfigFile(config.JSON) - if err != nil { - return err - } - - for filename, cert := range config.Certs { - err := createCertFile(c.certDir, filename, cert) - if err != nil { - return errors.Wrapf(err, "failed to write file %s", filename) - } - } - - // We'll keep the same pod. - opts := containerOpts{ - name: c.consulReq.Name, - certDir: c.certDir, - configFile: file, - dataDir: c.dataDir, - license: "", - addtionalNetworks: []string{"bridge", c.network}, - hostname: fmt.Sprintf("agent-%d", c.id), - } - _, consulReq2 := newContainerRequest(config, opts) - consulReq2.Env = c.consulReq.Env // copy license - fmt.Printf("Upgraded node %s config:%s\n", c.name, file) - - if c.container != nil && *utils.FollowLog { - err = c.container.StopLogProducer() - time.Sleep(2 * time.Second) - if err != nil { - fmt.Printf("WARN: error stop log producer: %v", err) - } - } - - if err = c.container.Terminate(c.ctx); err != nil { - return fmt.Errorf("error terminate running container: %v", err) - } - - c.consulReq = consulReq2 - - time.Sleep(5 * time.Second) - container, err := startContainer(ctx, c.consulReq) - c.container = container - if err != nil { - return err - } - c.ctx = ctx - - if *utils.FollowLog { - if err := container.StartLogProducer(ctx); err != nil { - return err - } - container.FollowOutput(&LogConsumer{ - Prefix: c.name, - }) - } - - return nil -} - -// Terminate attempts to terminate the agent container. -// This might also include running termination functions for containers associated with the agent. -// On failure, an error will be returned and the reaper process (RYUK) will handle cleanup. -func (c *consulContainerNode) Terminate() error { - // Services might register a termination function that should also fire - // when the "agent" is cleaned up - for _, f := range c.terminateFuncs { - err := f() - if err != nil { - continue - } - } - - if c.container == nil { - return nil - } - - state, err := c.container.State(context.Background()) - if err == nil && state.Running && *utils.FollowLog { - // StopLogProducer can only be called on running containers - err = c.container.StopLogProducer() - if err1 := c.container.Terminate(c.ctx); err == nil { - err = err1 - } - } else { - if err1 := c.container.Terminate(c.ctx); err == nil { - err = err1 - } - } - - c.container = nil - - return err -} - -func (c *consulContainerNode) DataDir() string { - return c.dataDir -} - -func startContainer(ctx context.Context, req testcontainers.ContainerRequest) (testcontainers.Container, error) { - ctx, cancel := context.WithTimeout(ctx, time.Second*40) - defer cancel() - return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ - ContainerRequest: req, - Started: true, - }) -} - -const pauseImage = "k8s.gcr.io/pause:3.3" - -type containerOpts struct { - certDir string - configFile string - dataDir string - hostname string - index int - license string - name string - addtionalNetworks []string -} - -func newContainerRequest(config Config, opts containerOpts) (podRequest, consulRequest testcontainers.ContainerRequest) { - skipReaper := isRYUKDisabled() - - httpPort := "8500" - - pod := testcontainers.ContainerRequest{ - Image: pauseImage, - AutoRemove: false, - Name: opts.name + "-pod", - SkipReaper: skipReaper, - ExposedPorts: []string{httpPort + "/tcp"}, - Hostname: opts.hostname, - Networks: opts.addtionalNetworks, - } - - // For handshakes like auto-encrypt, it can take 10's of seconds for the agent to become "ready". - // If we only wait until the log stream starts, subsequent commands to agents will fail. - // TODO: optimize the wait strategy - app := testcontainers.ContainerRequest{ - NetworkMode: dockercontainer.NetworkMode("container:" + opts.name + "-pod"), - Image: config.Image + ":" + config.Version, - WaitingFor: wait.ForLog(bootLogLine).WithStartupTimeout(60 * time.Second), // See note above - AutoRemove: false, - Name: opts.name, - Mounts: []testcontainers.ContainerMount{ - {Source: testcontainers.DockerBindMountSource{HostPath: opts.certDir}, Target: "/consul/config/certs"}, - {Source: testcontainers.DockerBindMountSource{HostPath: opts.configFile}, Target: "/consul/config/config.json"}, - {Source: testcontainers.DockerBindMountSource{HostPath: opts.dataDir}, Target: "/consul/data"}, - }, - Cmd: config.Cmd, - SkipReaper: skipReaper, - Env: map[string]string{"CONSUL_LICENSE": opts.license}, - } - return pod, app -} - -// isRYUKDisabled returns whether the reaper process (RYUK) has been disabled -// by an environment variable. -// -// https://github.com/testcontainers/moby-ryuk -func isRYUKDisabled() bool { - skipReaperStr := os.Getenv(disableRYUKEnv) - skipReaper, err := strconv.ParseBool(skipReaperStr) - if err != nil { - return false - } - return skipReaper -} - -func readLicense() (string, error) { - license := os.Getenv("CONSUL_LICENSE") - if license == "" { - licensePath := os.Getenv("CONSUL_LICENSE_PATH") - if licensePath != "" { - licenseBytes, err := os.ReadFile(licensePath) - if err != nil { - return "", err - } - license = string(licenseBytes) - } - } - return license, nil -} - -func createConfigFile(JSON string) (string, error) { - tmpDir, err := os.MkdirTemp("", "consul-container-test-config") - if err != nil { - return "", err - } - err = os.Chmod(tmpDir, 0777) - if err != nil { - return "", err - } - err = os.Mkdir(tmpDir+"/config", 0777) - if err != nil { - return "", err - } - configFile := tmpDir + "/config/config.hcl" - err = os.WriteFile(configFile, []byte(JSON), 0644) - if err != nil { - return "", err - } - return configFile, nil -} - -func createCertFile(dir, filename, cert string) error { - filename = filepath.Base(filename) - path := filepath.Join(dir, filename) - err := os.WriteFile(path, []byte(cert), 0644) - if err != nil { - return errors.Wrap(err, "could not write cert file") - } - return nil -} - -type parsedConfig struct { - Datacenter string `json:"datacenter"` - Server bool `json:"server"` -} - -func readSomeConfigFileFields(JSON string) (parsedConfig, error) { - var pc parsedConfig - if err := json.Unmarshal([]byte(JSON), &pc); err != nil { - return pc, errors.Wrap(err, "failed to parse config file") - } - if pc.Datacenter == "" { - pc.Datacenter = "dc1" - } - return pc, nil -} diff --git a/test/integration/consul-container/libs/agent/encryption.go b/test/integration/consul-container/libs/agent/encryption.go deleted file mode 100644 index a486dcb5b8..0000000000 --- a/test/integration/consul-container/libs/agent/encryption.go +++ /dev/null @@ -1,58 +0,0 @@ -package agent - -import ( - "crypto/rand" - "crypto/x509" - "encoding/base64" - "fmt" - "net" - - "github.com/pkg/errors" - - "github.com/hashicorp/consul/tlsutil" -) - -func newSerfEncryptionKey() (string, error) { - key := make([]byte, 32) - n, err := rand.Reader.Read(key) - if err != nil { - return "", errors.Wrap(err, "error reading random data") - } - if n != 32 { - return "", errors.Wrap(err, "couldn't read enough entropy. Generate more entropy!") - } - - return base64.StdEncoding.EncodeToString(key), nil -} - -func newServerTLSKeyPair(dc string, ctx *BuildContext) (string, string, string, string) { - // Generate agent-specific key pair. Borrowed from 'consul tls cert create -server -dc ' - name := fmt.Sprintf("server.%s.%s", dc, "consul") - - dnsNames := []string{ - name, - "localhost", - } - ipAddresses := []net.IP{net.ParseIP("127.0.0.1")} - extKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth} - - signer, err := tlsutil.ParseSigner(ctx.caKey) - if err != nil { - panic("could not parse signer from CA key") - } - - pub, priv, err := tlsutil.GenerateCert(tlsutil.CertOpts{ - Signer: signer, CA: ctx.caCert, Name: name, Days: 365, - DNSNames: dnsNames, IPAddresses: ipAddresses, ExtKeyUsage: extKeyUsage, - }) - - prefix := fmt.Sprintf("%s-server-%s", dc, "consul") - certFileName := fmt.Sprintf("%s-%d.pem", prefix, ctx.index) - keyFileName := fmt.Sprintf("%s-%d-key.pem", prefix, ctx.index) - - if err = tlsutil.Verify(ctx.caCert, pub, name); err != nil { - panic(fmt.Sprintf("could not verify keypair for %s and %s", certFileName, keyFileName)) - } - - return keyFileName, priv, certFileName, pub -} diff --git a/test/integration/consul-container/libs/assert/service.go b/test/integration/consul-container/libs/assert/service.go index ae2c50b8c0..6b97c9d32e 100644 --- a/test/integration/consul-container/libs/assert/service.go +++ b/test/integration/consul-container/libs/assert/service.go @@ -3,13 +3,13 @@ package assert import ( "fmt" "io" - "net/http" "strings" "testing" "time" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/go-cleanhttp" ) const ( @@ -20,12 +20,13 @@ const ( // HTTPServiceEchoes verifies that a post to the given ip/port combination returns the data // in the response body func HTTPServiceEchoes(t *testing.T, ip string, port int) { - phrase := "hello" + const phrase = "hello" + failer := func() *retry.Timer { return &retry.Timer{Timeout: defaultHTTPTimeout, Wait: defaultHTTPWait} } - client := http.DefaultClient + client := cleanhttp.DefaultClient() url := fmt.Sprintf("http://%s:%d", ip, port) retry.RunWith(failer(), t, func(r *retry.R) { diff --git a/test/integration/consul-container/libs/cluster/agent.go b/test/integration/consul-container/libs/cluster/agent.go new file mode 100644 index 0000000000..5dd3319aba --- /dev/null +++ b/test/integration/consul-container/libs/cluster/agent.go @@ -0,0 +1,71 @@ +package cluster + +import ( + "context" + + "github.com/hashicorp/consul/api" + "github.com/testcontainers/testcontainers-go" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" +) + +// Agent represent a Consul agent abstraction +type Agent interface { + GetIP() string + GetClient() *api.Client + GetName() string + GetPod() testcontainers.Container + ClaimAdminPort() int + GetConfig() Config + GetInfo() AgentInfo + GetDatacenter() string + IsServer() bool + RegisterTermination(func() error) + Terminate() error + TerminateAndRetainPod() error + Upgrade(ctx context.Context, config Config) error + Exec(ctx context.Context, cmd []string) (int, error) + DataDir() string +} + +// Config is a set of configurations required to create a Agent +// +// Constructed by (Builder).ToAgentConfig() +type Config struct { + ScratchDir string + CertVolume string + CACert string + JSON string + ConfigBuilder *ConfigBuilder + Image string + Version string + Cmd []string + + // service defaults + UseAPIWithTLS bool // TODO + UseGRPCWithTLS bool +} + +func (c *Config) DockerImage() string { + return utils.DockerImage(c.Image, c.Version) +} + +// Clone copies everything. It is the caller's job to replace fields that +// should be unique. +func (c Config) Clone() Config { + c2 := c + if c.Cmd != nil { + c2.Cmd = make([]string, len(c.Cmd)) + for i, v := range c.Cmd { + c2.Cmd[i] = v + } + } + return c2 +} + +// TODO: refactor away +type AgentInfo struct { + CACertFile string + UseTLSForAPI bool + UseTLSForGRPC bool +} diff --git a/test/integration/consul-container/libs/cluster/app.go b/test/integration/consul-container/libs/cluster/app.go new file mode 100644 index 0000000000..cdcb4bcb55 --- /dev/null +++ b/test/integration/consul-container/libs/cluster/app.go @@ -0,0 +1,138 @@ +package cluster + +import ( + "context" + "fmt" + "time" + + dockercontainer "github.com/docker/docker/api/types/container" + "github.com/docker/go-connections/nat" + "github.com/hashicorp/go-multierror" + "github.com/testcontainers/testcontainers-go" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" +) + +// LaunchInfo is the resutl of LaunchContainerOnNode. +type LaunchInfo struct { + Container testcontainers.Container + IP string + MappedPorts map[string]nat.Port +} + +// LaunchContainerOnNode will run a new container attached to the same network +// namespace as the provided agent, in the same manner in Kubernetes where +// you'd run two containers in the same pod so you can share localhost. +// +// This is supposed to mimic more accurately how consul/CLI/envoy/etc all are +// co-located on localhost with the consul client agent in typical deployment +// topologies. +func LaunchContainerOnNode( + ctx context.Context, + node Agent, + req testcontainers.ContainerRequest, + mapPorts []string, +) (*LaunchInfo, error) { + if req.Name == "" { + return nil, fmt.Errorf("ContainerRequest requires the Name field") + } + if req.NetworkMode != "" { + return nil, fmt.Errorf("caller should not configure ContainerRequest.NetworkMode") + } + + req.NetworkMode = dockercontainer.NetworkMode("container:" + node.GetName() + "-pod") + + pod := node.GetPod() + if pod == nil { + return nil, fmt.Errorf("node Pod is required") + } + + // Do some trickery to ensure that partial completion is correctly torn + // down, but successful execution is not. + var deferClean utils.ResettableDefer + defer deferClean.Execute() + + launchCtx, cancel := context.WithTimeout(ctx, time.Second*40) + defer cancel() + + container, err := testcontainers.GenericContainer(launchCtx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + return nil, err + } + deferClean.Add(func() { + _ = container.Terminate(ctx) + }) + + ip, err := container.ContainerIP(ctx) + if err != nil { + return nil, err + } + + if utils.FollowLog { + if err := container.StartLogProducer(ctx); err != nil { + return nil, err + } + container.FollowOutput(&LogConsumer{ + Prefix: req.Name, + }) + deferClean.Add(func() { + _ = container.StopLogProducer() + }) + } + + ports := make(map[string]nat.Port) + for _, portStr := range mapPorts { + mapped, err := pod.MappedPort(ctx, nat.Port(portStr)) + if err != nil { + return nil, err + } + ports[portStr] = mapped + } + + info := &LaunchInfo{ + Container: container, + IP: ip, + MappedPorts: ports, + } + + node.RegisterTermination(func() error { + return TerminateContainer(ctx, container, true) + }) + + // disable cleanup functions now that we have an object with a Terminate() function + deferClean.Reset() + + return info, nil +} + +// TerminateContainer attempts to terminate the container. On failure, an error +// will be returned and the reaper process (RYUK) will handle cleanup. +func TerminateContainer(ctx context.Context, c testcontainers.Container, stopLogs bool) error { + if c == nil { + return nil + } + + var merr error + + if utils.FollowLog && stopLogs { + if state, err := c.State(ctx); err == nil && state.Running { + // StopLogProducer can only be called on running containers + if err := c.StopLogProducer(); err != nil { + merr = multierror.Append(merr, err) + } + } + } + + if err := c.Stop(ctx, nil); err != nil { + merr = multierror.Append(merr, err) + } + + if err := c.Terminate(ctx); err != nil { + merr = multierror.Append(merr, err) + } + + return merr +} diff --git a/test/integration/consul-container/libs/cluster/builder.go b/test/integration/consul-container/libs/cluster/builder.go new file mode 100644 index 0000000000..9b456c199c --- /dev/null +++ b/test/integration/consul-container/libs/cluster/builder.go @@ -0,0 +1,323 @@ +package cluster + +import ( + "encoding/json" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + "golang.org/x/mod/semver" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" +) + +// TODO: switch from semver to go-version + +const ( + remoteCertDirectory = "/consul/config/certs" + + ConsulCACertPEM = "consul-agent-ca.pem" + ConsulCACertKey = "consul-agent-ca-key.pem" +) + +// BuildContext provides a reusable object meant to share common configuration settings +// between agent configuration builders. +type BuildContext struct { + datacenter string + consulImageName string + consulVersion string + + injectGossipEncryption bool // setup the agents to use a gossip encryption key + encryptKey string + + injectCerts bool // initializes the built-in CA and distributes client certificates to agents + injectAutoEncryption bool // initialize the built-in CA and set up agents to use auto-encrpt + allowHTTPAnyway bool + useAPIWithTLS bool + useGRPCWithTLS bool + + certVolume string + caCert string + tlsCertIndex int // keeps track of the certificates issued for naming purposes +} + +func (c *BuildContext) DockerImage() string { + return utils.DockerImage(c.consulImageName, c.consulVersion) +} + +// BuildOptions define the desired automated test setup overrides that are +// applied across agents in the cluster +type BuildOptions struct { + // Datacenter is the override datacenter for agents. + Datacenter string + + // ConsulImageName is the default Consul image name for agents in the + // cluster when none is specified. + ConsulImageName string + + // ConsulVersion is the default Consul version for agents in the cluster + // when none is specified. + ConsulVersion string + + // InjectGossipEncryption provides a gossip encryption key for all agents. + InjectGossipEncryption bool + + // InjectCerts provides a CA for all agents and (future) agent certs. + // + // It also disables the HTTP API unless AllowHTTPAnyway is enabled. + InjectCerts bool + + // InjectAutoEncryption configures auto-encrypt for TLS and sets up certs. + // Overrides InjectCerts. + // + // It also disables the HTTP API unless AllowHTTPAnyway is enabled. + InjectAutoEncryption bool + + // AllowHTTPAnyway ensures that the HTTP API is enabled even when + // InjectCerts or InjectAutoEncryption are enabled. + AllowHTTPAnyway bool + + // UseAPIWithTLS ensures that any accesses for the JSON API use the https + // port. By default it will not. + UseAPIWithTLS bool + + // UseGRPCWithTLS ensures that any accesses for external gRPC use the + // grpc_tls port. By default it will not. + UseGRPCWithTLS bool +} + +func NewBuildContext(t *testing.T, opts BuildOptions) *BuildContext { + ctx := &BuildContext{ + datacenter: opts.Datacenter, + consulImageName: opts.ConsulImageName, + consulVersion: opts.ConsulVersion, + injectGossipEncryption: opts.InjectGossipEncryption, + injectCerts: opts.InjectCerts, + injectAutoEncryption: opts.InjectAutoEncryption, + allowHTTPAnyway: opts.AllowHTTPAnyway, + useAPIWithTLS: opts.UseAPIWithTLS, + useGRPCWithTLS: opts.UseGRPCWithTLS, + } + + if ctx.consulImageName == "" { + ctx.consulImageName = utils.TargetImageName + } + if ctx.consulVersion == "" { + ctx.consulVersion = utils.TargetVersion + } + + if opts.InjectGossipEncryption { + serfKey, err := newSerfEncryptionKey() + require.NoError(t, err, "could not generate serf encryption key") + ctx.encryptKey = serfKey + } + + if opts.InjectAutoEncryption { + if opts.UseAPIWithTLS { + // TODO: we should improve this + t.Fatalf("Cannot use TLS with the API in conjunction with Auto Encrypt because you would need to use the Connect CA Cert for verification") + } + if opts.UseGRPCWithTLS { + // TODO: we should improve this + t.Fatalf("Cannot use TLS with gRPC in conjunction with Auto Encrypt because you would need to use the Connect CA Cert for verification") + } + } + + if opts.InjectAutoEncryption || opts.InjectCerts { + ctx.createTLSCAFiles(t) + } else { + if opts.UseAPIWithTLS { + t.Fatalf("UseAPIWithTLS requires one of InjectAutoEncryption or InjectCerts to be set") + } + if opts.UseGRPCWithTLS { + t.Fatalf("UseGRPCWithTLS requires one of InjectAutoEncryption or InjectCerts to be set") + } + } + return ctx +} + +type Builder struct { + context *BuildContext // this is non-nil + conf *ConfigBuilder +} + +// NewConfigBuilder instantiates a builder object with sensible defaults for a single consul instance +// This includes the following: +// * default ports with no plaintext options +// * debug logging +// * single server with bootstrap +// * bind to all interfaces, advertise on 'eth0' +// * connect enabled +func NewConfigBuilder(ctx *BuildContext) *Builder { + if ctx == nil { + panic("BuildContext is a required argument") + } + b := &Builder{ + conf: &ConfigBuilder{}, + context: ctx, + } + + b.conf.Set("advertise_addr", `{{ GetInterfaceIP "eth0" }}`) + b.conf.Set("bind_addr", "0.0.0.0") + b.conf.Set("data_dir", "/consul/data") + b.conf.Set("bootstrap", true) + b.conf.Set("client_addr", "0.0.0.0") + b.conf.Set("connect.enabled", true) + b.conf.Set("log_level", "debug") + b.conf.Set("server", true) + + // These are the default ports, disabling plaintext transport + b.conf.Set("ports.dns", 8600) + //nolint:staticcheck + if ctx.certVolume == "" { + b.conf.Set("ports.http", 8500) + b.conf.Set("ports.https", -1) + } else { + b.conf.Set("ports.http", -1) + b.conf.Set("ports.https", 8501) + } + b.conf.Set("ports.grpc", 8502) + b.conf.Set("ports.serf_lan", 8301) + b.conf.Set("ports.serf_wan", 8302) + b.conf.Set("ports.server", 8300) + + if ctx.allowHTTPAnyway { + b.conf.Set("ports.http", 8500) + } + + if ctx.consulVersion == "local" || semver.Compare("v"+ctx.consulVersion, "v1.14.0") >= 0 { + // Enable GRPCTLS for version after v1.14.0 + b.conf.Set("ports.grpc_tls", 8503) + } + + return b +} + +// Advanced lets you directly manipulate specific config settings. +func (b *Builder) Advanced(fn func(*ConfigBuilder)) *Builder { + if fn != nil { + fn(b.conf) + } + return b +} + +func (b *Builder) Bootstrap(servers int) *Builder { + if servers < 1 { + b.conf.Unset("bootstrap") + b.conf.Unset("bootstrap_expect") + } else if servers == 1 { + b.conf.Set("bootstrap", true) + b.conf.Unset("bootstrap_expect") + } else { + b.conf.Unset("bootstrap") + b.conf.Set("bootstrap_expect", servers) + } + return b +} + +func (b *Builder) Client() *Builder { + b.conf.Unset("ports.server") + b.conf.Unset("server") + b.conf.Unset("bootstrap") + b.conf.Unset("bootstrap_expect") + return b +} + +func (b *Builder) Datacenter(name string) *Builder { + b.conf.Set("datacenter", name) + return b +} + +func (b *Builder) Peering(enable bool) *Builder { + b.conf.Set("peering.enabled", enable) + return b +} + +func (b *Builder) RetryJoin(names ...string) *Builder { + b.conf.Set("retry_join", names) + return b +} + +func (b *Builder) Telemetry(statSite string) *Builder { + b.conf.Set("telemetry.statsite_address", statSite) + return b +} + +// ToAgentConfig renders the builders configuration into a string +// representation of the json config file for agents. +func (b *Builder) ToAgentConfig(t *testing.T) *Config { + b.injectContextOptions(t) + + out, err := json.MarshalIndent(b.conf, "", " ") + require.NoError(t, err, "could not generate json config") + + confCopy, err := b.conf.Clone() + require.NoError(t, err) + + return &Config{ + JSON: string(out), + ConfigBuilder: confCopy, + + Cmd: []string{"agent"}, + + Image: b.context.consulImageName, + Version: b.context.consulVersion, + + CertVolume: b.context.certVolume, + CACert: b.context.caCert, + + UseAPIWithTLS: b.context.useAPIWithTLS, + UseGRPCWithTLS: b.context.useGRPCWithTLS, + } +} + +func (b *Builder) injectContextOptions(t *testing.T) { + var dc string + if b.context.datacenter != "" { + b.conf.Set("datacenter", b.context.datacenter) + dc = b.context.datacenter + } + if val, _ := b.conf.GetString("datacenter"); val == "" { + dc = "dc1" + } + b.conf.Set("datacenter", dc) + + server, _ := b.conf.GetBool("server") + + if b.context.encryptKey != "" { + b.conf.Set("encrypt", b.context.encryptKey) + } + + // For any TLS setup, we add the CA to agent conf + if b.context.certVolume != "" { + b.conf.Set("tls.defaults.ca_file", filepath.Join(remoteCertDirectory, ConsulCACertPEM)) + b.conf.Set("tls.defaults.verify_outgoing", true) // Secure settings + b.conf.Set("tls.internal_rpc.verify_server_hostname", true) + } + + // Also for any TLS setup, generate server key pairs from the CA + if b.context.certVolume != "" && server { + keyFileName, certFileName := b.context.createTLSCertFiles(t, dc) + b.context.tlsCertIndex++ + + b.conf.Set("tls.defaults.cert_file", filepath.Join(remoteCertDirectory, certFileName)) + b.conf.Set("tls.defaults.key_file", filepath.Join(remoteCertDirectory, keyFileName)) + b.conf.Set("tls.internal_rpc.verify_incoming", true) // Only applies to servers for auto-encrypt + } + + // This assumes we've already gone through the CA/Cert setup in the previous conditional + if b.context.injectAutoEncryption { + if server { + b.conf.Set("auto_encrypt.allow_tls", true) // This setting is different between client and servers + b.conf.Set("tls.grpc.use_auto_cert", true) // This is required for peering to work over the non-GRPC_TLS port + // VerifyIncoming does not apply to client agents for auto-encrypt + } else { + b.conf.Set("auto_encrypt.tls", true) // This setting is different between client and servers + b.conf.Set("tls.grpc.use_auto_cert", true) // This is required for peering to work over the non-GRPC_TLS port + } + } + + if b.context.injectCerts && !b.context.injectAutoEncryption { + panic("client certificate distribution not implemented") + } +} diff --git a/test/integration/consul-container/libs/cluster/cluster.go b/test/integration/consul-container/libs/cluster/cluster.go index 4588cd5adb..73bd6d4040 100644 --- a/test/integration/consul-container/libs/cluster/cluster.go +++ b/test/integration/consul-container/libs/cluster/cluster.go @@ -2,22 +2,22 @@ package cluster import ( "context" + "encoding/json" + "errors" "fmt" - "io/ioutil" + "os" "path/filepath" + "strconv" "strings" "testing" "time" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/serf/serf" - "github.com/pkg/errors" "github.com/stretchr/testify/require" "github.com/teris-io/shortid" "github.com/testcontainers/testcontainers-go" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - libagent "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" ) // Cluster provides an interface for creating and controlling a Consul cluster @@ -25,75 +25,158 @@ import ( // These fields are public in the event someone might want to surgically // craft a test case. type Cluster struct { - Agents []libagent.Agent - BuildContext *libagent.BuildContext - CACert string - CAKey string - ID string - Index int - Network testcontainers.Network - NetworkName string + Agents []Agent + // BuildContext *BuildContext // TODO + CACert string + CAKey string + ID string + Index int + Network testcontainers.Network + NetworkName string + ScratchDir string +} + +type TestingT interface { + Cleanup(f func()) +} + +func NewN(t TestingT, conf Config, count int) (*Cluster, error) { + var configs []Config + for i := 0; i < count; i++ { + configs = append(configs, conf) + } + + return New(t, configs) } // New creates a Consul cluster. An agent will be started for each of the given // configs and joined to the cluster. // -// A cluster has its own docker network for DNS connectivity, but is also joined -func New(configs []libagent.Config) (*Cluster, error) { +// A cluster has its own docker network for DNS connectivity, but is also +// joined +// +// The provided TestingT is used to register a cleanup function to terminate +// the cluster. +func New(t TestingT, configs []Config) (*Cluster, error) { id, err := shortid.Generate() if err != nil { - return nil, errors.Wrap(err, "could not cluster id") + return nil, fmt.Errorf("could not cluster id: %w", err) } name := fmt.Sprintf("consul-int-cluster-%s", id) - network, err := createNetwork(name) + network, err := createNetwork(t, name) if err != nil { - return nil, errors.Wrap(err, "could not create cluster container network") + return nil, fmt.Errorf("could not create cluster container network: %w", err) } - cluster := Cluster{ + // Rig up one scratch dir for the cluster with auto-cleanup on test exit. + scratchDir, err := os.MkdirTemp("", name) + if err != nil { + return nil, err + } + t.Cleanup(func() { + _ = os.RemoveAll(scratchDir) + }) + err = os.Chmod(scratchDir, 0777) + if err != nil { + return nil, err + } + + cluster := &Cluster{ ID: id, Network: network, NetworkName: name, + ScratchDir: scratchDir, + } + t.Cleanup(func() { + _ = cluster.Terminate() + }) + + if err := cluster.Add(configs, true); err != nil { + return nil, fmt.Errorf("could not start or join all agents: %w", err) } - if err := cluster.Add(configs); err != nil { - return nil, errors.Wrap(err, "could not start or join all agents") + return cluster, nil +} + +func (c *Cluster) AddN(conf Config, count int, join bool) error { + var configs []Config + for i := 0; i < count; i++ { + configs = append(configs, conf) } - return &cluster, nil + return c.Add(configs, join) } // Add starts an agent with the given configuration and joins it with the existing cluster -func (c *Cluster) Add(configs []libagent.Config) error { +func (c *Cluster) Add(configs []Config, serfJoin bool) (xe error) { + if c.Index == 0 && !serfJoin { + return fmt.Errorf("The first call to Cluster.Add must have serfJoin=true") + } - agents := make([]libagent.Agent, len(configs)) + var agents []Agent for idx, conf := range configs { - n, err := libagent.NewConsulContainer(context.Background(), conf, c.NetworkName, c.Index) - if err != nil { - return errors.Wrapf(err, "could not add container index %d", idx) + // Each agent gets it's own area in the cluster scratch. + conf.ScratchDir = filepath.Join(c.ScratchDir, strconv.Itoa(c.Index)) + if err := os.MkdirAll(conf.ScratchDir, 0777); err != nil { + return err } - agents[idx] = n + if err := os.Chmod(conf.ScratchDir, 0777); err != nil { + return err + } + + n, err := NewConsulContainer( + context.Background(), + conf, + c.NetworkName, + c.Index, + ) + if err != nil { + return fmt.Errorf("could not add container index %d: %w", idx, err) + } + agents = append(agents, n) c.Index++ } - if err := c.Join(agents); err != nil { - return errors.Wrapf(err, "could not join agent") + + if serfJoin { + if err := c.Join(agents); err != nil { + return fmt.Errorf("could not join agents to cluster: %w", err) + } + } else { + if err := c.JoinExternally(agents); err != nil { + return fmt.Errorf("could not join agents to cluster: %w", err) + } } + return nil } // Join joins the given agent to the cluster. -func (c *Cluster) Join(agents []libagent.Agent) error { - var joinAddr string - if len(c.Agents) >= 1 { - joinAddr, _ = c.Agents[0].GetAddr() - } else if len(agents) >= 1 { - joinAddr, _ = agents[0].GetAddr() +func (c *Cluster) Join(agents []Agent) error { + return c.join(agents, false) +} +func (c *Cluster) JoinExternally(agents []Agent) error { + return c.join(agents, true) +} +func (c *Cluster) join(agents []Agent, skipSerfJoin bool) error { + if len(agents) == 0 { + return nil // no change } + if len(c.Agents) == 0 { + // Join the rest to the first. + c.Agents = append(c.Agents, agents[0]) + return c.join(agents[1:], skipSerfJoin) + } + + // Always join to the original server. + joinAddr := c.Agents[0].GetIP() + for _, n := range agents { - err := n.GetClient().Agent().Join(joinAddr, false) - if err != nil { - return errors.Wrapf(err, "could not join agent %s to %s", n.GetName(), joinAddr) + if !skipSerfJoin { + err := n.GetClient().Agent().Join(joinAddr, false) + if err != nil { + return fmt.Errorf("could not join agent %s to %s: %w", n.GetName(), joinAddr, err) + } } c.Agents = append(c.Agents, n) } @@ -102,10 +185,10 @@ func (c *Cluster) Join(agents []libagent.Agent) error { // Remove instructs the agent to leave the cluster then removes it // from the cluster Agent list. -func (c *Cluster) Remove(n libagent.Agent) error { +func (c *Cluster) Remove(n Agent) error { err := n.GetClient().Agent().Leave() if err != nil { - return errors.Wrapf(err, "could not remove agent %s", n.GetName()) + return fmt.Errorf("could not remove agent %s: %w", n.GetName(), err) } foundIdx := -1 @@ -128,74 +211,100 @@ func (c *Cluster) Remove(n libagent.Agent) error { // // https://developer.hashicorp.com/consul/docs/upgrading#standard-upgrades // -// - takes a snapshot -// - terminate and rejoin the pod of new version of consul +// - takes a snapshot (which is discarded) +// - terminate and rejoin the pod of a new version of consul +// +// NOTE: we pass in a *testing.T but this method also returns an error. JUST +// within this method when in doubt return an error. A testing assertion should +// be saved only for using t.Cleanup or in a few of the retry-until-working +// helpers below. +// +// This lets us have tests that assert that an upgrade will fail. func (c *Cluster) StandardUpgrade(t *testing.T, ctx context.Context, targetVersion string) error { - retry.RunWith(&retry.Timer{Timeout: 30 * time.Second, Wait: 1 * time.Second}, t, func(r *retry.R) { - // NOTE: to suppress flakiness - execCode, err := c.Agents[0].Exec(context.Background(), []string{"consul", "snapshot", "save", "backup.snap"}) - require.Equal(r, 0, execCode) - require.NoError(r, err) - }) - - // verify only the leader can take a snapshot - snapshotCount := 0 - for _, agent := range c.Agents { - if !agent.IsServer() { - continue - } - - files, err := ioutil.ReadDir(filepath.Join(agent.DataDir(), "raft", "snapshots")) - if err != nil { - return err - } - if len(files) >= 1 { - snapshotCount++ - } + // We take a snapshot, but note that we currently do nothing with it. + execCode, err := c.Agents[0].Exec(context.Background(), []string{"consul", "snapshot", "save", "backup.snap"}) + if execCode != 0 { + return fmt.Errorf("error taking snapshot of the cluster, returned code %d", execCode) + } + if err != nil { + return err } - require.Equalf(t, 1, snapshotCount, "only leader agent can have a snapshot file") // Upgrade individual agent to the target version in the following order // 1. followers // 2. leader // 3. clients (TODO) + + // Grab a client connected to the leader, which we will upgrade last so our + // connection remains ok. leader, err := c.Leader() - client := leader.GetClient() - require.NoError(t, err) - t.Log("Leader name:", leader.GetName()) + if err != nil { + return err + } + t.Logf("Leader name: %s", leader.GetName()) followers, err := c.Followers() - require.NoError(t, err) - t.Log("The number of followers", len(followers)) - - for _, agent := range followers { - t.Log("Upgrade follower", agent.GetName()) + if err != nil { + return err + } + t.Logf("The number of followers = %d", len(followers)) + upgradeFn := func(agent Agent, clientFactory func() *api.Client) error { config := agent.GetConfig() config.Version = targetVersion + + if agent.IsServer() { + // You only ever need bootstrap settings the FIRST time, so we do not need + // them again. + config.ConfigBuilder.Unset("bootstrap") + } else { + // If we upgrade the clients fast enough + // membership might not be gossiped to all of + // the clients to persist into their serf + // snapshot, so force them to rejoin the + // normal way on restart. + config.ConfigBuilder.Set("retry_join", []string{"agent-0"}) + } + + newJSON, err := json.MarshalIndent(config.ConfigBuilder, "", " ") + if err != nil { + return fmt.Errorf("could not re-generate json config: %w", err) + } + config.JSON = string(newJSON) + t.Logf("Upgraded cluster config for %q:\n%s", agent.GetName(), config.JSON) + err = agent.Upgrade(context.Background(), config) if err != nil { return err } + client := clientFactory() + + // wait until the agent rejoin WaitForMembers(t, client, len(c.Agents)) - break + + return nil } - if len(followers) > 0 { - client = followers[0].GetClient() + for _, agent := range followers { + t.Logf("Upgrade follower: %s", agent.GetName()) + + if err := upgradeFn(agent, leader.GetClient); err != nil { + return fmt.Errorf("error upgrading follower %q: %w", agent.GetName(), err) + } } - t.Log("Upgrade leader:", leader.GetName()) - config := leader.GetConfig() - config.Version = targetVersion - err = leader.Upgrade(context.Background(), config) + t.Logf("Upgrade leader: %s", leader.GetName()) + err = upgradeFn(leader, func() *api.Client { + if len(followers) > 0 { + return followers[0].GetClient() + } + return c.APIClient(0) + }) if err != nil { - return err + return fmt.Errorf("error upgrading leader %q: %w", leader.GetName(), err) } - WaitForMembers(t, client, len(c.Agents)) - return nil } @@ -211,15 +320,15 @@ func (c *Cluster) Terminate() error { // Testcontainers seems to clean this the network. // Trigger it now will throw an error while the containers are still shutting down - //if err := c.Network.Remove(context.Background()); err != nil { - // return errors.Wrapf(err, "could not terminate cluster network %s", c.ID) - //} + // if err := c.Network.Remove(context.Background()); err != nil { + // return fmt.Errorf("could not terminate cluster network %s: %w", c.ID, err) + // } return nil } // Leader returns the cluster leader agent, or an error if no leader is // available. -func (c *Cluster) Leader() (libagent.Agent, error) { +func (c *Cluster) Leader() (Agent, error) { if len(c.Agents) < 1 { return nil, fmt.Errorf("no agent available") } @@ -231,7 +340,7 @@ func (c *Cluster) Leader() (libagent.Agent, error) { } for _, n := range c.Agents { - addr, _ := n.GetAddr() + addr := n.GetIP() if strings.Contains(leaderAdd, addr) { return n, nil } @@ -239,35 +348,10 @@ func (c *Cluster) Leader() (libagent.Agent, error) { return nil, fmt.Errorf("leader not found") } -// GetClient returns a consul API client to the node if node is provided. -// Otherwise, GetClient returns the API client to the first node of either -// server or client agent. -func (c *Cluster) GetClient(node libagent.Agent, isServer bool) (*api.Client, error) { - var err error - if node != nil { - return node.GetClient(), err - } - - nodes, err := c.Clients() - if isServer { - nodes, err = c.Servers() - } - - if err != nil { - return nil, fmt.Errorf("unable to get the api client: %s", err) - } - - if len(nodes) <= 0 { - return nil, fmt.Errorf("not enough node: %d", len(nodes)) - } - - return nodes[0].GetClient(), err -} - func getLeader(client *api.Client) (string, error) { leaderAdd, err := client.Status().Leader() if err != nil { - return "", errors.Wrap(err, "could not query leader") + return "", fmt.Errorf("could not query leader: %w", err) } if leaderAdd == "" { return "", errors.New("no leader available") @@ -276,8 +360,8 @@ func getLeader(client *api.Client) (string, error) { } // Followers returns the cluster following servers. -func (c *Cluster) Followers() ([]libagent.Agent, error) { - var followers []libagent.Agent +func (c *Cluster) Followers() ([]Agent, error) { + var followers []Agent leader, err := c.Leader() if err != nil { @@ -293,40 +377,72 @@ func (c *Cluster) Followers() ([]libagent.Agent, error) { } // Servers returns the handle to server agents -func (c *Cluster) Servers() ([]libagent.Agent, error) { - var servers []libagent.Agent +func (c *Cluster) Servers() []Agent { + var servers []Agent for _, n := range c.Agents { if n.IsServer() { servers = append(servers, n) } } - return servers, nil + return servers } // Clients returns the handle to client agents -func (c *Cluster) Clients() ([]libagent.Agent, error) { - var clients []libagent.Agent +func (c *Cluster) Clients() []Agent { + var clients []Agent for _, n := range c.Agents { if !n.IsServer() { clients = append(clients, n) } } - return clients, nil + return clients +} + +func (c *Cluster) APIClient(index int) *api.Client { + nodes := c.Clients() + if len(nodes) == 0 { + nodes = c.Servers() + if len(nodes) == 0 { + return nil + } + } + return nodes[0].GetClient() +} + +// GetClient returns a consul API client to the node if node is provided. +// Otherwise, GetClient returns the API client to the first node of either +// server or client agent. +// +// TODO: see about switching to just APIClient() calls instead? +func (c *Cluster) GetClient(node Agent, isServer bool) (*api.Client, error) { + if node != nil { + return node.GetClient(), nil + } + + nodes := c.Clients() + if isServer { + nodes = c.Servers() + } + + if len(nodes) <= 0 { + return nil, errors.New("no nodes") + } + + return nodes[0].GetClient(), nil } // PeerWithCluster establishes peering with the acceptor cluster func (c *Cluster) PeerWithCluster(acceptingClient *api.Client, acceptingPeerName string, dialingPeerName string) error { - node := c.Agents[0] - dialingClient := node.GetClient() + dialingClient := c.APIClient(0) generateReq := api.PeeringGenerateTokenRequest{ PeerName: acceptingPeerName, } generateRes, _, err := acceptingClient.Peerings().GenerateToken(context.Background(), generateReq, &api.WriteOptions{}) if err != nil { - return fmt.Errorf("error generate token: %v", err) + return fmt.Errorf("error generate token: %w", err) } establishReq := api.PeeringEstablishRequest{ @@ -335,7 +451,7 @@ func (c *Cluster) PeerWithCluster(acceptingClient *api.Client, acceptingPeerName } _, _, err = dialingClient.Peerings().Establish(context.Background(), establishReq, &api.WriteOptions{}) if err != nil { - return fmt.Errorf("error establish peering: %v", err) + return fmt.Errorf("error establish peering: %w", err) } return nil diff --git a/test/integration/consul-container/libs/cluster/config.go b/test/integration/consul-container/libs/cluster/config.go new file mode 100644 index 0000000000..fec5ffacbe --- /dev/null +++ b/test/integration/consul-container/libs/cluster/config.go @@ -0,0 +1,184 @@ +package cluster + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/mitchellh/copystructure" +) + +// TODO: rename file + +type ConfigBuilder struct { + nodes map[string]any +} + +var _ json.Marshaler = (*ConfigBuilder)(nil) + +func (b *ConfigBuilder) Clone() (*ConfigBuilder, error) { + if b.nodes == nil { + return &ConfigBuilder{}, nil + } + + raw, err := copystructure.Copy(b.nodes) + if err != nil { + return nil, err + } + return &ConfigBuilder{ + nodes: raw.(map[string]any), + }, nil +} + +func (b *ConfigBuilder) MarshalJSON() ([]byte, error) { + if b == nil || len(b.nodes) == 0 { + return []byte("{}"), nil + } + + return json.Marshal(b.nodes) +} + +func (b *ConfigBuilder) String() string { + d, err := json.MarshalIndent(b, "", " ") + if err != nil { + return "" + } + return string(d) +} + +func (b *ConfigBuilder) GetString(k string) (string, bool) { + raw, ok := b.Get(k) + if !ok { + return "", false + } + + return raw.(string), true +} + +func (b *ConfigBuilder) GetBool(k string) (bool, bool) { + raw, ok := b.Get(k) + if !ok { + return false, false + } + + return raw.(bool), true +} + +func (b *ConfigBuilder) Get(k string) (any, bool) { + if b.nodes == nil { + return nil, false + } + + parts := strings.Split(k, ".") + + switch len(parts) { + case 0: + return nil, false + case 1: + v, ok := b.nodes[k] + return v, ok + } + + parents, child := parts[0:len(parts)-1], parts[len(parts)-1] + + curr := b.nodes + for _, parent := range parents { + next, ok := curr[parent] + if !ok { + return nil, false + } + curr = next.(map[string]any) + } + + v, ok := curr[child] + return v, ok +} + +func (b *ConfigBuilder) Set(k string, v any) { + if b.nodes == nil { + b.nodes = make(map[string]any) + } + + validateValueType(v) + + parts := strings.Split(k, ".") + + switch len(parts) { + case 0: + return + case 1: + b.nodes[k] = v + return + } + + parents, child := parts[0:len(parts)-1], parts[len(parts)-1] + + curr := b.nodes + for _, parent := range parents { + next, ok := curr[parent] + if ok { + curr = next.(map[string]any) + } else { + next := make(map[string]any) + curr[parent] = next + curr = next + } + } + + curr[child] = v +} + +func validateValueType(v any) { + switch x := v.(type) { + case string: + case int: + case bool: + case []string: + case []any: + for _, item := range x { + validateSliceValueType(item) + } + default: + panic(fmt.Sprintf("unexpected type %T", v)) + } +} + +func validateSliceValueType(v any) { + switch v.(type) { + case string: + case int: + case bool: + case *ConfigBuilder: + default: + panic(fmt.Sprintf("unexpected type %T", v)) + } +} + +func (b *ConfigBuilder) Unset(k string) { + if b.nodes == nil { + return + } + + parts := strings.Split(k, ".") + + switch len(parts) { + case 0: + return + case 1: + delete(b.nodes, k) + return + } + + parents, child := parts[0:len(parts)-1], parts[len(parts)-1] + + curr := b.nodes + for _, parent := range parents { + next, ok := curr[parent] + if !ok { + return + } + curr = next.(map[string]any) + } + + delete(curr, child) +} diff --git a/test/integration/consul-container/libs/cluster/container.go b/test/integration/consul-container/libs/cluster/container.go new file mode 100644 index 0000000000..4e80431c32 --- /dev/null +++ b/test/integration/consul-container/libs/cluster/container.go @@ -0,0 +1,562 @@ +package cluster + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "strconv" + "time" + + dockercontainer "github.com/docker/docker/api/types/container" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/go-multierror" + "github.com/pkg/errors" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" +) + +const bootLogLine = "Consul agent running" +const disableRYUKEnv = "TESTCONTAINERS_RYUK_DISABLED" + +// consulContainerNode implements the Agent interface by running a Consul agent +// in a container. +type consulContainerNode struct { + ctx context.Context + pod testcontainers.Container + container testcontainers.Container + serverMode bool + datacenter string + config Config + podReq testcontainers.ContainerRequest + consulReq testcontainers.ContainerRequest + dataDir string + network string + id int + name string + terminateFuncs []func() error + + client *api.Client + clientAddr string + clientCACertFile string + ip string + + nextAdminPortOffset int + + info AgentInfo +} + +func (c *consulContainerNode) GetPod() testcontainers.Container { + return c.pod +} + +func (c *consulContainerNode) ClaimAdminPort() int { + p := 19000 + c.nextAdminPortOffset + c.nextAdminPortOffset++ + return p +} + +// NewConsulContainer starts a Consul agent in a container with the given config. +func NewConsulContainer(ctx context.Context, config Config, network string, index int) (Agent, error) { + if config.ScratchDir == "" { + return nil, fmt.Errorf("ScratchDir is required") + } + + license, err := readLicense() + if err != nil { + return nil, err + } + + pc, err := readSomeConfigFileFields(config.JSON) + if err != nil { + return nil, err + } + + consulType := "client" + if pc.Server { + consulType = "server" + } + name := utils.RandName(fmt.Sprintf("%s-consul-%s-%d", pc.Datacenter, consulType, index)) + + // Inject new Agent name + config.Cmd = append(config.Cmd, "-node", name) + + tmpDirData := filepath.Join(config.ScratchDir, "data") + if err := os.MkdirAll(tmpDirData, 0777); err != nil { + return nil, fmt.Errorf("error creating data directory %s: %w", tmpDirData, err) + } + if err := os.Chmod(tmpDirData, 0777); err != nil { + return nil, fmt.Errorf("error chowning data directory %s: %w", tmpDirData, err) + } + + var caCertFileForAPI string + if config.CACert != "" { + caCertFileForAPI = filepath.Join(config.ScratchDir, "ca.pem") + if err := os.WriteFile(caCertFileForAPI, []byte(config.CACert), 0644); err != nil { + return nil, fmt.Errorf("error writing out CA cert %s: %w", caCertFileForAPI, err) + } + } + + configFile, err := createConfigFile(config.ScratchDir, config.JSON) + if err != nil { + return nil, fmt.Errorf("error writing out config file %s: %w", configFile, err) + } + + opts := containerOpts{ + name: name, + configFile: configFile, + dataDir: tmpDirData, + license: license, + addtionalNetworks: []string{"bridge", network}, + hostname: fmt.Sprintf("agent-%d", index), + } + podReq, consulReq := newContainerRequest(config, opts) + + // Do some trickery to ensure that partial completion is correctly torn + // down, but successful execution is not. + var deferClean utils.ResettableDefer + defer deferClean.Execute() + + podContainer, err := startContainer(ctx, podReq) + if err != nil { + return nil, fmt.Errorf("error starting pod with image %q: %w", podReq.Image, err) + } + deferClean.Add(func() { + _ = podContainer.Terminate(ctx) + }) + + var ( + httpPort = pc.Ports.HTTP + httpsPort = pc.Ports.HTTPS + + clientAddr string + clientCACertFile string + + info AgentInfo + ) + if httpPort > 0 { + uri, err := podContainer.PortEndpoint(ctx, "8500", "http") + if err != nil { + return nil, err + } + clientAddr = uri + + } else if httpsPort > 0 { + uri, err := podContainer.PortEndpoint(ctx, "8501", "https") + if err != nil { + return nil, err + } + clientAddr = uri + + clientCACertFile = caCertFileForAPI + + } else { + if pc.Server { + return nil, fmt.Errorf("server container does not expose HTTP or HTTPS") + } + } + + if caCertFileForAPI != "" { + if config.UseAPIWithTLS { + if pc.Ports.HTTPS > 0 { + info.UseTLSForAPI = true + } else { + return nil, fmt.Errorf("UseAPIWithTLS is set but ports.https is not for this agent") + } + } + if config.UseGRPCWithTLS { + if pc.Ports.GRPCTLS > 0 { + info.UseTLSForGRPC = true + } else { + return nil, fmt.Errorf("UseGRPCWithTLS is set but ports.grpc_tls is not for this agent") + } + } + info.CACertFile = clientCACertFile + } + + ip, err := podContainer.ContainerIP(ctx) + if err != nil { + return nil, err + } + + consulContainer, err := startContainer(ctx, consulReq) + if err != nil { + return nil, fmt.Errorf("error starting main with image %q: %w", consulReq.Image, err) + } + deferClean.Add(func() { + _ = consulContainer.Terminate(ctx) + }) + + if utils.FollowLog { + if err := consulContainer.StartLogProducer(ctx); err != nil { + return nil, err + } + deferClean.Add(func() { + _ = consulContainer.StopLogProducer() + }) + + consulContainer.FollowOutput(&LogConsumer{ + Prefix: opts.name, + }) + } + + node := &consulContainerNode{ + config: config, + pod: podContainer, + container: consulContainer, + serverMode: pc.Server, + datacenter: pc.Datacenter, + ctx: ctx, + podReq: podReq, + consulReq: consulReq, + dataDir: tmpDirData, + network: network, + id: index, + name: name, + ip: ip, + info: info, + } + + if httpPort > 0 || httpsPort > 0 { + apiConfig := api.DefaultConfig() + apiConfig.Address = clientAddr + if clientCACertFile != "" { + apiConfig.TLSConfig.CAFile = clientCACertFile + } + + apiClient, err := api.NewClient(apiConfig) + if err != nil { + return nil, err + } + + node.client = apiClient + node.clientAddr = clientAddr + node.clientCACertFile = clientCACertFile + } + + // disable cleanup functions now that we have an object with a Terminate() function + deferClean.Reset() + + return node, nil +} + +func (c *consulContainerNode) GetName() string { + if c.container == nil { + return c.consulReq.Name // TODO: is this safe to do all the time? + } + name, err := c.container.Name(c.ctx) + if err != nil { + return "" + } + return name +} + +func (c *consulContainerNode) GetConfig() Config { + return c.config.Clone() +} + +func (c *consulContainerNode) GetDatacenter() string { + return c.datacenter +} + +func (c *consulContainerNode) IsServer() bool { + return c.serverMode +} + +// GetClient returns an API client that can be used to communicate with the Agent. +func (c *consulContainerNode) GetClient() *api.Client { + return c.client +} + +func (c *consulContainerNode) GetAPIAddrInfo() (addr, caCert string) { + return c.clientAddr, c.clientCACertFile +} + +func (c *consulContainerNode) GetInfo() AgentInfo { + return c.info +} + +func (c *consulContainerNode) GetIP() string { + return c.ip +} + +func (c *consulContainerNode) RegisterTermination(f func() error) { + c.terminateFuncs = append(c.terminateFuncs, f) +} + +func (c *consulContainerNode) Exec(ctx context.Context, cmd []string) (int, error) { + exit, _, err := c.container.Exec(ctx, cmd) + return exit, err +} + +func (c *consulContainerNode) Upgrade(ctx context.Context, config Config) error { + if config.ScratchDir == "" { + return fmt.Errorf("ScratchDir is required") + } + + newConfigFile, err := createConfigFile(config.ScratchDir, config.JSON) + if err != nil { + return err + } + + // We'll keep the same pod. + opts := containerOpts{ + name: c.consulReq.Name, + configFile: newConfigFile, + dataDir: c.dataDir, + license: "", + addtionalNetworks: []string{"bridge", c.network}, + hostname: c.consulReq.Hostname, + } + _, consulReq2 := newContainerRequest(config, opts) + consulReq2.Env = c.consulReq.Env // copy license + + // sanity check two fields + if consulReq2.Name != c.consulReq.Name { + return fmt.Errorf("new name %q should match old name %q", consulReq2.Name, c.consulReq.Name) + } + if consulReq2.Hostname != c.consulReq.Hostname { + return fmt.Errorf("new hostname %q should match old hostname %q", consulReq2.Hostname, c.consulReq.Hostname) + } + + if err := c.TerminateAndRetainPod(); err != nil { + return fmt.Errorf("error terminating running container during upgrade: %w", err) + } + + c.consulReq = consulReq2 + + container, err := startContainer(ctx, c.consulReq) + c.ctx = ctx + c.container = container + if err != nil { + return err + } + + if utils.FollowLog { + if err := container.StartLogProducer(ctx); err != nil { + return err + } + container.FollowOutput(&LogConsumer{ + Prefix: opts.name, + }) + } + + return nil +} + +// Terminate attempts to terminate the agent container. +// This might also include running termination functions for containers associated with the agent. +// On failure, an error will be returned and the reaper process (RYUK) will handle cleanup. +func (c *consulContainerNode) Terminate() error { + return c.terminate(false) +} +func (c *consulContainerNode) TerminateAndRetainPod() error { + return c.terminate(true) +} +func (c *consulContainerNode) terminate(retainPod bool) error { + // Services might register a termination function that should also fire + // when the "agent" is cleaned up + for _, f := range c.terminateFuncs { + err := f() + if err != nil { + continue + } + } + + var merr error + if c.container != nil { + if err := TerminateContainer(c.ctx, c.container, true); err != nil { + merr = multierror.Append(merr, err) + } + c.container = nil + } + + if !retainPod && c.pod != nil { + if err := TerminateContainer(c.ctx, c.pod, false); err != nil { + merr = multierror.Append(merr, err) + } + + c.pod = nil + } + + return merr +} + +func (c *consulContainerNode) DataDir() string { + return c.dataDir +} + +func startContainer(ctx context.Context, req testcontainers.ContainerRequest) (testcontainers.Container, error) { + ctx, cancel := context.WithTimeout(ctx, time.Second*40) + defer cancel() + return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) +} + +const pauseImage = "k8s.gcr.io/pause:3.3" + +type containerOpts struct { + configFile string + dataDir string + hostname string + index int + license string + name string + addtionalNetworks []string +} + +func newContainerRequest(config Config, opts containerOpts) (podRequest, consulRequest testcontainers.ContainerRequest) { + skipReaper := isRYUKDisabled() + + pod := testcontainers.ContainerRequest{ + Image: pauseImage, + AutoRemove: false, + Name: opts.name + "-pod", + SkipReaper: skipReaper, + ExposedPorts: []string{ + "8500/tcp", + "8501/tcp", + + "8443/tcp", // Envoy Gateway Listener + + "5000/tcp", // Envoy Connect Listener + "8079/tcp", // Envoy Connect Listener + "8080/tcp", // Envoy Connect Listener + "9998/tcp", // Envoy Connect Listener + "9999/tcp", // Envoy Connect Listener + + "19000/tcp", // Envoy Admin Port + "19001/tcp", // Envoy Admin Port + "19002/tcp", // Envoy Admin Port + "19003/tcp", // Envoy Admin Port + "19004/tcp", // Envoy Admin Port + "19005/tcp", // Envoy Admin Port + "19006/tcp", // Envoy Admin Port + "19007/tcp", // Envoy Admin Port + "19008/tcp", // Envoy Admin Port + "19009/tcp", // Envoy Admin Port + }, + Hostname: opts.hostname, + Networks: opts.addtionalNetworks, + } + + // For handshakes like auto-encrypt, it can take 10's of seconds for the agent to become "ready". + // If we only wait until the log stream starts, subsequent commands to agents will fail. + // TODO: optimize the wait strategy + app := testcontainers.ContainerRequest{ + NetworkMode: dockercontainer.NetworkMode("container:" + opts.name + "-pod"), + Image: config.DockerImage(), + WaitingFor: wait.ForLog(bootLogLine).WithStartupTimeout(60 * time.Second), // See note above + AutoRemove: false, + Name: opts.name, + Mounts: []testcontainers.ContainerMount{ + { + Source: testcontainers.DockerBindMountSource{HostPath: opts.configFile}, + Target: "/consul/config/config.json", + ReadOnly: true, + }, + { + Source: testcontainers.DockerBindMountSource{HostPath: opts.dataDir}, + Target: "/consul/data", + }, + }, + Cmd: config.Cmd, + SkipReaper: skipReaper, + Env: map[string]string{"CONSUL_LICENSE": opts.license}, + } + + if config.CertVolume != "" { + app.Mounts = append(app.Mounts, testcontainers.ContainerMount{ + Source: testcontainers.DockerVolumeMountSource{ + Name: config.CertVolume, + }, + Target: "/consul/config/certs", + ReadOnly: true, + }) + } + + // fmt.Printf("app: %s\n", utils.Dump(app)) + + return pod, app +} + +// isRYUKDisabled returns whether the reaper process (RYUK) has been disabled +// by an environment variable. +// +// https://github.com/testcontainers/moby-ryuk +func isRYUKDisabled() bool { + skipReaperStr := os.Getenv(disableRYUKEnv) + skipReaper, err := strconv.ParseBool(skipReaperStr) + if err != nil { + return false + } + return skipReaper +} + +func readLicense() (string, error) { + if license := os.Getenv("CONSUL_LICENSE"); license != "" { + return license, nil + } + + licensePath := os.Getenv("CONSUL_LICENSE_PATH") + if licensePath == "" { + return "", nil + } + + licenseBytes, err := os.ReadFile(licensePath) + if err != nil { + return "", err + } + return string(licenseBytes), nil +} + +func createConfigFile(scratchDir string, JSON string) (string, error) { + configDir := filepath.Join(scratchDir, "config") + + if err := os.MkdirAll(configDir, 0777); err != nil { + return "", err + } + if err := os.Chmod(configDir, 0777); err != nil { + return "", err + } + + configFile := filepath.Join(configDir, "config.hcl") + + if err := os.WriteFile(configFile, []byte(JSON), 0644); err != nil { + return "", err + } + return configFile, nil +} + +type parsedConfig struct { + Datacenter string `json:"datacenter"` + Server bool `json:"server"` + Ports parsedPorts `json:"ports"` +} + +type parsedPorts struct { + DNS int `json:"dns"` + HTTP int `json:"http"` + HTTPS int `json:"https"` + GRPC int `json:"grpc"` + GRPCTLS int `json:"grpc_tls"` + SerfLAN int `json:"serf_lan"` + SerfWAN int `json:"serf_wan"` + Server int `json:"server"` +} + +func readSomeConfigFileFields(JSON string) (parsedConfig, error) { + var pc parsedConfig + if err := json.Unmarshal([]byte(JSON), &pc); err != nil { + return pc, errors.Wrap(err, "failed to parse config file") + } + if pc.Datacenter == "" { + pc.Datacenter = "dc1" + } + return pc, nil +} diff --git a/test/integration/consul-container/libs/cluster/encryption.go b/test/integration/consul-container/libs/cluster/encryption.go new file mode 100644 index 0000000000..58ccd7e040 --- /dev/null +++ b/test/integration/consul-container/libs/cluster/encryption.go @@ -0,0 +1,132 @@ +package cluster + +import ( + "bytes" + "crypto/rand" + "encoding/base64" + "fmt" + "io" + "path/filepath" + "testing" + + "github.com/hashicorp/go-uuid" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" +) + +const ( + certVolumePrefix = "test-container-certs-" + consulUID = "100" + consulGID = "1000" + consulUserArg = consulUID + ":" + consulGID +) + +func newSerfEncryptionKey() (string, error) { + key := make([]byte, 32) + n, err := rand.Reader.Read(key) + if err != nil { + return "", errors.Wrap(err, "error reading random data") + } + if n != 32 { + return "", errors.Wrap(err, "couldn't read enough entropy. Generate more entropy!") + } + + return base64.StdEncoding.EncodeToString(key), nil +} + +func (c *BuildContext) createTLSCAFiles(t *testing.T) { + id, err := uuid.GenerateUUID() + require.NoError(t, err, "could not create cert volume UUID") + + c.certVolume = certVolumePrefix + id + + // TODO: cleanup anything with the prefix? + + // Create a volume to hold the data. + err = utils.DockerExec([]string{"volume", "create", c.certVolume}, io.Discard) + require.NoError(t, err, "could not create docker volume to hold cert data: %s", c.certVolume) + t.Cleanup(func() { + _ = utils.DockerExec([]string{"volume", "rm", c.certVolume}, io.Discard) + }) + + err = utils.DockerExec([]string{"run", + "--rm", + "-i", + "--net=none", + "-v", c.certVolume + ":/data", + "busybox:latest", + "sh", "-c", + // Need this so the permissions stick; docker seems to treat unused volumes differently. + `touch /data/VOLUME_PLACEHOLDER && chown -R ` + consulUserArg + ` /data`, + }, io.Discard) + require.NoError(t, err, "could not initialize docker volume for cert data: %s", c.certVolume) + + err = utils.DockerExec([]string{"run", + "--rm", + "-i", + "--net=none", + "-u", consulUserArg, + "-v", c.certVolume + ":/data", + "-w", "/data", + "--entrypoint", "", + c.DockerImage(), + "consul", "tls", "ca", "create", + }, io.Discard) + require.NoError(t, err, "could not create TLS certificate authority in docker volume: %s", c.certVolume) + + var w bytes.Buffer + err = utils.DockerExec([]string{"run", + "--rm", + "-i", + "--net=none", + "-u", consulUserArg, + "-v", c.certVolume + ":/data", + "-w", "/data", + "--entrypoint", "", + c.DockerImage(), + "cat", filepath.Join("/data", ConsulCACertPEM), + }, &w) + require.NoError(t, err, "could not extract TLS CA certificate authority public key from docker volume: %s", c.certVolume) + + c.caCert = w.String() +} + +func (c *BuildContext) createTLSCertFiles(t *testing.T, dc string) (keyFileName, certFileName string) { + require.NotEmpty(t, "the CA has not been initialized yet") + + err := utils.DockerExec([]string{"run", + "--rm", + "-i", + "--net=none", + "-u", consulUserArg, + "-v", c.certVolume + ":/data", + "-w", "/data", + "--entrypoint", "", + c.DockerImage(), + "consul", "tls", "cert", "create", "-server", "-dc", dc, + }, io.Discard) + require.NoError(t, err, "could not create TLS server certificate dc=%q in docker volume: %s", dc, c.certVolume) + + prefix := fmt.Sprintf("%s-server-%s", dc, "consul") + certFileName = fmt.Sprintf("%s-%d.pem", prefix, c.tlsCertIndex) + keyFileName = fmt.Sprintf("%s-%d-key.pem", prefix, c.tlsCertIndex) + + for _, fn := range []string{certFileName, keyFileName} { + err = utils.DockerExec([]string{"run", + "--rm", + "-i", + "--net=none", + "-u", consulUserArg, + "-v", c.certVolume + ":/data:ro", + "-w", "/data", + "--entrypoint", "", + c.DockerImage(), + "stat", filepath.Join("/data", fn), + }, io.Discard) + require.NoError(t, err, "Generated TLS cert file %q does not exist in volume", fn) + } + + return keyFileName, certFileName +} diff --git a/test/integration/consul-container/libs/cluster/helpers.go b/test/integration/consul-container/libs/cluster/helpers.go deleted file mode 100644 index f555a676a9..0000000000 --- a/test/integration/consul-container/libs/cluster/helpers.go +++ /dev/null @@ -1,82 +0,0 @@ -package cluster - -import ( - "context" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - libagent "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" - libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -type Options struct { - Datacenter string - NumServer int - NumClient int - Version string -} - -// CreatingPeeringClusterAndSetup creates a cluster with peering enabled -// It also creates and registers a mesh-gateway at the client agent. -// The API client returned is pointed at the client agent. -func CreatingPeeringClusterAndSetup(t *testing.T, clusterOpts *Options) (*Cluster, *api.Client) { - var configs []libagent.Config - - opts := libagent.BuildOptions{ - Datacenter: clusterOpts.Datacenter, - InjectAutoEncryption: true, - InjectGossipEncryption: true, - ConsulVersion: clusterOpts.Version, - } - ctx, err := libagent.NewBuildContext(opts) - require.NoError(t, err) - - numServer := clusterOpts.NumServer - for i := 0; i < numServer; i++ { - serverConf, err := libagent.NewConfigBuilder(ctx). - Bootstrap(numServer). - Peering(true). - RetryJoin(fmt.Sprintf("agent-%d", (i+1)%3)). // Round-robin join the servers - ToAgentConfig() - require.NoError(t, err) - t.Logf("%s server config %d: \n%s", clusterOpts.Datacenter, i, serverConf.JSON) - - configs = append(configs, *serverConf) - } - - // Add a stable client to register the service - clientConf, err := libagent.NewConfigBuilder(ctx). - Client(). - Peering(true). - RetryJoin("agent-0", "agent-1", "agent-2"). - ToAgentConfig() - require.NoError(t, err) - - t.Logf("%s client config: \n%s", clusterOpts.Datacenter, clientConf.JSON) - - configs = append(configs, *clientConf) - - cluster, err := New(configs) - require.NoError(t, err) - cluster.BuildContext = ctx - - client, err := cluster.GetClient(nil, false) - require.NoError(t, err) - WaitForLeader(t, cluster, client) - WaitForMembers(t, client, numServer+1) - - // Default Proxy Settings - ok, err := utils.ApplyDefaultProxySettings(client) - require.NoError(t, err) - require.True(t, ok) - - // Create the mesh gateway for dataplane traffic - clientNodes, _ := cluster.Clients() - _, err = libservice.NewGatewayService(context.Background(), "mesh", "mesh", clientNodes[0]) - require.NoError(t, err) - return cluster, client -} diff --git a/test/integration/consul-container/libs/agent/log.go b/test/integration/consul-container/libs/cluster/log.go similarity index 96% rename from test/integration/consul-container/libs/agent/log.go rename to test/integration/consul-container/libs/cluster/log.go index c46f486b19..721b248808 100644 --- a/test/integration/consul-container/libs/agent/log.go +++ b/test/integration/consul-container/libs/cluster/log.go @@ -1,4 +1,4 @@ -package agent +package cluster import ( "fmt" diff --git a/test/integration/consul-container/libs/cluster/network.go b/test/integration/consul-container/libs/cluster/network.go index 89abf6f7e5..edab30deeb 100644 --- a/test/integration/consul-container/libs/cluster/network.go +++ b/test/integration/consul-container/libs/cluster/network.go @@ -7,7 +7,7 @@ import ( "github.com/testcontainers/testcontainers-go" ) -func createNetwork(name string) (testcontainers.Network, error) { +func createNetwork(t TestingT, name string) (testcontainers.Network, error) { req := testcontainers.GenericNetworkRequest{ NetworkRequest: testcontainers.NetworkRequest{ Name: name, @@ -19,5 +19,8 @@ func createNetwork(name string) (testcontainers.Network, error) { if err != nil { return nil, errors.Wrap(err, "could not create network") } + t.Cleanup(func() { + _ = network.Remove(context.Background()) + }) return network, nil } diff --git a/test/integration/consul-container/libs/service/connect.go b/test/integration/consul-container/libs/service/connect.go index 94607d45c4..b1d74cf3e1 100644 --- a/test/integration/consul-container/libs/service/connect.go +++ b/test/integration/consul-container/libs/service/connect.go @@ -3,14 +3,17 @@ package service import ( "context" "fmt" + "path/filepath" + "strconv" "time" - "github.com/docker/go-connections/nat" - "github.com/hashicorp/consul/api" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" - libnode "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" + "github.com/hashicorp/consul/api" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" + libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -24,6 +27,8 @@ type ConnectContainer struct { serviceName string } +var _ Service = (*ConnectContainer)(nil) + func (g ConnectContainer) GetName() string { name, err := g.container.Name(g.ctx) if err != nil { @@ -47,26 +52,8 @@ func (g ConnectContainer) GetAdminAddr() (string, int) { return "localhost", g.adminPort } -// Terminate attempts to terminate the container. On failure, an error will be -// returned and the reaper process (RYUK) will handle cleanup. func (c ConnectContainer) Terminate() error { - if c.container == nil { - return nil - } - - var err error - if *utils.FollowLog { - err := c.container.StopLogProducer() - if err1 := c.container.Terminate(c.ctx); err == nil { - err = err1 - } - } else { - err = c.container.Terminate(c.ctx) - } - - c.container = nil - - return err + return cluster.TerminateContainer(c.ctx, c.container, true) } func (g ConnectContainer) Export(partition, peer string, client *api.Client) error { @@ -79,10 +66,15 @@ func (g ConnectContainer) GetServiceName() string { // NewConnectService returns a container that runs envoy sidecar, launched by // "consul connect envoy", for service name (serviceName) on the specified -// node. The container exposes port serviceBindPort and envoy admin port (19000) -// by mapping them onto host ports. The container's name has a prefix +// node. The container exposes port serviceBindPort and envoy admin port +// (19000) by mapping them onto host ports. The container's name has a prefix // combining datacenter and name. -func NewConnectService(ctx context.Context, name string, serviceName string, serviceBindPort int, node libnode.Agent) (*ConnectContainer, error) { +func NewConnectService(ctx context.Context, name string, serviceName string, serviceBindPort int, node libcluster.Agent) (*ConnectContainer, error) { + nodeConfig := node.GetConfig() + if nodeConfig.ScratchDir == "" { + return nil, fmt.Errorf("node ScratchDir is required") + } + namePrefix := fmt.Sprintf("%s-service-connect-%s", node.GetDatacenter(), name) containerName := utils.RandName(namePrefix) @@ -97,7 +89,7 @@ func NewConnectService(ctx context.Context, name string, serviceName string, ser } dockerfileCtx.BuildArgs = buildargs - nodeIP, _ := node.GetAddr() + adminPort := node.ClaimAdminPort() req := testcontainers.ContainerRequest{ FromDockerfile: dockerfileCtx, @@ -107,61 +99,61 @@ func NewConnectService(ctx context.Context, name string, serviceName string, ser Cmd: []string{ "consul", "connect", "envoy", "-sidecar-for", serviceName, - "-admin-bind", "0.0.0.0:19000", - "-grpc-addr", fmt.Sprintf("%s:8502", nodeIP), - "-http-addr", fmt.Sprintf("%s:8500", nodeIP), + "-admin-bind", fmt.Sprintf("0.0.0.0:%d", adminPort), "--", - "--log-level", envoyLogLevel}, - ExposedPorts: []string{ - fmt.Sprintf("%d/tcp", serviceBindPort), // Envoy Listener - "19000/tcp", // Envoy Admin Port + "--log-level", envoyLogLevel, }, - } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ - ContainerRequest: req, - Started: true, - }) - if err != nil { - return nil, err + Env: make(map[string]string), } - ip, err := container.ContainerIP(ctx) - if err != nil { - return nil, err - } - - mappedAppPort, err := container.MappedPort(ctx, nat.Port(fmt.Sprintf("%d", serviceBindPort))) - if err != nil { - return nil, err - } - mappedAdminPort, err := container.MappedPort(ctx, nat.Port(fmt.Sprintf("%d", 19000))) - if err != nil { - return nil, err - } - - if *utils.FollowLog { - if err := container.StartLogProducer(ctx); err != nil { - return nil, err - } - container.FollowOutput(&LogConsumer{ - Prefix: containerName, + nodeInfo := node.GetInfo() + if nodeInfo.UseTLSForAPI || nodeInfo.UseTLSForGRPC { + req.Mounts = append(req.Mounts, testcontainers.ContainerMount{ + Source: testcontainers.DockerBindMountSource{ + // See cluster.NewConsulContainer for this info + HostPath: filepath.Join(nodeConfig.ScratchDir, "ca.pem"), + }, + Target: "/ca.pem", + ReadOnly: true, }) } - // Register the termination function the agent so the containers can stop together - terminate := func() error { - return container.Terminate(context.Background()) + if nodeInfo.UseTLSForAPI { + req.Env["CONSUL_HTTP_ADDR"] = fmt.Sprintf("https://127.0.0.1:%d", 8501) + req.Env["CONSUL_HTTP_SSL"] = "1" + req.Env["CONSUL_CACERT"] = "/ca.pem" + } else { + req.Env["CONSUL_HTTP_ADDR"] = fmt.Sprintf("http://127.0.0.1:%d", 8500) + } + + if nodeInfo.UseTLSForGRPC { + req.Env["CONSUL_GRPC_ADDR"] = fmt.Sprintf("https://127.0.0.1:%d", 8503) + req.Env["CONSUL_GRPC_CACERT"] = "/ca.pem" + } else { + req.Env["CONSUL_GRPC_ADDR"] = fmt.Sprintf("http://127.0.0.1:%d", 8502) + } + + var ( + appPortStr = strconv.Itoa(serviceBindPort) + adminPortStr = strconv.Itoa(adminPort) + ) + + info, err := cluster.LaunchContainerOnNode(ctx, node, req, []string{appPortStr, adminPortStr}) + if err != nil { + return nil, err + } + + out := &ConnectContainer{ + ctx: ctx, + container: info.Container, + ip: info.IP, + appPort: info.MappedPorts[appPortStr].Int(), + adminPort: info.MappedPorts[adminPortStr].Int(), + serviceName: name, } - node.RegisterTermination(terminate) fmt.Printf("NewConnectService: name %s, mappedAppPort %d, bind port %d\n", - serviceName, mappedAppPort.Int(), serviceBindPort) + serviceName, out.appPort, serviceBindPort) - return &ConnectContainer{ - container: container, - ip: ip, - appPort: mappedAppPort.Int(), - adminPort: mappedAdminPort.Int(), - serviceName: name, - }, nil + return out, nil } diff --git a/test/integration/consul-container/libs/service/examples.go b/test/integration/consul-container/libs/service/examples.go index 85cb0a8881..62a356da3c 100644 --- a/test/integration/consul-container/libs/service/examples.go +++ b/test/integration/consul-container/libs/service/examples.go @@ -3,14 +3,16 @@ package service import ( "context" "fmt" + "strconv" "time" - "github.com/docker/go-connections/nat" - "github.com/hashicorp/consul/api" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" - libnode "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" + "github.com/hashicorp/consul/api" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" + libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -24,6 +26,8 @@ type exampleContainer struct { serviceName string } +var _ Service = (*exampleContainer)(nil) + func (g exampleContainer) GetName() string { name, err := g.container.Name(g.ctx) if err != nil { @@ -43,40 +47,20 @@ func (g exampleContainer) Start() error { return g.container.Start(context.Background()) } -// Terminate attempts to terminate the container. On failure, an error will be -// returned and the reaper process (RYUK) will handle cleanup. func (c exampleContainer) Terminate() error { - if c.container == nil { - return nil - } - - var err error - if *utils.FollowLog { - err = c.container.StopLogProducer() - if err1 := c.container.Terminate(c.ctx); err1 == nil { - err = err1 - } - } else { - err = c.container.Terminate(c.ctx) - } - - c.container = nil - - return err + return cluster.TerminateContainer(c.ctx, c.container, true) } func (g exampleContainer) Export(partition, peerName string, client *api.Client) error { config := &api.ExportedServicesConfigEntry{ Name: partition, - Services: []api.ExportedService{ - { - Name: g.GetServiceName(), - Consumers: []api.ServiceConsumer{ - // TODO: need to handle the changed field name in 1.13 - {Peer: peerName}, - }, + Services: []api.ExportedService{{ + Name: g.GetServiceName(), + Consumers: []api.ServiceConsumer{ + // TODO: need to handle the changed field name in 1.13 + {Peer: peerName}, }, - }, + }}, } _, _, err := client.ConfigEntries().Set(config, &api.WriteOptions{}) @@ -87,57 +71,49 @@ func (g exampleContainer) GetServiceName() string { return g.serviceName } -func NewExampleService(ctx context.Context, name string, httpPort int, grpcPort int, node libnode.Agent) (Service, error) { +func NewExampleService(ctx context.Context, name string, httpPort int, grpcPort int, node libcluster.Agent) (Service, error) { namePrefix := fmt.Sprintf("%s-service-example-%s", node.GetDatacenter(), name) containerName := utils.RandName(namePrefix) + pod := node.GetPod() + if pod == nil { + return nil, fmt.Errorf("node Pod is required") + } + + var ( + httpPortStr = strconv.Itoa(httpPort) + grpcPortStr = strconv.Itoa(grpcPort) + ) + req := testcontainers.ContainerRequest{ Image: hashicorpDockerProxy + "/fortio/fortio", WaitingFor: wait.ForLog("").WithStartupTimeout(10 * time.Second), AutoRemove: false, Name: containerName, - Cmd: []string{"server", "-http-port", fmt.Sprintf("%d", httpPort), "-grpc-port", fmt.Sprintf("%d", grpcPort), "-redirect-port", "-disabled"}, - Env: map[string]string{"FORTIO_NAME": name}, - ExposedPorts: []string{ - fmt.Sprintf("%d/tcp", httpPort), // HTTP Listener - fmt.Sprintf("%d/tcp", grpcPort), // GRPC Listener + Cmd: []string{ + "server", + "-http-port", httpPortStr, + "-grpc-port", grpcPortStr, + "-redirect-port", "-disabled", }, + Env: map[string]string{"FORTIO_NAME": name}, } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ - ContainerRequest: req, - Started: true, - }) - if err != nil { - return nil, err - } - ip, err := container.ContainerIP(ctx) - if err != nil { - return nil, err - } - mappedHTPPPort, err := container.MappedPort(ctx, nat.Port(fmt.Sprintf("%d", httpPort))) + + info, err := cluster.LaunchContainerOnNode(ctx, node, req, []string{httpPortStr, grpcPortStr}) if err != nil { return nil, err } - mappedGRPCPort, err := container.MappedPort(ctx, nat.Port(fmt.Sprintf("%d", grpcPort))) - if err != nil { - return nil, err + out := &exampleContainer{ + ctx: ctx, + container: info.Container, + ip: info.IP, + httpPort: info.MappedPorts[httpPortStr].Int(), + grpcPort: info.MappedPorts[grpcPortStr].Int(), + serviceName: name, } - if *utils.FollowLog { - if err := container.StartLogProducer(ctx); err != nil { - return nil, err - } - container.FollowOutput(&LogConsumer{ - Prefix: containerName, - }) - } + fmt.Printf("Example service exposed http port %d, gRPC port %d\n", out.httpPort, out.grpcPort) - terminate := func() error { - return container.Terminate(context.Background()) - } - node.RegisterTermination(terminate) - - fmt.Printf("Example service exposed http port %d, gRPC port %d\n", mappedHTPPPort.Int(), mappedGRPCPort.Int()) - return &exampleContainer{container: container, ip: ip, httpPort: mappedHTPPPort.Int(), grpcPort: mappedGRPCPort.Int(), serviceName: name}, nil + return out, nil } diff --git a/test/integration/consul-container/libs/service/gateway.go b/test/integration/consul-container/libs/service/gateway.go index 232619e7bf..77c945c047 100644 --- a/test/integration/consul-container/libs/service/gateway.go +++ b/test/integration/consul-container/libs/service/gateway.go @@ -3,13 +3,17 @@ package service import ( "context" "fmt" + "path/filepath" + "strconv" "time" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" "github.com/hashicorp/consul/api" - libnode "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" + + "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" + libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -19,10 +23,12 @@ type gatewayContainer struct { container testcontainers.Container ip string port int - req testcontainers.ContainerRequest + adminPort int serviceName string } +var _ Service = (*gatewayContainer)(nil) + func (g gatewayContainer) GetName() string { name, err := g.container.Name(g.ctx) if err != nil { @@ -35,6 +41,10 @@ func (g gatewayContainer) GetAddr() (string, int) { return g.ip, g.port } +func (g gatewayContainer) GetAdminAddr() (string, int) { + return "localhost", g.adminPort +} + func (g gatewayContainer) Start() error { if g.container == nil { return fmt.Errorf("container has not been initialized") @@ -42,26 +52,8 @@ func (g gatewayContainer) Start() error { return g.container.Start(context.Background()) } -// Terminate attempts to terminate the container. On failure, an error will be -// returned and the reaper process (RYUK) will handle cleanup. func (c gatewayContainer) Terminate() error { - if c.container == nil { - return nil - } - - var err error - if *utils.FollowLog { - err = c.container.StopLogProducer() - if err1 := c.container.Terminate(c.ctx); err == nil { - err = err1 - } - } else { - err = c.container.Terminate(c.ctx) - } - - c.container = nil - - return err + return cluster.TerminateContainer(c.ctx, c.container, true) } func (g gatewayContainer) Export(partition, peer string, client *api.Client) error { @@ -72,7 +64,12 @@ func (g gatewayContainer) GetServiceName() string { return g.serviceName } -func NewGatewayService(ctx context.Context, name string, kind string, node libnode.Agent) (Service, error) { +func NewGatewayService(ctx context.Context, name string, kind string, node libcluster.Agent) (Service, error) { + nodeConfig := node.GetConfig() + if nodeConfig.ScratchDir == "" { + return nil, fmt.Errorf("node ScratchDir is required") + } + namePrefix := fmt.Sprintf("%s-service-gateway-%s", node.GetDatacenter(), name) containerName := utils.RandName(namePrefix) @@ -87,7 +84,7 @@ func NewGatewayService(ctx context.Context, name string, kind string, node libno } dockerfileCtx.BuildArgs = buildargs - nodeIP, _ := node.GetAddr() + adminPort := node.ClaimAdminPort() req := testcontainers.ContainerRequest{ FromDockerfile: dockerfileCtx, @@ -100,45 +97,61 @@ func NewGatewayService(ctx context.Context, name string, kind string, node libno "-register", "-service", name, "-address", "{{ GetInterfaceIP \"eth0\" }}:8443", - fmt.Sprintf("-grpc-addr=%s:%d", nodeIP, 8502), - "-admin-bind", "0.0.0.0:19000", + "-admin-bind", fmt.Sprintf("0.0.0.0:%d", adminPort), "--", - "--log-level", envoyLogLevel}, - Env: map[string]string{"CONSUL_HTTP_ADDR": fmt.Sprintf("%s:%d", nodeIP, 8500)}, - ExposedPorts: []string{ - "8443/tcp", // Envoy Gateway Listener - "19000/tcp", // Envoy Admin Port + "--log-level", envoyLogLevel, }, + Env: make(map[string]string), } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ - ContainerRequest: req, - Started: true, + + nodeInfo := node.GetInfo() + if nodeInfo.UseTLSForAPI || nodeInfo.UseTLSForGRPC { + req.Mounts = append(req.Mounts, testcontainers.ContainerMount{ + Source: testcontainers.DockerBindMountSource{ + // See cluster.NewConsulContainer for this info + HostPath: filepath.Join(nodeConfig.ScratchDir, "ca.pem"), + }, + Target: "/ca.pem", + ReadOnly: true, + }) + } + + if nodeInfo.UseTLSForAPI { + req.Env["CONSUL_HTTP_ADDR"] = fmt.Sprintf("https://127.0.0.1:%d", 8501) + req.Env["CONSUL_HTTP_SSL"] = "1" + req.Env["CONSUL_CACERT"] = "/ca.pem" + } else { + req.Env["CONSUL_HTTP_ADDR"] = fmt.Sprintf("http://127.0.0.1:%d", 8500) + } + + if nodeInfo.UseTLSForGRPC { + req.Env["CONSUL_GRPC_ADDR"] = fmt.Sprintf("https://127.0.0.1:%d", 8503) + req.Env["CONSUL_GRPC_CACERT"] = "/ca.pem" + } else { + req.Env["CONSUL_GRPC_ADDR"] = fmt.Sprintf("http://127.0.0.1:%d", 8502) + } + + var ( + portStr = "8443" + adminPortStr = strconv.Itoa(adminPort) + ) + + info, err := cluster.LaunchContainerOnNode(ctx, node, req, []string{ + portStr, + adminPortStr, }) if err != nil { return nil, err } - ip, err := container.ContainerIP(ctx) - if err != nil { - return nil, err - } - mappedPort, err := container.MappedPort(ctx, "8443") - if err != nil { - return nil, err + + out := &gatewayContainer{ + ctx: ctx, + container: info.Container, + ip: info.IP, + port: info.MappedPorts[portStr].Int(), + adminPort: info.MappedPorts[adminPortStr].Int(), + serviceName: name, } - if *utils.FollowLog { - if err := container.StartLogProducer(ctx); err != nil { - return nil, err - } - container.FollowOutput(&LogConsumer{ - Prefix: containerName, - }) - } - - terminate := func() error { - return container.Terminate(context.Background()) - } - node.RegisterTermination(terminate) - - return &gatewayContainer{container: container, ip: ip, port: mappedPort.Int(), serviceName: name}, nil + return out, nil } diff --git a/test/integration/consul-container/libs/service/helpers.go b/test/integration/consul-container/libs/service/helpers.go index 92e35079c4..b41af48f35 100644 --- a/test/integration/consul-container/libs/service/helpers.go +++ b/test/integration/consul-container/libs/service/helpers.go @@ -4,61 +4,49 @@ import ( "context" "fmt" "io" - "net/http" "github.com/hashicorp/consul/api" - libnode "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" + "github.com/hashicorp/go-cleanhttp" + + libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) -func CreateAndRegisterStaticServerAndSidecar(node libnode.Agent) (Service, Service, error) { +func CreateAndRegisterStaticServerAndSidecar(node libcluster.Agent) (Service, Service, error) { + // Do some trickery to ensure that partial completion is correctly torn + // down, but successful execution is not. + var deferClean utils.ResettableDefer + defer deferClean.Execute() + // Create a service and proxy instance serverService, err := NewExampleService(context.Background(), "static-server", 8080, 8079, node) if err != nil { return nil, nil, err } + deferClean.Add(func() { + _ = serverService.Terminate() + }) serverConnectProxy, err := NewConnectService(context.Background(), "static-server-sidecar", "static-server", 8080, node) // bindPort not used if err != nil { return nil, nil, err } - - serverServiceIP, _ := serverService.GetAddr() - serverConnectProxyIP, _ := serverConnectProxy.GetAddr() + deferClean.Add(func() { + _ = serverConnectProxy.Terminate() + }) // Register the static-server service and sidecar req := &api.AgentServiceRegistration{ - Name: "static-server", - Port: 8080, - Address: serverServiceIP, + Name: "static-server", + Port: 8080, Connect: &api.AgentServiceConnect{ SidecarService: &api.AgentServiceRegistration{ - Name: "static-server-sidecar-proxy", - Port: 20000, - Address: serverConnectProxyIP, - Kind: api.ServiceKindConnectProxy, - Checks: api.AgentServiceChecks{ - &api.AgentServiceCheck{ - Name: "Connect Sidecar Listening", - TCP: fmt.Sprintf("%s:%d", serverConnectProxyIP, 20000), - Interval: "10s", - Status: api.HealthPassing, - }, - &api.AgentServiceCheck{ - Name: "Connect Sidecar Aliasing Static Server", - AliasService: "static-server", - Status: api.HealthPassing, - }, - }, - Proxy: &api.AgentServiceConnectProxyConfig{ - DestinationServiceName: "static-server", - LocalServiceAddress: serverServiceIP, - LocalServicePort: 8080, - }, + Proxy: &api.AgentServiceConnectProxyConfig{}, }, }, Check: &api.AgentServiceCheck{ Name: "Static Server Listening", - TCP: fmt.Sprintf("%s:%d", serverServiceIP, 8080), + TCP: fmt.Sprintf("127.0.0.1:%d", 8080), Interval: "10s", Status: api.HealthPassing, }, @@ -69,17 +57,30 @@ func CreateAndRegisterStaticServerAndSidecar(node libnode.Agent) (Service, Servi return serverService, serverConnectProxy, err } + // disable cleanup functions now that we have an object with a Terminate() function + deferClean.Reset() + return serverService, serverConnectProxy, nil } -func CreateAndRegisterStaticClientSidecar(node libnode.Agent, peerName string, localMeshGateway bool) (*ConnectContainer, error) { +func CreateAndRegisterStaticClientSidecar( + node libcluster.Agent, + peerName string, + localMeshGateway bool, +) (*ConnectContainer, error) { + // Do some trickery to ensure that partial completion is correctly torn + // down, but successful execution is not. + var deferClean utils.ResettableDefer + defer deferClean.Execute() + // Create a service and proxy instance clientConnectProxy, err := NewConnectService(context.Background(), "static-client-sidecar", "static-client", 5000, node) if err != nil { return nil, err } - - clientConnectProxyIP, _ := clientConnectProxy.GetAddr() + deferClean.Add(func() { + _ = clientConnectProxy.Terminate() + }) mgwMode := api.MeshGatewayModeRemote if localMeshGateway { @@ -92,33 +93,19 @@ func CreateAndRegisterStaticClientSidecar(node libnode.Agent, peerName string, l Port: 8080, Connect: &api.AgentServiceConnect{ SidecarService: &api.AgentServiceRegistration{ - Name: "static-client-sidecar-proxy", - Port: 20000, - Kind: api.ServiceKindConnectProxy, - Checks: api.AgentServiceChecks{ - &api.AgentServiceCheck{ - Name: "Connect Sidecar Listening", - TCP: fmt.Sprintf("%s:%d", clientConnectProxyIP, 20000), - Interval: "10s", - Status: api.HealthPassing, - }, - }, Proxy: &api.AgentServiceConnectProxyConfig{ - Upstreams: []api.Upstream{ - { - DestinationName: "static-server", - DestinationPeer: peerName, - LocalBindAddress: "0.0.0.0", - LocalBindPort: 5000, - MeshGateway: api.MeshGatewayConfig{ - Mode: mgwMode, - }, + Upstreams: []api.Upstream{{ + DestinationName: "static-server", + DestinationPeer: peerName, + LocalBindAddress: "0.0.0.0", + LocalBindPort: 5000, + MeshGateway: api.MeshGatewayConfig{ + Mode: mgwMode, }, - }, + }}, }, }, }, - Checks: api.AgentServiceChecks{}, } err = node.GetClient().Agent().ServiceRegister(req) @@ -126,11 +113,14 @@ func CreateAndRegisterStaticClientSidecar(node libnode.Agent, peerName string, l return clientConnectProxy, err } + // disable cleanup functions now that we have an object with a Terminate() function + deferClean.Reset() + return clientConnectProxy, nil } func GetEnvoyConfigDump(port int) (string, error) { - client := http.DefaultClient + client := cleanhttp.DefaultClient() url := fmt.Sprintf("http://localhost:%d/config_dump?include_eds", port) res, err := client.Get(url) diff --git a/test/integration/consul-container/libs/service/service.go b/test/integration/consul-container/libs/service/service.go index 94dfb6c95f..30b4a79503 100644 --- a/test/integration/consul-container/libs/service/service.go +++ b/test/integration/consul-container/libs/service/service.go @@ -1,8 +1,6 @@ package service -import ( - "github.com/hashicorp/consul/api" -) +import "github.com/hashicorp/consul/api" // Service represents a process that will be registered with the // Consul catalog, including Consul components such as sidecars and gateways diff --git a/test/integration/consul-container/libs/topology/peering_topology.go b/test/integration/consul-container/libs/topology/peering_topology.go new file mode 100644 index 0000000000..d55ce12f7a --- /dev/null +++ b/test/integration/consul-container/libs/topology/peering_topology.go @@ -0,0 +1,210 @@ +package topology + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/require" + + libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" + libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" + libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" +) + +const ( + AcceptingPeerName = "accepting-to-dialer" + DialingPeerName = "dialing-to-acceptor" +) + +type BuiltCluster struct { + Cluster *libcluster.Cluster + Context *libcluster.BuildContext + Service libservice.Service + Container *libservice.ConnectContainer +} + +// BasicPeeringTwoClustersSetup sets up a scenario for testing peering, which consists of +// +// - an accepting cluster with 3 servers and 1 client agent. The client should be used to +// host a service for export: staticServerSvc. +// - an dialing cluster with 1 server and 1 client. The client should be used to host a +// service connecting to staticServerSvc. +// - Create the peering, export the service from accepting cluster, and verify service +// connectivity. +// +// It returns objects of the accepting cluster, dialing cluster, staticServerSvc, and staticClientSvcSidecar +func BasicPeeringTwoClustersSetup( + t *testing.T, + consulVersion string, +) (*BuiltCluster, *BuiltCluster) { + acceptingCluster, acceptingCtx, acceptingClient := NewPeeringCluster(t, "dc1", 3, consulVersion) + dialingCluster, dialingCtx, dialingClient := NewPeeringCluster(t, "dc2", 1, consulVersion) + require.NoError(t, dialingCluster.PeerWithCluster(acceptingClient, AcceptingPeerName, DialingPeerName)) + + libassert.PeeringStatus(t, acceptingClient, AcceptingPeerName, api.PeeringStateActive) + // libassert.PeeringExports(t, acceptingClient, acceptingPeerName, 1) + + // Register an static-server service in acceptingCluster and export to dialing cluster + var serverSidecarService libservice.Service + { + clientNode := acceptingCluster.Clients()[0] + + // Create a service and proxy instance + var err error + serverSidecarService, _, err := libservice.CreateAndRegisterStaticServerAndSidecar(clientNode) + require.NoError(t, err) + + libassert.CatalogServiceExists(t, acceptingClient, "static-server") + libassert.CatalogServiceExists(t, acceptingClient, "static-server-sidecar-proxy") + + require.NoError(t, serverSidecarService.Export("default", AcceptingPeerName, acceptingClient)) + + } + + // Register an static-client service in dialing cluster and set upstream to static-server service + var clientSidecarService *libservice.ConnectContainer + { + clientNode := dialingCluster.Clients()[0] + + // Create a service and proxy instance + var err error + clientSidecarService, err = libservice.CreateAndRegisterStaticClientSidecar(clientNode, DialingPeerName, true) + require.NoError(t, err) + + libassert.CatalogServiceExists(t, dialingClient, "static-client-sidecar-proxy") + } + + _, port := clientSidecarService.GetAddr() + libassert.HTTPServiceEchoes(t, "localhost", port) + + return &BuiltCluster{ + Cluster: acceptingCluster, + Context: acceptingCtx, + Service: serverSidecarService, + Container: nil, + }, + &BuiltCluster{ + Cluster: dialingCluster, + Context: dialingCtx, + Service: nil, + Container: clientSidecarService, + } +} + +// NewDialingCluster creates a cluster for peering with a single dev agent +// TODO: note: formerly called CreatingPeeringClusterAndSetup +// +// Deprecated: use NewPeeringCluster mostly +func NewDialingCluster( + t *testing.T, + version string, + dialingPeerName string, +) (*libcluster.Cluster, *api.Client, libservice.Service) { + t.Helper() + t.Logf("creating the dialing cluster") + + opts := libcluster.BuildOptions{ + Datacenter: "dc2", + InjectAutoEncryption: true, + InjectGossipEncryption: true, + AllowHTTPAnyway: true, + ConsulVersion: version, + } + ctx := libcluster.NewBuildContext(t, opts) + + conf := libcluster.NewConfigBuilder(ctx). + Peering(true). + ToAgentConfig(t) + t.Logf("dc2 server config: \n%s", conf.JSON) + + cluster, err := libcluster.NewN(t, *conf, 1) + require.NoError(t, err) + + node := cluster.Agents[0] + client := node.GetClient() + libcluster.WaitForLeader(t, cluster, client) + libcluster.WaitForMembers(t, client, 1) + + // Default Proxy Settings + ok, err := utils.ApplyDefaultProxySettings(client) + require.NoError(t, err) + require.True(t, ok) + + // Create the mesh gateway for dataplane traffic + _, err = libservice.NewGatewayService(context.Background(), "mesh", "mesh", node) + require.NoError(t, err) + + // Create a service and proxy instance + clientProxyService, err := libservice.CreateAndRegisterStaticClientSidecar(node, dialingPeerName, true) + require.NoError(t, err) + + libassert.CatalogServiceExists(t, client, "static-client-sidecar-proxy") + + return cluster, client, clientProxyService +} + +// NewPeeringCluster creates a cluster with peering enabled. It also creates +// and registers a mesh-gateway at the client agent. The API client returned is +// pointed at the client agent. +func NewPeeringCluster( + t *testing.T, + datacenter string, + numServers int, + version string, +) (*libcluster.Cluster, *libcluster.BuildContext, *api.Client) { + require.NotEmpty(t, datacenter) + require.True(t, numServers > 0) + + opts := libcluster.BuildOptions{ + Datacenter: datacenter, + InjectAutoEncryption: true, + InjectGossipEncryption: true, + AllowHTTPAnyway: true, + ConsulVersion: version, + } + ctx := libcluster.NewBuildContext(t, opts) + + serverConf := libcluster.NewConfigBuilder(ctx). + Bootstrap(numServers). + Peering(true). + ToAgentConfig(t) + t.Logf("%s server config: \n%s", datacenter, serverConf.JSON) + + cluster, err := libcluster.NewN(t, *serverConf, numServers) + require.NoError(t, err) + + var retryJoin []string + for i := 0; i < numServers; i++ { + retryJoin = append(retryJoin, fmt.Sprintf("agent-%d", i)) + } + + // Add a stable client to register the service + clientConf := libcluster.NewConfigBuilder(ctx). + Client(). + Peering(true). + RetryJoin(retryJoin...). + ToAgentConfig(t) + t.Logf("%s server config: \n%s", datacenter, clientConf.JSON) + + require.NoError(t, cluster.AddN(*clientConf, 1, true)) + + // Use the client agent as the HTTP endpoint since we will not rotate it in many tests. + clientNode := cluster.Agents[numServers] + client := clientNode.GetClient() + libcluster.WaitForLeader(t, cluster, client) + libcluster.WaitForMembers(t, client, numServers+1) + + // Default Proxy Settings + ok, err := utils.ApplyDefaultProxySettings(client) + require.NoError(t, err) + require.True(t, ok) + + // Create the mesh gateway for dataplane traffic + _, err = libservice.NewGatewayService(context.Background(), "mesh", "mesh", clientNode) + require.NoError(t, err) + + return cluster, ctx, client +} diff --git a/test/integration/consul-container/libs/utils/debug.go b/test/integration/consul-container/libs/utils/debug.go new file mode 100644 index 0000000000..809d2205f3 --- /dev/null +++ b/test/integration/consul-container/libs/utils/debug.go @@ -0,0 +1,12 @@ +package utils + +import "encoding/json" + +// Dump pretty prints the provided arg as json. +func Dump(v any) string { + b, err := json.MarshalIndent(v, "", " ") + if err != nil { + return "" + } + return string(b) +} diff --git a/test/integration/consul-container/libs/utils/defer.go b/test/integration/consul-container/libs/utils/defer.go new file mode 100644 index 0000000000..a1b011abf7 --- /dev/null +++ b/test/integration/consul-container/libs/utils/defer.go @@ -0,0 +1,28 @@ +package utils + +// ResettableDefer is a way to capture a series of cleanup functions and +// bulk-cancel them. Ideal to use in a long constructor function before the +// overall Close/Stop/Terminate method is ready to use to tear down all of the +// portions properly. +type ResettableDefer struct { + cleanupFns []func() +} + +// Add registers another function to call at Execute time. +func (d *ResettableDefer) Add(f func()) { + d.cleanupFns = append(d.cleanupFns, f) +} + +// Reset clears the pending defer work. +func (d *ResettableDefer) Reset() { + d.cleanupFns = nil +} + +// Execute actually executes the functions registered by Add in the reverse +// order of their call order (like normal defer blocks). +func (d *ResettableDefer) Execute() { + // Run these in reverse order, like defer blocks. + for i := len(d.cleanupFns) - 1; i >= 0; i-- { + d.cleanupFns[i]() + } +} diff --git a/test/integration/consul-container/libs/utils/docker.go b/test/integration/consul-container/libs/utils/docker.go new file mode 100644 index 0000000000..da6b4b79a4 --- /dev/null +++ b/test/integration/consul-container/libs/utils/docker.go @@ -0,0 +1,38 @@ +package utils + +import ( + "bytes" + "fmt" + "io" + "os" + "os/exec" +) + +// DockerExec simply shell out to the docker CLI binary on your host. +func DockerExec(args []string, stdout io.Writer) error { + return cmdExec("docker", "docker", args, stdout, "") +} + +func cmdExec(name, binary string, args []string, stdout io.Writer, dir string) error { + if binary == "" { + panic("binary named " + name + " was not detected") + } + var errWriter bytes.Buffer + + if stdout == nil { + stdout = os.Stdout + } + + cmd := exec.Command(binary, args...) + if dir != "" { + cmd.Dir = dir + } + cmd.Stdout = stdout + cmd.Stderr = &errWriter + cmd.Stdin = nil + if err := cmd.Run(); err != nil { + return fmt.Errorf("could not invoke %q: %v : %s", name, err, errWriter.String()) + } + + return nil +} diff --git a/test/integration/consul-container/libs/utils/utils.go b/test/integration/consul-container/libs/utils/utils.go index c95307e490..ec52163c36 100644 --- a/test/integration/consul-container/libs/utils/utils.go +++ b/test/integration/consul-container/libs/utils/utils.go @@ -10,6 +10,9 @@ import ( func RandName(name string) string { shortID, err := shortid.New(1, shortid.DefaultABC, 6666) + if err != nil { + return "" + } id, err := shortID.Generate() if err != nil { return "" diff --git a/test/integration/consul-container/libs/utils/version.go b/test/integration/consul-container/libs/utils/version.go new file mode 100644 index 0000000000..51bd781702 --- /dev/null +++ b/test/integration/consul-container/libs/utils/version.go @@ -0,0 +1,47 @@ +package utils + +import ( + "flag" + + "github.com/hashicorp/go-version" +) + +var ( + TargetImageName string + TargetVersion string + + LatestImageName string + LatestVersion string + + FollowLog bool +) + +const ( + DefaultImageNameOSS = "consul" + DefaultImageNameENT = "hashicorp/consul-enterprise" + ImageVersionSuffixENT = "-ent" +) + +func init() { + flag.StringVar(&TargetImageName, "target-image", defaultImageName, "docker image name to be used under test (Default: "+defaultImageName+")") + flag.StringVar(&TargetVersion, "target-version", "local", "docker image version to be used as UUT (unit under test)") + + flag.StringVar(&LatestImageName, "latest-image", defaultImageName, "docker image name to be used under test (Default: "+defaultImageName+")") + flag.StringVar(&LatestVersion, "latest-version", "latest", "docker image to be used as latest") + + flag.BoolVar(&FollowLog, "follow-log", true, "follow container log in output (Default: true)") +} + +func DockerImage(image, version string) string { + v := image + ":" + version + if image == DefaultImageNameENT && isSemVer(version) { + // Enterprise versions get a suffix. + v += ImageVersionSuffixENT + } + return v +} + +func isSemVer(ver string) bool { + _, err := version.NewVersion(ver) + return err == nil +} diff --git a/test/integration/consul-container/libs/utils/version_oss.go b/test/integration/consul-container/libs/utils/version_oss.go index 35c4d779fb..0f615e4deb 100644 --- a/test/integration/consul-container/libs/utils/version_oss.go +++ b/test/integration/consul-container/libs/utils/version_oss.go @@ -3,13 +3,7 @@ package utils -import "flag" - -// TODO: need a better way to abstract the container creation and configuration; -// please refer to the discussion in github PR - -var TargetImage = flag.String("target-image", "consul", "docker image name to be used under test (Default: consul)") -var TargetVersion = flag.String("target-version", "local", "docker image version to be used as UUT (unit under test)") -var LatestImage = flag.String("latest-image", "consul", "docker image name to be used under test (Default: consul)") -var LatestVersion = flag.String("latest-version", "1.11", "docker image to be used as latest") -var FollowLog = flag.Bool("follow-log", true, "follow container log in output (Default: true)") +const ( + defaultImageName = DefaultImageNameOSS + ImageVersionSuffix = "" +) diff --git a/test/integration/consul-container/test/basic/connect_service_test.go b/test/integration/consul-container/test/basic/connect_service_test.go index aab4f12160..072b428e2c 100644 --- a/test/integration/consul-container/test/basic/connect_service_test.go +++ b/test/integration/consul-container/test/basic/connect_service_test.go @@ -5,7 +5,6 @@ import ( "github.com/stretchr/testify/require" - libagent "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" @@ -23,7 +22,6 @@ import ( // - Make sure a call to the client sidecar local bind port returns a response from the upstream, static-server func TestBasicConnectService(t *testing.T) { cluster := createCluster(t) - defer terminate(t, cluster) clientService := createServices(t, cluster) _, port := clientService.GetAddr() @@ -31,31 +29,27 @@ func TestBasicConnectService(t *testing.T) { libassert.HTTPServiceEchoes(t, "localhost", port) } -func terminate(t *testing.T, cluster *libcluster.Cluster) { - err := cluster.Terminate() - require.NoError(t, err) -} - -// createCluster func createCluster(t *testing.T) *libcluster.Cluster { - opts := libagent.BuildOptions{ + opts := libcluster.BuildOptions{ InjectAutoEncryption: true, InjectGossipEncryption: true, + // TODO: fix the test to not need the service/envoy stack to use :8500 + AllowHTTPAnyway: true, } - ctx, err := libagent.NewBuildContext(opts) - require.NoError(t, err) + ctx := libcluster.NewBuildContext(t, opts) - conf, err := libagent.NewConfigBuilder(ctx).ToAgentConfig() - require.NoError(t, err) + conf := libcluster.NewConfigBuilder(ctx). + ToAgentConfig(t) t.Logf("Cluster config:\n%s", conf.JSON) - configs := []libagent.Config{*conf} + configs := []libcluster.Config{*conf} - cluster, err := libcluster.New(configs) + cluster, err := libcluster.New(t, configs) require.NoError(t, err) - client, err := cluster.GetClient(nil, true) - require.NoError(t, err) + node := cluster.Agents[0] + client := node.GetClient() + libcluster.WaitForLeader(t, cluster, client) libcluster.WaitForMembers(t, client, 1) diff --git a/test/integration/consul-container/test/metrics/leader_test.go b/test/integration/consul-container/test/metrics/leader_test.go index 399816b701..af2168c7fb 100644 --- a/test/integration/consul-container/test/metrics/leader_test.go +++ b/test/integration/consul-container/test/metrics/leader_test.go @@ -1,100 +1,77 @@ package metrics import ( - "context" - "fmt" - "io" - "net/http" - "net/url" "strings" "testing" - "time" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" - libagent "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) // Given a 3-server cluster, when the leader is elected, then leader's isLeader is 1 and non-leader's 0 func TestLeadershipMetrics(t *testing.T) { - var configs []agent.Config + opts := libcluster.BuildOptions{ + InjectAutoEncryption: true, + InjectGossipEncryption: true, + } + ctx := libcluster.NewBuildContext(t, opts) + + var configs []libcluster.Config + + statsConf := libcluster.NewConfigBuilder(ctx). + Telemetry("127.0.0.0:2180"). + ToAgentConfig(t) - statsConf, err := libagent.NewConfigBuilder(nil).Telemetry("127.0.0.0:2180").ToAgentConfig() - require.NoError(t, err) configs = append(configs, *statsConf) - conf, err := libagent.NewConfigBuilder(nil).Bootstrap(3).ToAgentConfig() - require.NoError(t, err) + conf := libcluster.NewConfigBuilder(ctx). + Bootstrap(3). + ToAgentConfig(t) + numServer := 3 for i := 1; i < numServer; i++ { configs = append(configs, *conf) } - cluster, err := libcluster.New(configs) + cluster, err := libcluster.New(t, configs) require.NoError(t, err) - defer terminate(t, cluster) svrCli := cluster.Agents[0].GetClient() libcluster.WaitForLeader(t, cluster, svrCli) libcluster.WaitForMembers(t, svrCli, 3) - retryWithBackoff := func(agent agent.Agent, expectedStr string) error { - waiter := &utils.Waiter{ - MaxWait: 5 * time.Minute, - } - _, port := agent.GetAddr() - ctx := context.Background() - for { - if waiter.Failures() > 5 { - return fmt.Errorf("reach max failure: %d", waiter.Failures()) - } - - metricsStr, err := getMetrics(t, "127.0.0.1", port, "/v1/agent/metrics") - if err != nil { - return fmt.Errorf("error get metrics: %v", err) - } - if strings.Contains(metricsStr, expectedStr) { - return nil - } - waiter.Wait(ctx) - } - } - leader, err := cluster.Leader() require.NoError(t, err) - leadAddr, leaderPort := leader.GetAddr() + leadAddr := leader.GetIP() - for i, n := range cluster.Agents { - addr, port := n.GetAddr() - if addr == leadAddr && port == leaderPort { - err = retryWithBackoff(leader, ".server.isLeader\",\"Value\":1,") - require.NoError(t, err, "%dth node(leader): could not find the metric %q in the /v1/agent/metrics response", i, ".server.isLeader\",\"Value\":1,") - } else { - err = retryWithBackoff(n, ".server.isLeader\",\"Value\":0,") - require.NoError(t, err, "%dth node(non-leader): could not find the metric %q in the /v1/agent/metrics response", i, ".server.isLeader\",\"Value\":0,") - } + for _, agent := range cluster.Agents { + client := agent.GetClient().Agent() + + retry.RunWith(libcluster.LongFailer(), t, func(r *retry.R) { + info, err := client.Metrics() + require.NoError(r, err) + + var ( + leaderGauge api.GaugeValue + found bool + ) + for _, g := range info.Gauges { + if strings.HasSuffix(g.Name, ".server.isLeader") { + leaderGauge = g + found = true + } + } + require.True(r, found, "did not find isLeader gauge metric") + + addr := agent.GetIP() + if addr == leadAddr { + require.Equal(r, float32(1), leaderGauge.Value) + } else { + require.Equal(r, float32(0), leaderGauge.Value) + } + }) } } - -func getMetrics(t *testing.T, addr string, port int, path string) (string, error) { - u, err := url.Parse(fmt.Sprintf("http://%s:%d", addr, port)) - require.NoError(t, err) - u.Path = path - resp, err := http.Get(u.String()) - if err != nil { - return "", fmt.Errorf("error get metrics: %v", err) - } - body, err := io.ReadAll(resp.Body) - if err != nil { - return "nil", fmt.Errorf("error read metrics: %v", err) - } - return string(body), nil -} - -func terminate(t *testing.T, cluster *libcluster.Cluster) { - err := cluster.Terminate() - require.NoError(t, err) -} diff --git a/test/integration/consul-container/test/peering/rotate_server_and_ca_then_fail_test.go b/test/integration/consul-container/test/peering/rotate_server_and_ca_then_fail_test.go index 7afbdc4320..fdbb3dd9c2 100644 --- a/test/integration/consul-container/test/peering/rotate_server_and_ca_then_fail_test.go +++ b/test/integration/consul-container/test/peering/rotate_server_and_ca_then_fail_test.go @@ -6,16 +6,16 @@ import ( "testing" "time" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - libagent "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" + libtopology "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/test/integration/consul-container/test/topology" ) // TestPeering_RotateServerAndCAThenFail_ @@ -46,48 +46,55 @@ import ( // - Terminate the server nodes in the exporting cluster // - Make sure there is still service connectivity from the importing cluster func TestPeering_RotateServerAndCAThenFail_(t *testing.T) { - acceptingCluster, dialingCluster, _, staticClientSvcSidecar := topology.BasicPeeringTwoClustersSetup(t, *utils.TargetVersion) - defer func() { - err := acceptingCluster.Terminate() - require.NoErrorf(t, err, "termining accepting cluster") - dialingCluster.Terminate() - require.NoErrorf(t, err, "termining dialing cluster") - }() + accepting, dialing := libtopology.BasicPeeringTwoClustersSetup(t, utils.TargetVersion) + var ( + acceptingCluster = accepting.Cluster + dialingCluster = dialing.Cluster + acceptingCtx = accepting.Context + clientSidecarService = dialing.Container + ) dialingClient, err := dialingCluster.GetClient(nil, false) require.NoError(t, err) - _, port := staticClientSvcSidecar.GetAddr() acceptingClient, err := acceptingCluster.GetClient(nil, false) require.NoError(t, err) - t.Run("test rotating servers", func(t *testing.T) { + t.Logf("test rotating servers") + { + var ( + peerName = libtopology.AcceptingPeerName + cluster = acceptingCluster + client = acceptingClient + ctx = acceptingCtx + ) // Start by replacing the Followers - leader, err := acceptingCluster.Leader() + leader, err := cluster.Leader() require.NoError(t, err) - followers, err := acceptingCluster.Followers() + followers, err := cluster.Followers() require.NoError(t, err) require.Len(t, followers, 2) for idx, follower := range followers { t.Log("Removing follower", idx) - rotateServer(t, acceptingCluster, acceptingClient, acceptingCluster.BuildContext, follower) + rotateServer(t, cluster, client, ctx, follower) } t.Log("Removing leader") - rotateServer(t, acceptingCluster, acceptingClient, acceptingCluster.BuildContext, leader) + rotateServer(t, cluster, client, ctx, leader) - libassert.PeeringStatus(t, acceptingClient, topology.AcceptingPeerName, api.PeeringStateActive) - libassert.PeeringExports(t, acceptingClient, topology.AcceptingPeerName, 1) + libassert.PeeringStatus(t, client, peerName, api.PeeringStateActive) + libassert.PeeringExports(t, client, peerName, 1) + _, port := clientSidecarService.GetAddr() libassert.HTTPServiceEchoes(t, "localhost", port) - }) + } - t.Run("rotate exporting cluster's root CA", func(t *testing.T) { + testutil.RunStep(t, "rotate exporting cluster's root CA", func(t *testing.T) { // we will verify that the peering on the dialing side persists the updates CAs - peeringBefore, peerMeta, err := dialingClient.Peerings().Read(context.Background(), topology.DialingPeerName, &api.QueryOptions{}) + peeringBefore, peerMeta, err := dialingClient.Peerings().Read(context.Background(), libtopology.DialingPeerName, &api.QueryOptions{}) require.NoError(t, err) _, caMeta, err := acceptingClient.Connect().CAGetConfig(&api.QueryOptions{}) @@ -116,7 +123,7 @@ func TestPeering_RotateServerAndCAThenFail_(t *testing.T) { require.NoError(t, err) // The peering object should reflect the update - peeringAfter, _, err := dialingClient.Peerings().Read(context.Background(), topology.DialingPeerName, &api.QueryOptions{ + peeringAfter, _, err := dialingClient.Peerings().Read(context.Background(), libtopology.DialingPeerName, &api.QueryOptions{ WaitIndex: peerMeta.LastIndex, WaitTime: 30 * time.Second, }) @@ -130,19 +137,17 @@ func TestPeering_RotateServerAndCAThenFail_(t *testing.T) { require.Len(t, rootList.Roots, 2) // Connectivity should still be contained - _, port := staticClientSvcSidecar.GetAddr() + _, port := clientSidecarService.GetAddr() libassert.HTTPServiceEchoes(t, "localhost", port) - verifySidecarHasTwoRootCAs(t, staticClientSvcSidecar) + verifySidecarHasTwoRootCAs(t, clientSidecarService) }) - t.Run("terminate exporting clusters servers and ensure imported services are still reachable", func(t *testing.T) { + testutil.RunStep(t, "terminate exporting clusters servers and ensure imported services are still reachable", func(t *testing.T) { // Keep this list for later - newNodes, err := acceptingCluster.Clients() - require.NoError(t, err) + newNodes := acceptingCluster.Clients() - serverNodes, err := acceptingCluster.Servers() - require.NoError(t, err) + serverNodes := acceptingCluster.Servers() for _, node := range serverNodes { require.NoError(t, node.Terminate()) } @@ -153,26 +158,20 @@ func TestPeering_RotateServerAndCAThenFail_(t *testing.T) { // ensure any transitory actions like replication cleanup would not affect the next verifications time.Sleep(30 * time.Second) - _, port := staticClientSvcSidecar.GetAddr() + _, port := clientSidecarService.GetAddr() libassert.HTTPServiceEchoes(t, "localhost", port) }) } -func terminate(t *testing.T, cluster *libcluster.Cluster) { - err := cluster.Terminate() - require.NoError(t, err) -} - // rotateServer add a new server agent to the cluster, then forces the prior agent to leave. -func rotateServer(t *testing.T, cluster *libcluster.Cluster, client *api.Client, ctx *libagent.BuildContext, node libagent.Agent) { - conf, err := libagent.NewConfigBuilder(cluster.BuildContext). +func rotateServer(t *testing.T, cluster *libcluster.Cluster, client *api.Client, ctx *libcluster.BuildContext, node libcluster.Agent) { + conf := libcluster.NewConfigBuilder(ctx). Bootstrap(0). Peering(true). RetryJoin("agent-3"). // Always use the client agent since it never leaves the cluster - ToAgentConfig() - require.NoError(t, err) + ToAgentConfig(t) - err = cluster.Add([]libagent.Config{*conf}) + err := cluster.AddN(*conf, 1, false) require.NoError(t, err, "could not start new node") libcluster.WaitForMembers(t, client, 5) @@ -185,6 +184,7 @@ func rotateServer(t *testing.T, cluster *libcluster.Cluster, client *api.Client, func verifySidecarHasTwoRootCAs(t *testing.T, sidecar libservice.Service) { connectContainer, ok := sidecar.(*libservice.ConnectContainer) require.True(t, ok) + _, adminPort := connectContainer.GetAdminAddr() failer := func() *retry.Timer { @@ -193,19 +193,13 @@ func verifySidecarHasTwoRootCAs(t *testing.T, sidecar libservice.Service) { retry.RunWith(failer(), t, func(r *retry.R) { dump, err := libservice.GetEnvoyConfigDump(adminPort) - if err != nil { - r.Fatal("could not curl envoy configuration") - } + require.NoError(r, err, "could not curl envoy configuration") // Make sure there are two certs in the sidecar filter := `.configs[] | select(.["@type"] | contains("type.googleapis.com/envoy.admin.v3.ClustersConfigDump")).dynamic_active_clusters[] | select(.cluster.name | contains("static-server.default.dialing-to-acceptor.external")).cluster.transport_socket.typed_config.common_tls_context.validation_context.trusted_ca.inline_string` results, err := utils.JQFilter(dump, filter) - if err != nil { - r.Fatal("could not parse envoy configuration") - } - if len(results) != 1 { - r.Fatal("could not find certificates in cluster TLS context") - } + require.NoError(r, err, "could not parse envoy configuration") + require.Len(r, results, 1, "could not find certificates in cluster TLS context") rest := []byte(results[0]) var count int @@ -218,8 +212,6 @@ func verifySidecarHasTwoRootCAs(t *testing.T, sidecar libservice.Service) { count++ } - if count != 2 { - r.Fatalf("expected 2 TLS certificates and %d present", count) - } + require.Equal(r, 2, count, "expected 2 TLS certificates and %d present", count) }) } diff --git a/test/integration/consul-container/test/topology/peering_topology.go b/test/integration/consul-container/test/topology/peering_topology.go deleted file mode 100644 index 31a53ad912..0000000000 --- a/test/integration/consul-container/test/topology/peering_topology.go +++ /dev/null @@ -1,87 +0,0 @@ -package topology - -import ( - "sync" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" -) - -const ( - AcceptingPeerName = "accepting-to-dialer" - DialingPeerName = "dialing-to-acceptor" -) - -// BasicPeeringTwoClustersSetup sets up a scenario for testing peering, which consists of -// - an accepting cluster with 3 servers and 1 client agnet. The client should be used to -// host a service for export: staticServerSvc. -// - an dialing cluster with 1 server and 1 client. The client should be used to host a -// service connecting to staticServerSvc. -// - Create the peering, export the service from accepting cluster, and verify service -// connectivity. -// -// It returns objects of the accepting cluster, dialing cluster, staticServerSvc, and staticClientSvcSidecar -func BasicPeeringTwoClustersSetup(t *testing.T, consulVersion string) (*libcluster.Cluster, *libcluster.Cluster, *libservice.Service, *libservice.ConnectContainer) { - var wg sync.WaitGroup - var acceptingCluster, dialingCluster *libcluster.Cluster - var acceptingClient *api.Client - - wg.Add(1) - go func() { - opts := &libcluster.Options{ - Datacenter: "dc1", - NumServer: 3, - NumClient: 1, - Version: consulVersion, - } - acceptingCluster, acceptingClient = libcluster.CreatingPeeringClusterAndSetup(t, opts) - wg.Done() - }() - - wg.Add(1) - go func() { - opts := &libcluster.Options{ - Datacenter: "dc2", - NumServer: 1, - NumClient: 1, - Version: consulVersion, - } - dialingCluster, _ = libcluster.CreatingPeeringClusterAndSetup(t, opts) - wg.Done() - }() - wg.Wait() - - err := dialingCluster.PeerWithCluster(acceptingClient, AcceptingPeerName, DialingPeerName) - require.NoError(t, err) - - libassert.PeeringStatus(t, acceptingClient, AcceptingPeerName, api.PeeringStateActive) - - // Register an static-server service in acceptingCluster and export to dialing cluster - clientNodes, err := acceptingCluster.Clients() - require.NoError(t, err) - require.True(t, len(clientNodes) > 0) - staticServerSvc, _, err := libservice.CreateAndRegisterStaticServerAndSidecar(clientNodes[0]) - require.NoError(t, err) - libassert.CatalogServiceExists(t, acceptingClient, "static-server") - libassert.CatalogServiceExists(t, acceptingClient, "static-server-sidecar-proxy") - - staticServerSvc.Export("default", AcceptingPeerName, acceptingClient) - libassert.PeeringExports(t, acceptingClient, AcceptingPeerName, 1) - - // Register an static-client service in dialing cluster and set upstream to static-server service - clientNodesDialing, err := dialingCluster.Clients() - require.NoError(t, err) - require.True(t, len(clientNodesDialing) > 0) - staticClientSvcSidecar, err := libservice.CreateAndRegisterStaticClientSidecar(clientNodesDialing[0], DialingPeerName, true) - require.NoError(t, err) - - _, port := staticClientSvcSidecar.GetAddr() - libassert.HTTPServiceEchoes(t, "localhost", port) - - return acceptingCluster, dialingCluster, &staticServerSvc, staticClientSvcSidecar -} diff --git a/test/integration/consul-container/test/upgrade/README.md b/test/integration/consul-container/test/upgrade/README.md index 7ea36fc41f..adffc5344a 100644 --- a/test/integration/consul-container/test/upgrade/README.md +++ b/test/integration/consul-container/test/upgrade/README.md @@ -1,11 +1,17 @@ # Consul Upgrade Integration tests + ## Local run - run `make dev-docker` - run the tests, e.g., `go test -run ^TestBasicConnectService$ ./test/basic -v` -To specify targets and latest image pass `target-version` and `latest-version` to the tests. By default, it uses the `consul` docker image with respectively `local` and `latest` tags. +To specify targets and latest image pass `target-version` and `latest-version` +to the tests. By default, it uses the `consul` docker image with respectively +`local` and `latest` tags. -To use dev consul image, pass `target-image` and `target-version`, `-target-image hashicorppreview/consul -target-version 1.14-dev`. +To use dev consul image, pass `target-image` and `target-version`: -By default, all container's logs are written to either `stdout`, or `stderr`; this makes it hard to debug, when the test case creates many -containers. To disable following container logs, run the test with `-follow-log false`. + -target-image hashicorppreview/consul -target-version 1.14-dev + +By default, all container's logs are written to either `stdout`, or `stderr`; +this makes it hard to debug, when the test case creates many containers. To +disable following container logs, run the test with `-follow-log false`. diff --git a/test/integration/consul-container/test/upgrade/fullstopupgrade_test.go b/test/integration/consul-container/test/upgrade/fullstopupgrade_test.go index 49973c813f..dfb700ec3e 100644 --- a/test/integration/consul-container/test/upgrade/fullstopupgrade_test.go +++ b/test/integration/consul-container/test/upgrade/fullstopupgrade_test.go @@ -6,12 +6,10 @@ import ( "testing" "time" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/api" - - "github.com/hashicorp/consul/sdk/testutil/retry" - libagent "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -33,62 +31,48 @@ func TestStandardUpgradeToTarget_fromLatest(t *testing.T) { }, { oldversion: "1.13", - targetVersion: *utils.TargetVersion, + targetVersion: utils.TargetVersion, }, { oldversion: "1.14", - targetVersion: *utils.TargetVersion, + targetVersion: utils.TargetVersion, }, } run := func(t *testing.T, tc testcase) { - - var configs []libagent.Config - - configCtx, err := libagent.NewBuildContext(libagent.BuildOptions{ - ConsulVersion: tc.oldversion, + configCtx := libcluster.NewBuildContext(t, libcluster.BuildOptions{ + ConsulImageName: utils.TargetImageName, + ConsulVersion: tc.oldversion, }) - require.NoError(t, err) - numServers := 1 - leaderConf, err := libagent.NewConfigBuilder(configCtx). + + const ( + numServers = 1 + ) + + serverConf := libcluster.NewConfigBuilder(configCtx). Bootstrap(numServers). - ToAgentConfig() - require.NoError(t, err) - t.Logf("Cluster config:\n%s", leaderConf.JSON) - leaderConf.Version = tc.oldversion - for i := 0; i < numServers; i++ { - configs = append(configs, *leaderConf) - } + ToAgentConfig(t) + t.Logf("Cluster config:\n%s", serverConf.JSON) + require.Equal(t, tc.oldversion, serverConf.Version) // TODO: remove - cluster, err := libcluster.New(configs) + cluster, err := libcluster.NewN(t, *serverConf, numServers) require.NoError(t, err) - defer terminate(t, cluster) - server := cluster.Agents[0] - client := server.GetClient() + client := cluster.APIClient(0) + libcluster.WaitForLeader(t, cluster, client) libcluster.WaitForMembers(t, client, numServers) // Create a service to be stored in the snapshot - serviceName := "api" + const serviceName = "api" index := serviceCreate(t, client, serviceName) - ch := make(chan []*api.ServiceEntry) - errCh := make(chan error) - go func() { - service, q, err := client.Health().Service(serviceName, "", false, &api.QueryOptions{WaitIndex: index}) - if err == nil && q.QueryBackend != api.QueryBackendStreaming { - err = fmt.Errorf("invalid backend for this test %s", q.QueryBackend) - } - if err != nil { - errCh <- err - } else { - ch <- service - } - }() + + ch, errCh := serviceHealthBlockingQuery(client, serviceName, index) require.NoError(t, client.Agent().ServiceRegister( &api.AgentServiceRegistration{Name: serviceName, Port: 9998}, )) - timer := time.NewTimer(1 * time.Second) + + timer := time.NewTimer(3 * time.Second) select { case err := <-errCh: require.NoError(t, err) @@ -101,6 +85,7 @@ func TestStandardUpgradeToTarget_fromLatest(t *testing.T) { } // upgrade the cluster to the Target version + t.Logf("initiating standard upgrade to version=%q", tc.targetVersion) err = cluster.StandardUpgrade(t, context.Background(), tc.targetVersion) if !tc.expectErr { require.NoError(t, err) @@ -124,6 +109,6 @@ func TestStandardUpgradeToTarget_fromLatest(t *testing.T) { func(t *testing.T) { run(t, tc) }) - time.Sleep(5 * time.Second) + // time.Sleep(5 * time.Second) } } diff --git a/test/integration/consul-container/test/upgrade/healthcheck_test.go b/test/integration/consul-container/test/upgrade/healthcheck_test.go index b3d49523ed..c7a5717bc9 100644 --- a/test/integration/consul-container/test/upgrade/healthcheck_test.go +++ b/test/integration/consul-container/test/upgrade/healthcheck_test.go @@ -1,16 +1,12 @@ package upgrade import ( - "context" - "fmt" "testing" "time" + "github.com/hashicorp/consul/api" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/api" - - libagent "github.com/hashicorp/consul/test/integration/consul-container/libs/agent" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -22,194 +18,19 @@ func TestTargetServersWithLatestGAClients(t *testing.T) { numClients = 1 ) - cluster := serversCluster(t, numServers, *utils.TargetVersion, *utils.TargetImage) - defer terminate(t, cluster) + cluster := serversCluster(t, numServers, utils.TargetImageName, utils.TargetVersion) - clients := clientsCreate(t, numClients, *utils.LatestImage, *utils.LatestVersion, cluster) + clientsCreate(t, numClients, utils.LatestImageName, utils.LatestVersion, cluster) - require.NoError(t, cluster.Join(clients)) - - client := cluster.Agents[0].GetClient() + client := cluster.APIClient(0) libcluster.WaitForLeader(t, cluster, client) libcluster.WaitForMembers(t, client, 4) - serviceName := "api" + const serviceName = "api" index := serviceCreate(t, client, serviceName) - ch := make(chan []*api.ServiceEntry) - errCh := make(chan error) - - go func() { - service, q, err := client.Health().Service(serviceName, "", false, &api.QueryOptions{WaitIndex: index}) - if err == nil && q.QueryBackend != api.QueryBackendStreaming { - err = fmt.Errorf("invalid backend for this test %s", q.QueryBackend) - } - if err != nil { - errCh <- err - } else { - ch <- service - } - }() - - require.NoError(t, client.Agent().ServiceRegister( - &api.AgentServiceRegistration{Name: serviceName, Port: 9998}, - )) - - timer := time.NewTimer(1 * time.Second) - select { - case err := <-errCh: - require.NoError(t, err) - case service := <-ch: - require.Len(t, service, 1) - require.Equal(t, serviceName, service[0].Service.Service) - require.Equal(t, 9998, service[0].Service.Port) - case <-timer.C: - t.Fatalf("test timeout") - } -} - -// Test health check GRPC call using Mixed (majority latest) Servers and Latest GA Clients -func TestMixedServersMajorityLatestGAClient(t *testing.T) { - var configs []libagent.Config - - leaderConf, err := libagent.NewConfigBuilder(nil).ToAgentConfig() - require.NoError(t, err) - - configs = append(configs, *leaderConf) - - // This needs a specialized config since it is using an older version of the agent. - // That is missing fields like GRPC_TLS and PEERING, which are passed as defaults - serverConf := `{ - "advertise_addr": "{{ GetInterfaceIP \"eth0\" }}", - "bind_addr": "0.0.0.0", - "client_addr": "0.0.0.0", - "log_level": "DEBUG", - "server": true, - "bootstrap_expect": 3 - }` - - for i := 1; i < 3; i++ { - configs = append(configs, - libagent.Config{ - JSON: serverConf, - Cmd: []string{"agent"}, - Version: *utils.LatestVersion, - Image: *utils.LatestImage, - }) - } - - cluster, err := libcluster.New(configs) - require.NoError(t, err) - defer terminate(t, cluster) - - const ( - numClients = 1 - ) - - clients := clientsCreate(t, numClients, *utils.LatestImage, *utils.LatestVersion, cluster) - - require.NoError(t, cluster.Join(clients)) - - client := clients[0].GetClient() - - libcluster.WaitForLeader(t, cluster, client) - libcluster.WaitForMembers(t, client, 4) - - serviceName := "api" - index := serviceCreate(t, client, serviceName) - - ch := make(chan []*api.ServiceEntry) - errCh := make(chan error) - go func() { - service, q, err := client.Health().Service(serviceName, "", false, &api.QueryOptions{WaitIndex: index}) - if err == nil && q.QueryBackend != api.QueryBackendStreaming { - err = fmt.Errorf("invalid backend for this test %s", q.QueryBackend) - } - if err != nil { - errCh <- err - } else { - ch <- service - } - }() - - require.NoError(t, client.Agent().ServiceRegister( - &api.AgentServiceRegistration{Name: serviceName, Port: 9998}, - )) - - timer := time.NewTimer(1 * time.Second) - select { - case err := <-errCh: - require.NoError(t, err) - case service := <-ch: - require.Len(t, service, 1) - require.Equal(t, serviceName, service[0].Service.Service) - require.Equal(t, 9998, service[0].Service.Port) - case <-timer.C: - t.Fatalf("test timeout") - } -} - -// Test health check GRPC call using Mixed (majority target) Servers and Latest GA Clients -func TestMixedServersMajorityTargetGAClient(t *testing.T) { - var configs []libagent.Config - - for i := 0; i < 2; i++ { - serverConf, err := libagent.NewConfigBuilder(nil).Bootstrap(3).ToAgentConfig() - require.NoError(t, err) - configs = append(configs, *serverConf) - } - - leaderConf := `{ - "advertise_addr": "{{ GetInterfaceIP \"eth0\" }}", - "bind_addr": "0.0.0.0", - "client_addr": "0.0.0.0", - "log_level": "DEBUG", - "server": true - }` - - configs = append(configs, - libagent.Config{ - JSON: leaderConf, - Cmd: []string{"agent"}, - Version: *utils.LatestVersion, - Image: *utils.LatestImage, - }) - - cluster, err := libcluster.New(configs) - require.NoError(t, err) - defer terminate(t, cluster) - - const ( - numClients = 1 - ) - - clients := clientsCreate(t, numClients, *utils.LatestImage, *utils.LatestVersion, cluster) - - require.NoError(t, cluster.Join(clients)) - - client := clients[0].GetClient() - - libcluster.WaitForLeader(t, cluster, client) - libcluster.WaitForMembers(t, client, 4) - - serviceName := "api" - index := serviceCreate(t, client, serviceName) - - ch := make(chan []*api.ServiceEntry) - errCh := make(chan error) - go func() { - service, q, err := client.Health().Service(serviceName, "", false, &api.QueryOptions{WaitIndex: index}) - if err == nil && q.QueryBackend != api.QueryBackendStreaming { - err = fmt.Errorf("invalid backend for this test %s", q.QueryBackend) - } - if err != nil { - errCh <- err - } else { - ch <- service - } - }() - + ch, errCh := serviceHealthBlockingQuery(client, serviceName, index) require.NoError(t, client.Agent().ServiceRegister( &api.AgentServiceRegistration{Name: serviceName, Port: 9998}, )) @@ -227,76 +48,96 @@ func TestMixedServersMajorityTargetGAClient(t *testing.T) { } } -func clientsCreate(t *testing.T, numClients int, image string, version string, cluster *libcluster.Cluster) []libagent.Agent { - clients := make([]libagent.Agent, numClients) +// Test health check GRPC call using Mixed (majority latest) Servers and Latest GA Clients +func TestMixedServersMajorityLatestGAClient(t *testing.T) { + testMixedServersGAClient(t, false) +} - // This needs a specialized config since it is using an older version of the agent. - // That is missing fields like GRPC_TLS and PEERING, which are passed as defaults - conf := `{ - "advertise_addr": "{{ GetInterfaceIP \"eth0\" }}", - "bind_addr": "0.0.0.0", - "client_addr": "0.0.0.0", - "log_level": "DEBUG" - }` +// Test health check GRPC call using Mixed (majority target) Servers and Latest GA Clients +func TestMixedServersMajorityTargetGAClient(t *testing.T) { + testMixedServersGAClient(t, true) +} - for i := 0; i < numClients; i++ { - var err error - clients[i], err = libagent.NewConsulContainer(context.Background(), - libagent.Config{ - JSON: conf, - Cmd: []string{"agent"}, - Version: version, - Image: image, - }, - cluster.NetworkName, - cluster.Index) - require.NoError(t, err) +// Test health check GRPC call using Mixed (majority conditional) Servers and Latest GA Clients +func testMixedServersGAClient(t *testing.T, majorityIsTarget bool) { + var ( + latestOpts = libcluster.BuildOptions{ + ConsulImageName: utils.LatestImageName, + ConsulVersion: utils.LatestVersion, + } + targetOpts = libcluster.BuildOptions{ + ConsulImageName: utils.TargetImageName, + ConsulVersion: utils.TargetVersion, + } + + majorityOpts libcluster.BuildOptions + minorityOpts libcluster.BuildOptions + ) + + if majorityIsTarget { + majorityOpts = targetOpts + minorityOpts = latestOpts + } else { + majorityOpts = latestOpts + minorityOpts = targetOpts } - return clients -} -func serviceCreate(t *testing.T, client *api.Client, serviceName string) uint64 { - err := client.Agent().ServiceRegister(&api.AgentServiceRegistration{ - Name: serviceName, - Port: 9999, - Connect: &api.AgentServiceConnect{ - SidecarService: &api.AgentServiceRegistration{ - Port: 22005, - }, - }, - }) - require.NoError(t, err) + const ( + numServers = 3 + numClients = 1 + ) - service, meta, err := client.Catalog().Service(serviceName, "", &api.QueryOptions{}) - require.NoError(t, err) - require.Len(t, service, 1) - require.Equal(t, serviceName, service[0].ServiceName) - require.Equal(t, 9999, service[0].ServicePort) + var configs []libcluster.Config + { + ctx := libcluster.NewBuildContext(t, minorityOpts) - return meta.LastIndex -} + conf := libcluster.NewConfigBuilder(ctx). + ToAgentConfig(t) + t.Logf("Cluster server (leader) config:\n%s", conf.JSON) -func serversCluster(t *testing.T, numServers int, version string, image string) *libcluster.Cluster { - var configs []libagent.Config - - conf, err := libagent.NewConfigBuilder(nil). - Bootstrap(numServers). - ToAgentConfig() - require.NoError(t, err) - - for i := 0; i < numServers; i++ { configs = append(configs, *conf) } - cluster, err := libcluster.New(configs) + + { + ctx := libcluster.NewBuildContext(t, majorityOpts) + + conf := libcluster.NewConfigBuilder(ctx). + Bootstrap(numServers). + ToAgentConfig(t) + t.Logf("Cluster server config:\n%s", conf.JSON) + + for i := 1; i < numServers; i++ { + configs = append(configs, *conf) + } + } + + cluster, err := libcluster.New(t, configs) require.NoError(t, err) - libcluster.WaitForLeader(t, cluster, nil) - libcluster.WaitForMembers(t, cluster.Agents[0].GetClient(), numServers) + clientsCreate(t, numClients, utils.LatestImageName, utils.LatestVersion, cluster) - return cluster -} + client := cluster.APIClient(0) -func terminate(t *testing.T, cluster *libcluster.Cluster) { - err := cluster.Terminate() - require.NoError(t, err) + libcluster.WaitForLeader(t, cluster, client) + libcluster.WaitForMembers(t, client, 4) // TODO(rb): why 4? + + const serviceName = "api" + index := serviceCreate(t, client, serviceName) + + ch, errCh := serviceHealthBlockingQuery(client, serviceName, index) + require.NoError(t, client.Agent().ServiceRegister( + &api.AgentServiceRegistration{Name: serviceName, Port: 9998}, + )) + + timer := time.NewTimer(3 * time.Second) + select { + case err := <-errCh: + require.NoError(t, err) + case service := <-ch: + require.Len(t, service, 1) + require.Equal(t, serviceName, service[0].Service.Service) + require.Equal(t, 9998, service[0].Service.Port) + case <-timer.C: + t.Fatalf("test timeout") + } } diff --git a/test/integration/consul-container/test/upgrade/helper_test.go b/test/integration/consul-container/test/upgrade/helper_test.go new file mode 100644 index 0000000000..c8627f3747 --- /dev/null +++ b/test/integration/consul-container/test/upgrade/helper_test.go @@ -0,0 +1,92 @@ +package upgrade + +import ( + "fmt" + "testing" + + "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/require" + + libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" +) + +func serversCluster(t *testing.T, numServers int, image, version string) *libcluster.Cluster { + t.Helper() + + opts := libcluster.BuildOptions{ + ConsulImageName: image, + ConsulVersion: version, + } + ctx := libcluster.NewBuildContext(t, opts) + + conf := libcluster.NewConfigBuilder(ctx). + Bootstrap(numServers). + ToAgentConfig(t) + t.Logf("Cluster server config:\n%s", conf.JSON) + + cluster, err := libcluster.NewN(t, *conf, numServers) + require.NoError(t, err) + + libcluster.WaitForLeader(t, cluster, nil) + libcluster.WaitForMembers(t, cluster.APIClient(0), numServers) + + return cluster +} + +func clientsCreate(t *testing.T, numClients int, image, version string, cluster *libcluster.Cluster) { + t.Helper() + + opts := libcluster.BuildOptions{ + ConsulImageName: image, + ConsulVersion: version, + } + ctx := libcluster.NewBuildContext(t, opts) + + conf := libcluster.NewConfigBuilder(ctx). + Client(). + ToAgentConfig(t) + t.Logf("Cluster client config:\n%s", conf.JSON) + + require.NoError(t, cluster.AddN(*conf, numClients, true)) +} + +func serviceCreate(t *testing.T, client *api.Client, serviceName string) uint64 { + require.NoError(t, client.Agent().ServiceRegister(&api.AgentServiceRegistration{ + Name: serviceName, + Port: 9999, + Connect: &api.AgentServiceConnect{ + SidecarService: &api.AgentServiceRegistration{ + Port: 22005, + }, + }, + })) + + service, meta, err := client.Catalog().Service(serviceName, "", &api.QueryOptions{}) + require.NoError(t, err) + require.Len(t, service, 1) + require.Equal(t, serviceName, service[0].ServiceName) + require.Equal(t, 9999, service[0].ServicePort) + + return meta.LastIndex +} + +func serviceHealthBlockingQuery(client *api.Client, serviceName string, waitIndex uint64) (chan []*api.ServiceEntry, chan error) { + var ( + ch = make(chan []*api.ServiceEntry, 1) + errCh = make(chan error, 1) + ) + go func() { + opts := &api.QueryOptions{WaitIndex: waitIndex} + service, q, err := client.Health().Service(serviceName, "", false, opts) + if err == nil && q.QueryBackend != api.QueryBackendStreaming { + err = fmt.Errorf("invalid backend for this test %s", q.QueryBackend) + } + if err != nil { + errCh <- err + } else { + ch <- service + } + }() + + return ch, errCh +} diff --git a/test/integration/consul-container/test/upgrade/peers_http_test.go b/test/integration/consul-container/test/upgrade/peers_http_test.go index 944521260f..39bf298227 100644 --- a/test/integration/consul-container/test/upgrade/peers_http_test.go +++ b/test/integration/consul-container/test/upgrade/peers_http_test.go @@ -4,14 +4,13 @@ import ( "context" "fmt" "testing" - "time" - - "github.com/stretchr/testify/require" "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/require" + libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" + libtopology "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/test/integration/consul-container/test/topology" ) // TestPeering_UpgradeToTarget_fromLatest checks peering status after dialing cluster @@ -30,35 +29,28 @@ func TestPeering_UpgradeToTarget_fromLatest(t *testing.T) { // }, { oldversion: "1.14", - targetVersion: *utils.TargetVersion, + targetVersion: utils.TargetVersion, }, } run := func(t *testing.T, tc testcase) { - acceptingCluster, dialingCluster, _, staticClientSvcSidecar := topology.BasicPeeringTwoClustersSetup(t, tc.oldversion) - // move to teardown - defer func() { - err := acceptingCluster.Terminate() - require.NoErrorf(t, err, "termining accepting cluster") - dialingCluster.Terminate() - require.NoErrorf(t, err, "termining dialing cluster") - }() + accepting, dialing := libtopology.BasicPeeringTwoClustersSetup(t, tc.oldversion) + var ( + acceptingCluster = accepting.Cluster + dialingCluster = dialing.Cluster + ) dialingClient, err := dialingCluster.GetClient(nil, false) require.NoError(t, err) - _, port := staticClientSvcSidecar.GetAddr() - // Upgrade the dialingCluster cluster and assert peering is still ACTIVE - err = dialingCluster.StandardUpgrade(t, context.Background(), tc.targetVersion) + acceptingClient, err := acceptingCluster.GetClient(nil, false) require.NoError(t, err) - libassert.PeeringStatus(t, dialingClient, topology.DialingPeerName, api.PeeringStateActive) - libassert.HTTPServiceEchoes(t, "localhost", port) // Upgrade the accepting cluster and assert peering is still ACTIVE - err = acceptingCluster.StandardUpgrade(t, context.Background(), tc.targetVersion) - require.NoError(t, err) + require.NoError(t, acceptingCluster.StandardUpgrade(t, context.Background(), tc.targetVersion)) - libassert.PeeringStatus(t, dialingClient, topology.DialingPeerName, api.PeeringStateActive) + libassert.PeeringStatus(t, acceptingClient, libtopology.AcceptingPeerName, api.PeeringStateActive) + libassert.PeeringStatus(t, dialingClient, libtopology.DialingPeerName, api.PeeringStateActive) } for _, tc := range tcs { @@ -66,6 +58,6 @@ func TestPeering_UpgradeToTarget_fromLatest(t *testing.T) { func(t *testing.T) { run(t, tc) }) - time.Sleep(3 * time.Second) + // time.Sleep(3 * time.Second) } }