From 51a2b138a523812f1248a5ca529f8cde43c22c45 Mon Sep 17 00:00:00 2001 From: LaunchDarklyReleaseBot <86431345+LaunchDarklyReleaseBot@users.noreply.github.com> Date: Wed, 26 Oct 2022 13:02:32 -0700 Subject: [PATCH] prepare 6.7.14 release (#206) * fix broken link in Markdown docs (#246) * make sure newly added credentials for existing environments are accepted in requests (#244) * don't return 503 if SDK initialization has timed out * add in-repo docs about error/503 behavior (#249) * [ch102255] BigSegments DynamoDB (#245) * add init timeout config option + better test coverage + misc refactoring (#250) * fix example build command * use public prerelease tags instead of private dependencies * fix Go installation in CI * update SDK dependencies for JSON number parsing bugfix * update gorilla/mux to 1.8.0 * update OpenCensus packages * add Go 1.16 CI + "latest Go" CI + use latest 1.15 patch for release * cimg images use "current", not "latest" * seems there isn't any cimg/go "latest" or "current" * add daily package build test in CI * job names * bump SDK version for traffic allocation feature * [ch113491] update alpine base image (#258) * use latest prerelease SDK * fix enabling of test tags in CI * add DynamoDB docker image in CI * set a polling base URI in end-to-end tests since big segments logic will use it * fix initialization logic so SDK client creation errors aren't lost when big segments are enabled * fix use of prefix key in DynamoDB + improve tests (#260) * more debug logging, less info logging for big segments logic * make logging of big segments patch version mismatch clearer and use Warn level * fix log parameter * fix DynamoDB updates for big segments metadata * add test to make sure sync time and cursor can be updated independently * only start big seg synchronizer if necessary * use SDK GA releases * change applyPatch to exit early on version mismatch; go back to restarting stream in this case * add unit tests for version mismatch behavior + DRY tests * add log assertion * fix retry logic on big segments stream failure * add more logging for big segments connection status * fix logging assertion * add more big segments integration tests * fix overly-time-sensitive file data tests * fix more flaky tests * run big segments tests with DynamoDB too * Migrate transitive dep (jwt-go) to use modern version without vulnerability. * Edit doc * move Relay release logic to .ldrelease script * suppress SDK big segments status query if we've never synced big segments * dump Relay logs including debug logs if integration test fails * include environment prefix in BigSegmentSynchronizer logging * increase big segment integration test timeout (#274) * generate client-side stream pings if big segments have changed * clear big segments cache as needed + simplify state management * fix tests and simplify component creation * use GA releases of SDK packages * disable CI package-build-test in Go 1.16+ * Migrate Relay release to Releaser v2 and support dry run (#278) * Adding degraded doc blurb for big segments (#280) * respect Redis password & TLS options for big segments; add Redis password integration tests * redact Redis URL password in logs and status resource * update go-server-sdk-redis-redigo to 1.2.1 for Redis URL logging fix * Part 1, add the config and the documentation for the new config * Part 2, Add the configuration validation and test * Part 3, the actual logic to include the headers in the CORS Access-Control-Allow-Headers * Linter * update Alpine version to 3.14.2 to fix openssl CVEs * Fix the global variable modification * Go format * turn off unnecessary metrics integrations in config for Docker smoke test * rename test.env to smoke-test.env to clarify what it's for * fix setting of custom Access-Control-Allow-Origin and add test (#285) * add more explanatory test output and more verbose debugging for big segments integration tests (#287) * update to Go 1.16.10 + Alpine 3.14.3; add some docs about releases (#288) * update go-server-sdk-consul version for Consul API version update * override x/crypto dependency version for CVE-2020-29652 * bump Prometheus dependency to eliminate jwt-go vulnerability * drop support for Go 1.14 & 1.15 * make sure defaults are always applied for base URL properties * rm unused * rm unnecessary linter directive * add separate configuration for server-side/client-side SDK base URLs & update the defaults * remove Whitesource CI job + remove obsolete dependency issue note * don't include any big segment status info in status resource unless that feature is active (#296) * don't include any big segment status info in status resource unless that feature is active * fix Big Segments staleness logic in status resource * documentation * update x/text package for vulnerability GO-2021-0113 * add Trivy security scan to CI (#297) * add daily re-scan with Trivy * use long timeout when awaiting changes related to file mod watching * update Go version to 1.17.6 (#301) * always terminate if auto-config stream fails with a fatal error * pass along tags header when proxying events * comments, rm debugging * fix auth header logic * fix auth header logic some more * comments * add tags header to CORS header whitelist (#304) * update to Alpine 3.14.4 for CVE-2022-0778 fix * force upgrade of openssl in Alpine * also upgrade libretls * fix it in both files * update to Alpine 3.14.5 for CVE-2022-0778/CVE-2018-25032 (#308) * update to Alpine 3.14.5 for CVE-2022-0778 * revert patches that are now included in Alpine 3.14.5 * add scripts for checking and updating Go/Alpine versions (#309) * update to Alpine 3.14.5 for CVE-2022-0778 * add scripts for checking and updating Go/Alpine versions * also make sure the Docker images really exist * update CONTRIBUTING.md * fix file rename * revert patches that are now included in Alpine 3.14.5 * update Alpine to 3.14.6 for CVE-2022-28391 * update SDK packages (includes sc-136333 fix) * don't include "v" prefix in Docker image version * update go-server-sdk-dynamodb for data size error fix & add docs (#316) * update builds to use Go 1.17.9 and fix the update script * update go-server-sdk-consul to latest release * update remote Docker version * update golang.org/x/crypto for CVE-2022-27191 (#321) * update golang.org/x/crypto for CVE-2022-27191 * fix go.sum * update eventsource for SSE output efficiency fix (#322) * Cache the replay event in case we get multiple new client connections (#189) * Cache the replay event in case we get multiple new client connections * Use singleflight to ensure only one replay event is generated at a time Co-authored-by: Moshe Good * don't install curl in Docker images * fix makefile logic for lint step * remove indirect curl-based request logic in integration tests * fix linter installation * update Go to 1.17.11, Alpine to 3.16.0 * improve concurrency test to verify that the data is or isn't from a separate query * fix lint warnings and remove unnecessary error return * update libssl & libcrypto versions for CVE-2022-2097 * add security scan of already-published Docker image (#328) * update Alpine version and some Go libraries to address CVEs (#329) * use Alpine 3.16.1 * update golang.org/x/net and golang.org/x/sync patch versions for CVEs * update golang.org/x/sys patch version for CVE * update Prometheus client library for CVE-2022-21698 * ensure that DynamoDB config is consistent between Big Segments and regular data store * comment * update Alpine to 3.16.2 * update golangci-lint and go-junit-report * fix CI * prevent traversal of directories outside target path when expanding archive * enforce TLS >= 1.2 for secure Redis * misc linter updates * fix test message * add Go 1.18 & 1.19 jobs * make test expectation less Go-version-dependent * linting * revert unnecessary change * fix installation of test coverage tool * migrate to AWS Go SDK v2 for DynamoDB (#333) * update to Go 1.19.2 * update golang.org/x/net for CVE-2022-27664 * update golang.org/x/text for CVE-2022-32149 * update Consul API dependency to avoid false report of CVE-2022-40716 * switch to fork of Stackdriver metrics client to remove AWS transitive dependency (#343) Co-authored-by: Eli Bishop Co-authored-by: LaunchDarklyCI Co-authored-by: hroederld Co-authored-by: LaunchDarklyReleaseBot Co-authored-by: Dan Richelson Co-authored-by: Dan Richelson Co-authored-by: Ben Woskow <48036130+bwoskow-ld@users.noreply.github.com> Co-authored-by: Ben Woskow Co-authored-by: Louis Chan Co-authored-by: Louis Chan <91093020+louis-launchdarkly@users.noreply.github.com> Co-authored-by: Moshe Good Co-authored-by: Moshe Good --- .circleci/config.yml | 10 +- .golangci.yml | 9 +- .ldrelease/config.yml | 2 +- Dockerfile | 2 +- Makefile | 4 +- _testservice/processes.go | 5 +- config/config_from_file_test.go | 6 +- go.mod | 43 ++--- go.sum | 174 +++++++++++------- integrationtests/build_relay_test.go | 4 +- integrationtests/docker/docker_helpers.go | 1 - integrationtests/oshelpers/commands.go | 1 - integrationtests/request_logger_test.go | 4 +- integrationtests/test_manager_test.go | 8 +- internal/autoconfig/stream_manager.go | 4 +- internal/core/application/commandline.go | 3 +- internal/core/application/commandline_test.go | 14 +- internal/core/application/server.go | 6 +- internal/core/application/server_test.go | 8 +- internal/core/bigsegments/store.go | 4 +- internal/core/bigsegments/store_dynamodb.go | 173 +++++++++-------- .../core/bigsegments/store_dynamodb_test.go | 147 ++++++++------- internal/core/bigsegments/store_redis.go | 5 +- internal/core/bigsegments/sync.go | 4 +- internal/core/bigsegments/sync_test.go | 2 +- internal/core/httpconfig/httpconfig_test.go | 4 +- internal/core/internal/events/event-relay.go | 4 +- internal/core/internal/metrics/metrics.go | 2 +- internal/core/internal/metrics/prometheus.go | 4 +- internal/core/internal/metrics/stackdriver.go | 2 +- .../core/internal/metrics/stackdriver_test.go | 3 +- internal/core/relay_core.go | 2 +- internal/core/relay_core_end_to_end_test.go | 4 +- internal/core/relay_core_endpoints.go | 5 +- internal/core/relay_core_endpoints_status.go | 4 +- internal/core/relay_core_endpoints_test.go | 6 +- internal/core/sdks/big_segments_test.go | 46 +---- internal/core/sdks/data_stores.go | 18 +- internal/core/sdks/data_stores_test.go | 91 +-------- internal/core/sharedtest/os_helpers.go | 3 +- internal/core/sharedtest/requests.go | 3 +- .../sharedtest/testsuites/endpoints_events.go | 4 +- .../sharedtest/testsuites/endpoints_other.go | 4 +- .../testsuites/endpoints_streams.go | 4 +- internal/filedata/archive_manager_test.go | 3 +- internal/filedata/archive_reader.go | 20 +- internal/filedata/archive_reader_test.go | 3 +- internal/filedata/testdata_test.go | 11 +- internal/util/closers.go | 18 +- 49 files changed, 426 insertions(+), 485 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0a2108cb..f329e4a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ parameters: # override it in any parameterized builds, but just as a convenient shareable constant go-release-version: type: string - default: "1.17.11" + default: "1.19.2" # We use a remote Docker host in some CI jobs that need to run Docker containers. # As of 2022-04-15, the default Docker daemon version was 17.09.0-ce, which started @@ -35,8 +35,14 @@ workflows: # This build has a deliberately unpinned version so that if a new Go major version # is released before we have updated the build, we can detect any problems early docker-image: circleci/golang:latest + - go-test: + name: Go 1.19 + docker-image: cimg/go:1.19 run-lint: true test-coverage: true + - go-test: + name: Go 1.18 + docker-image: cimg/go:1.18 - go-test: name: Go 1.17 docker-image: cimg/go:1.17 @@ -135,7 +141,7 @@ jobs: - run: go version && go env - run: name: install go-junit-report - command: go install github.com/jstemmer/go-junit-report@v0.9.1 + command: go install github.com/jstemmer/go-junit-report/v2@v2.0.0 - when: condition: <> steps: diff --git a/.golangci.yml b/.golangci.yml index 27db464f..633bcd59 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -20,7 +20,6 @@ linters: - godox - gofmt - goimports - - golint - gosec - gosimple - govet @@ -32,7 +31,6 @@ linters: - nolintlint - prealloc - staticcheck - - structcheck - stylecheck - typecheck - unconvert @@ -56,12 +54,9 @@ issues: - bodyclose - goconst - gochecknoglobals - - golint - - path: enterprise/ld-relay-enterprise.go # temporary exclusion because linter is confused by two command-line entry points + - path: integrationtests linters: - - deadcode - - golint - - unused + - stylecheck exclude-use-default: false max-same-issues: 1000 max-per-linter: 1000 diff --git a/.ldrelease/config.yml b/.ldrelease/config.yml index 122a12b9..15386979 100644 --- a/.ldrelease/config.yml +++ b/.ldrelease/config.yml @@ -38,7 +38,7 @@ repo: jobs: - docker: - image: cimg/go:1.17.11 # See "Runtime platform versions" in CONTRIBUTING.md + image: cimg/go:1.19.2 # See "Runtime platform versions" in CONTRIBUTING.md copyGitHistory: true template: name: go diff --git a/Dockerfile b/Dockerfile index fe55774b..16b197e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # This is a standalone Dockerfile that does not depend on goreleaser building the binary # It is NOT the version that is pushed to dockerhub -FROM golang:1.17.11-alpine3.16 as builder +FROM golang:1.19.2-alpine3.16 as builder # See "Runtime platform versions" in CONTRIBUTING.md RUN apk --no-cache add \ diff --git a/Makefile b/Makefile index a2c7f624..ef13230b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -GOLANGCI_LINT_VERSION=v1.27.0 +GOLANGCI_LINT_VERSION=v1.48.0 LINTER=./bin/golangci-lint LINTER_VERSION_FILE=./bin/.golangci-lint-version-$(GOLANGCI_LINT_VERSION) @@ -32,7 +32,7 @@ test: go test -race -v $(OPTIONAL_TAGS_PARAM) ./... test-coverage: $(COVERAGE_PROFILE_RAW) - if [ ! -x "$(GOPATH)/bin/go-coverage-enforcer)" ]; then go get -u github.com/launchdarkly-labs/go-coverage-enforcer; fi + if [ ! -x "$(GOPATH)/bin/go-coverage-enforcer)" ]; then go install github.com/launchdarkly-labs/go-coverage-enforcer@latest; fi $(GOPATH)/bin/go-coverage-enforcer $(COVERAGE_ENFORCER_FLAGS) -outprofile $(COVERAGE_PROFILE_FILTERED) $(COVERAGE_PROFILE_RAW) || true @# added || true because we don't currently want go-coverage-enforcer to stop the build due to coverage gaps go tool cover -html $(COVERAGE_PROFILE_FILTERED) -o $(COVERAGE_PROFILE_FILTERED_HTML) diff --git a/_testservice/processes.go b/_testservice/processes.go index a03bc712..83ddedec 100644 --- a/_testservice/processes.go +++ b/_testservice/processes.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io/ioutil" "os" "os/exec" "strconv" @@ -29,7 +28,7 @@ func startProcess(serviceName string, serviceArgs []string) error { } pid := cmd.Process.Pid - if err := ioutil.WriteFile(pidFile, []byte(strconv.Itoa(pid)), 0644); err != nil { + if err := os.WriteFile(pidFile, []byte(strconv.Itoa(pid)), 0644); err != nil { fmt.Fprintln(os.Stderr, "couldn't write PID file - killing process") _ = cmd.Process.Kill() return err @@ -40,7 +39,7 @@ func startProcess(serviceName string, serviceArgs []string) error { func stopProcess(serviceName string) error { pidFile := pidFileName(serviceName) - data, err := ioutil.ReadFile(pidFile) + data, err := os.ReadFile(pidFile) if err != nil { return fmt.Errorf("%s not found", pidFile) } diff --git a/config/config_from_file_test.go b/config/config_from_file_test.go index 43383a21..02b895b3 100644 --- a/config/config_from_file_test.go +++ b/config/config_from_file_test.go @@ -1,7 +1,7 @@ package config import ( - "io/ioutil" + "os" "testing" "time" @@ -181,7 +181,7 @@ LogLevel = "wrong"`, func testFileWithValidConfig(t *testing.T, tdc testDataValidConfig) { helpers.WithTempFile(func(filename string) { - require.NoError(t, ioutil.WriteFile(filename, []byte(tdc.fileContent), 0)) + require.NoError(t, os.WriteFile(filename, []byte(tdc.fileContent), 0)) var c Config mockLog := ldlogtest.NewMockLog() @@ -193,7 +193,7 @@ func testFileWithValidConfig(t *testing.T, tdc testDataValidConfig) { func testFileWithInvalidConfig(t *testing.T, fileContent string, errMessage string) { helpers.WithTempFile(func(filename string) { - require.NoError(t, ioutil.WriteFile(filename, []byte(fileContent), 0)) + require.NoError(t, os.WriteFile(filename, []byte(fileContent), 0)) var c Config err := LoadConfigFile(&c, filename, ldlog.NewDisabledLoggers()) diff --git a/go.mod b/go.mod index 23c0060a..e1c9f05e 100644 --- a/go.mod +++ b/go.mod @@ -4,50 +4,41 @@ go 1.16 require ( contrib.go.opencensus.io/exporter/prometheus v0.4.0 - contrib.go.opencensus.io/exporter/stackdriver v0.13.6 github.com/DataDog/datadog-go v3.7.2+incompatible // indirect github.com/DataDog/opencensus-go-exporter-datadog v0.0.0-20210527074920-9baf37265e83 github.com/antihax/optional v1.0.0 - github.com/armon/go-metrics v0.3.9 // indirect - github.com/aws/aws-sdk-go v1.40.45 - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/fatih/color v1.12.0 // indirect - github.com/fsnotify/fsnotify v1.4.9 - github.com/go-kit/log v0.2.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.16.14 + github.com/aws/aws-sdk-go-v2/config v1.17.5 + github.com/aws/aws-sdk-go-v2/credentials v1.12.18 + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.16.4 + github.com/cyphar/filepath-securejoin v0.2.3 + github.com/fsnotify/fsnotify v1.5.1 github.com/go-redis/redis/v8 v8.8.0 github.com/gomodule/redigo v1.8.2 - github.com/google/go-cmp v0.5.6 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/mux v1.8.0 - github.com/gregjones/httpcache v0.0.0-20171119193500-2bcd89a1743f - github.com/hashicorp/consul/api v1.12.0 + github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 + github.com/hashicorp/consul/api v1.15.3 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v0.16.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/kardianos/minwinsvc v0.0.0-20151122163309-cad6b2b879b0 - github.com/kr/text v0.2.0 // indirect github.com/launchdarkly/api-client-go v5.0.3+incompatible github.com/launchdarkly/eventsource v1.7.1 github.com/launchdarkly/go-configtypes v1.1.0 github.com/launchdarkly/go-server-sdk-consul v1.0.2 - github.com/launchdarkly/go-server-sdk-dynamodb v1.1.1 + github.com/launchdarkly/go-server-sdk-dynamodb/v2 v2.0.0 github.com/launchdarkly/go-server-sdk-redis-redigo v1.2.1 github.com/launchdarkly/go-test-helpers/v2 v2.3.1 - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/miekg/dns v1.1.43 // indirect - github.com/mitchellh/mapstructure v1.4.2 // indirect - github.com/onsi/gomega v1.13.0 // indirect + github.com/launchdarkly/opencensus-go-exporter-stackdriver v0.14.2 github.com/pborman/uuid v1.2.0 - github.com/prometheus/client_golang v1.11.1 // indirect - github.com/prometheus/common v0.30.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/stretchr/testify v1.7.0 + github.com/prometheus/client_golang v1.11.1 // indirect; override to address CVE-2022-21698 + github.com/stretchr/testify v1.7.1 go.opencensus.io v0.23.0 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect; fixes CVE-2021-44716 - golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect; fixes CVE-2022-29526 - golang.org/x/text v0.3.7 // indirect + golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect; override to address CVE-2022-27664 + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 + golang.org/x/text v0.3.8 // indirect; override to address CVE-2022-32149 gopkg.in/gcfg.v1 v1.2.3 gopkg.in/launchdarkly/go-jsonstream.v1 v1.0.1 gopkg.in/launchdarkly/go-sdk-common.v2 v2.4.0 @@ -55,5 +46,5 @@ require ( gopkg.in/launchdarkly/go-server-sdk-evaluation.v1 v1.5.0 gopkg.in/launchdarkly/go-server-sdk.v5 v5.9.0 gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + gopkg.in/yaml.v3 v3.0.0 // indirect ) diff --git a/go.sum b/go.sum index 2bc95c1d..cbda08b5 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjIDApI2GOPScCKwxedbs= contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= -contrib.go.opencensus.io/exporter/stackdriver v0.13.6 h1:5jjiD3beqIHucvDgsA/noHK/4oT7XLLi3Q7lwmJgA88= -contrib.go.opencensus.io/exporter/stackdriver v0.13.6/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 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= @@ -56,14 +54,40 @@ github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwc github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +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/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.37.2/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI= -github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v1.16.14 h1:db6GvO4Z2UqHt5gvT0lr6J5x5P+oQ7bdRzczVaRekMU= +github.com/aws/aws-sdk-go-v2 v1.16.14/go.mod h1:s/G+UV29dECbF5rf+RNj1xhlmvoNurGSr+McVSRj59w= +github.com/aws/aws-sdk-go-v2/config v1.17.5 h1:+NS1BWvprx7nHcIk5o32LrZgifs/7Pm1V2nWjQgZ2H0= +github.com/aws/aws-sdk-go-v2/config v1.17.5/go.mod h1:H0cvPNDO3uExWts/9PDhD/0ne2esu1uaIulwn1vkwxM= +github.com/aws/aws-sdk-go-v2/credentials v1.12.18 h1:HF62tbhARhgLfvmfwUbL9qZ+dkbZYzbFdxBb3l5gr7Q= +github.com/aws/aws-sdk-go-v2/credentials v1.12.18/go.mod h1:O7n/CPagQ33rfG6h7vR/W02ammuc5CrsSM22cNZp9so= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.15 h1:nkQ+aI0OCeYfzrBipL6ja/6VEbUnHQoZHBHtoK+Nzxw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.15/go.mod h1:Oz2/qWINxIgSmoZT9adpxJy2UhpcOAI3TIyWgYMVSz0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.21 h1:gRIXnmAVNyoRQywdNtpAkgY+f30QNzgF53Q5OobNZZs= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.21/go.mod h1:XsmHMV9c512xgsW01q7H0ut+UQQQpWX8QsFbdLHDwaU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.15 h1:noAhOo2mMDyYhTx99aYPvQw16T3fQ/DiKAv9fzpIKH8= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.15/go.mod h1:kjJ4CyD9M3Wq88GYg3IPfj67Rs0Uvz8aXK7MJ8BvE4I= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.22 h1:nF+E8HfYpOMw6M5oA9efB602VC00IHNQnB5CmFvZPvA= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.22/go.mod h1:tltHVGy977LrSOgRR5aV9+miyno/Gul/uJNPKS7FzP4= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.16.4 h1:mAZdz3kvGBWC0feqQcpUF9trQ0d1qmJVNrcUv6eneIo= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.16.4/go.mod h1:xDs8FfL3lHGCYWb0ytqxjIKT5AYLY/Oi9Mh8BV0nkLg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.8 h1:NpixDFjwr1BZg2459mX07NZnVYGGp62Lb6AtVGOLNlo= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.8/go.mod h1:MJUgrBPfGB4yk2uWoImVqd9cklry1hATyJV/7gJ6JTk= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.7.15 h1:cglph/vzXji9hnXhlWq2bVkPU0qofeOCV/Jv7AWGEh4= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.7.15/go.mod h1:NNBwPIB0wjkpeeQztU3FRD8O8T77MCrObyC1RiHf6G8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.15 h1:xlf0J6DUgAj/ocvKQxCmad8Bu1lJuRbt5Wu+4G1xw1g= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.15/go.mod h1:ZVJ7ejRl4+tkWMuCwjXoy0jd8fF5u3RCyWjSVjUIvQE= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.21 h1:7jUFr+7F4MzIjCZzy7ygRtXFQcQ0kAbT0gUvtUeAdyU= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.21/go.mod h1:q8nYq51W3gpZempYsAD83fPRlrOTMCwN+Ahg4BKFTXQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.3 h1:UTTPNP3/WzZa7hoHP3Szb/Yl0bM3NoBrf5ABy1OArUM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.3/go.mod h1:+IF75RMJh0+zqTGXGshyEGRsU2ImqWv6UuHGkHl6kEo= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.17 h1:LVM2jzEQ8mhb2dhrFl4PJ3sa5+KcKT01dsMk2Ma9/FU= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.17/go.mod h1:bQujK1n0V1D1Gz5uII1jaB1WDvhj4/T3tElsJnVXCR0= +github.com/aws/smithy-go v1.13.2 h1:TBLKyeJfXTrTXRHmsv4qWt9IQGYyWThLYaJWSahTOGE= +github.com/aws/smithy-go v1.13.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= 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= @@ -72,9 +96,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -85,6 +108,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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= @@ -97,29 +122,27 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 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/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-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-kit/log v0.1.0 h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= 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-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-redis/redis/v8 v8.8.0 h1:fDZP58UN/1RD3DjtTXP/fFZ04TFohSYhjZDkcDe2dnw= github.com/go-redis/redis/v8 v8.8.0/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -147,10 +170,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -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/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -167,8 +188,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -186,19 +208,23 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 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 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gregjones/httpcache v0.0.0-20171119193500-2bcd89a1743f h1:kOkUP6rcVVqC+KlKKENKtgfFfJyDySYhqL9srXooghY= github.com/gregjones/httpcache v0.0.0-20171119193500-2bcd89a1743f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= -github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU= +github.com/hashicorp/consul/api v1.15.3 h1:WYONYL2rxTXtlekAqblR2SCdJsizMDIj/uXb5wNy9zU= +github.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= +github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -206,35 +232,43 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng 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-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 v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.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-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-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-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= 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 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= 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/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 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= 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/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/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.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= +github.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM= +github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.9.7 h1:hkdgbqizGQHuU5IPqYM1JdSMV8nKfpuOnZYXssk9muY= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= 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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -288,61 +322,58 @@ github.com/launchdarkly/go-semver v1.0.2 h1:sYVRnuKyvxlmQCnCUyDkAhtmzSFRoX6rG2Xa github.com/launchdarkly/go-semver v1.0.2/go.mod h1:xFmMwXba5Mb+3h72Z+VeSs9ahCvKo2QFUTHRNHVqR28= github.com/launchdarkly/go-server-sdk-consul v1.0.2 h1:Kl99OW5M4u1gEYGgIgGxSNpWq1gY9GPiF8lw0fg3ieI= github.com/launchdarkly/go-server-sdk-consul v1.0.2/go.mod h1:2lk/aCHkrm7VUZuJR2RK7B0vX2YrxmhAk1uDwjnolFA= -github.com/launchdarkly/go-server-sdk-dynamodb v1.1.1 h1:lbzt1Uw0BON3TaqSDRq12wFGsu8nv4tBkLmi9TgKrJI= -github.com/launchdarkly/go-server-sdk-dynamodb v1.1.1/go.mod h1:ZCuGJJ0QWvtFeU65+iIlwVAPvOXWg9B/PWhG10S0/OY= +github.com/launchdarkly/go-server-sdk-dynamodb/v2 v2.0.0 h1:mf/YGBnEb8gOpOkYQpJB8rPuUU3pStVvKDv4P/FUPPE= +github.com/launchdarkly/go-server-sdk-dynamodb/v2 v2.0.0/go.mod h1:+GgKJxltoE18deMiDuCQL8ZlZ1s97jC5Egb+mwZPjIk= github.com/launchdarkly/go-server-sdk-redis-redigo v1.2.1 h1:5KhwXcx+0sqxjDf4m/irLCohe/8Fh72zzsC6XU3aTMc= github.com/launchdarkly/go-server-sdk-redis-redigo v1.2.1/go.mod h1:rcydnSjPuE8w5HYeOg/l98QSFUT/lM9Txk9/pbyU30k= github.com/launchdarkly/go-test-helpers/v2 v2.2.0/go.mod h1:L7+th5govYp5oKU9iN7To5PgznBuIjBPn+ejqKR0avw= github.com/launchdarkly/go-test-helpers/v2 v2.3.1 h1:KXUAQVTeHNcWVDVQ94uEkybI+URXI9rEd7E553EsZFw= github.com/launchdarkly/go-test-helpers/v2 v2.3.1/go.mod h1:L7+th5govYp5oKU9iN7To5PgznBuIjBPn+ejqKR0avw= +github.com/launchdarkly/opencensus-go-exporter-stackdriver v0.14.2 h1:ojocsFdk2ySSFqIAmtJxOQqF2aQo3q1etd+VTb5V9pA= +github.com/launchdarkly/opencensus-go-exporter-stackdriver v0.14.2/go.mod h1:E0xXDxC1FNMuovDLNlFQCY8dzQs3WoKyML8R7bugsOI= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 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 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/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= -github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +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/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 v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure 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.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4= github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= -github.com/onsi/ginkgo v1.16.2 h1:HFB2fbVIlhIfCfOW81bZFbiC/RvnpXSdhbF2/DJr134= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= 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= @@ -376,20 +407,19 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.28.0 h1:vGVfV9KrDTvWt5boZO0I19g2E3CsWfpPPKZM9dt3mEw= github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 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.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/statsd_exporter v0.21.0 h1:hA05Q5RFeIjgwKIYEdFd59xu5Wwaznf33yKI+pyX6T8= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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/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/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -404,8 +434,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -415,6 +446,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 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= @@ -440,6 +472,7 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -474,6 +507,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -514,12 +548,12 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo= +golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -542,8 +576,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ 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= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= -golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -600,9 +634,13 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/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= @@ -611,8 +649,9 @@ 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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 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= @@ -664,10 +703,10 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -761,9 +800,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/DataDog/dd-trace-go.v1 v1.22.0 h1:gpWsqqkwUldNZXGJqT69NU9MdEDhLboK1C4nMgR0MWw= gopkg.in/DataDog/dd-trace-go.v1 v1.22.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -807,8 +845,8 @@ 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-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= diff --git a/integrationtests/build_relay_test.go b/integrationtests/build_relay_test.go index 35f5d62e..424fce91 100644 --- a/integrationtests/build_relay_test.go +++ b/integrationtests/build_relay_test.go @@ -1,10 +1,10 @@ +//go:build integrationtests // +build integrationtests package integrationtests import ( "fmt" - "io/ioutil" "os" "regexp" "strings" @@ -46,7 +46,7 @@ func getRelayDockerImage(relayTagOrSHA string, loggers ldlog.Loggers) (*docker.I // Assume it is the SHA of a Git commit - try to check it out in a temporary directory loggers.Infof("Building Relay Docker image from private tag or branch: %s", relayTagOrSHA) - path, err := ioutil.TempDir("", "relay-integration-test-") + path, err := os.MkdirTemp("", "relay-integration-test-") if err != nil { return nil, err } diff --git a/integrationtests/docker/docker_helpers.go b/integrationtests/docker/docker_helpers.go index 00b4753a..3efa5a88 100644 --- a/integrationtests/docker/docker_helpers.go +++ b/integrationtests/docker/docker_helpers.go @@ -1,4 +1,3 @@ -//nolint:golint,stylecheck package docker import ( diff --git a/integrationtests/oshelpers/commands.go b/integrationtests/oshelpers/commands.go index 7d2b18ce..842b9e21 100644 --- a/integrationtests/oshelpers/commands.go +++ b/integrationtests/oshelpers/commands.go @@ -1,4 +1,3 @@ -//nolint:golint,stylecheck package oshelpers import ( diff --git a/integrationtests/request_logger_test.go b/integrationtests/request_logger_test.go index abcd6d3a..fa086822 100644 --- a/integrationtests/request_logger_test.go +++ b/integrationtests/request_logger_test.go @@ -1,3 +1,4 @@ +//go:build integrationtests // +build integrationtests package integrationtests @@ -5,7 +6,6 @@ package integrationtests import ( "bytes" "io" - "io/ioutil" "net/http" "gopkg.in/launchdarkly/go-sdk-common.v2/ldlog" @@ -56,6 +56,6 @@ func copyBody(body *io.ReadCloser) []byte { bodyCopy := bytes.NewBuffer(nil) io.Copy(bodyCopy, *body) (*body).Close() - *body = ioutil.NopCloser(bodyCopy) + *body = io.NopCloser(bodyCopy) return bodyCopy.Bytes() } diff --git a/integrationtests/test_manager_test.go b/integrationtests/test_manager_test.go index 45dc5a7d..011691fd 100644 --- a/integrationtests/test_manager_test.go +++ b/integrationtests/test_manager_test.go @@ -8,7 +8,7 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" + "io" "log" "net/http" "os" @@ -123,7 +123,7 @@ func newIntegrationTestManager() (*integrationTestManager, error) { return nil, err } - relaySharedDir, err := ioutil.TempDir("", "relay-i9ntest-") + relaySharedDir, err := os.MkdirTemp("", "relay-i9ntest-") if err != nil { return nil, err } @@ -274,7 +274,7 @@ func (m *integrationTestManager) awaitRelayStatus(t *testing.T, fn func(core.Sta } return false } - outData, err := ioutil.ReadAll(resp.Body) + outData, err := io.ReadAll(resp.Body) output := string(outData) if output != lastOutput { if !m.params.HTTPLogging { @@ -342,7 +342,7 @@ func (m *integrationTestManager) getFlagValues(t *testing.T, proj projectInfo, e require.NoError(t, err) if assert.Equal(t, 200, resp.StatusCode, "requested flags for environment "+env.key) { defer resp.Body.Close() - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) require.NoError(t, err) valuesObject := ldvalue.Parse(data) if !valuesObject.Equal(ldvalue.Null()) { diff --git a/internal/autoconfig/stream_manager.go b/internal/autoconfig/stream_manager.go index 043abbd1..d98e6ecf 100644 --- a/internal/autoconfig/stream_manager.go +++ b/internal/autoconfig/stream_manager.go @@ -30,8 +30,8 @@ const ( var ( // These regexes are used for obfuscating keys in debug logging - sdkKeyJSONRegex = regexp.MustCompile(`"value": *"[^"]*([^"][^"][^"][^"])"`) //nolint:gochecknoglobals - mobKeyJSONRegex = regexp.MustCompile(`"mobKey": *"[^"]*([^"][^"][^"][^"])"`) //nolint:gochecknoglobals + sdkKeyJSONRegex = regexp.MustCompile(`"value": *"[^"]*([^"][^"][^"][^"])"`) + mobKeyJSONRegex = regexp.MustCompile(`"mobKey": *"[^"]*([^"][^"][^"][^"])"`) ) // StreamManager manages the auto-configuration SSE stream. diff --git a/internal/core/application/commandline.go b/internal/core/application/commandline.go index bcad7ed6..cf51861b 100644 --- a/internal/core/application/commandline.go +++ b/internal/core/application/commandline.go @@ -41,8 +41,9 @@ func (o Options) DescribeConfigSource() string { // ReadOptions reads and validates the command-line options. // // The configuration parameter behavior is as follows: +// // 1. If you specify --config $FILEPATH, it loads that file. Failure to find it or parse it is a fatal error, -// unless you also specify --allow-missing-file. +// unless you also specify --allow-missing-file. // 2. If you specify --from-env, it creates a configuration from environment variables as described in README. // 3. If you specify both, the file is loaded first, then it applies changes from variables if any. // 4. Omitting all options is equivalent to explicitly specifying --config /etc/ld-relay.conf. diff --git a/internal/core/application/commandline_test.go b/internal/core/application/commandline_test.go index f10e1490..d483f66f 100644 --- a/internal/core/application/commandline_test.go +++ b/internal/core/application/commandline_test.go @@ -1,7 +1,7 @@ package application import ( - "io/ioutil" + "io" "testing" helpers "github.com/launchdarkly/go-test-helpers/v2" @@ -14,13 +14,13 @@ func TestReadOptions(t *testing.T) { appName := "ld-relay" t.Run("default config file path", func(t *testing.T) { - _, err := ReadOptions([]string{appName}, ioutil.Discard) + _, err := ReadOptions([]string{appName}, io.Discard) require.Error(t, err) assert.Equal(t, errConfigFileNotFound(DefaultConfigPath), err) }) t.Run("allow missing file with default path", func(t *testing.T) { - opts, err := ReadOptions([]string{appName, "--allow-missing-file"}, ioutil.Discard) + opts, err := ReadOptions([]string{appName, "--allow-missing-file"}, io.Discard) require.NoError(t, err) assert.Equal(t, "", opts.ConfigFile) assert.False(t, opts.UseEnvironment) @@ -28,7 +28,7 @@ func TestReadOptions(t *testing.T) { t.Run("custom config file", func(t *testing.T) { helpers.WithTempFile(func(filename string) { - opts, err := ReadOptions([]string{appName, "--config", filename}, ioutil.Discard) + opts, err := ReadOptions([]string{appName, "--config", filename}, io.Discard) require.NoError(t, err) assert.Equal(t, filename, opts.ConfigFile) assert.False(t, opts.UseEnvironment) @@ -37,7 +37,7 @@ func TestReadOptions(t *testing.T) { }) t.Run("environment only", func(t *testing.T) { - opts, err := ReadOptions([]string{appName, "--from-env"}, ioutil.Discard) + opts, err := ReadOptions([]string{appName, "--from-env"}, io.Discard) require.NoError(t, err) assert.Equal(t, "", opts.ConfigFile) assert.True(t, opts.UseEnvironment) @@ -46,7 +46,7 @@ func TestReadOptions(t *testing.T) { t.Run("environment plus config file", func(t *testing.T) { helpers.WithTempFile(func(filename string) { - opts, err := ReadOptions([]string{appName, "--config", filename, "--from-env"}, ioutil.Discard) + opts, err := ReadOptions([]string{appName, "--config", filename, "--from-env"}, io.Discard) require.NoError(t, err) assert.Equal(t, filename, opts.ConfigFile) assert.True(t, opts.UseEnvironment) @@ -55,7 +55,7 @@ func TestReadOptions(t *testing.T) { }) t.Run("invalid options", func(t *testing.T) { - _, err := ReadOptions([]string{appName, "--unknown"}, ioutil.Discard) + _, err := ReadOptions([]string{appName, "--unknown"}, io.Discard) assert.Error(t, err) }) } diff --git a/internal/core/application/server.go b/internal/core/application/server.go index 41c85424..1c75bad6 100644 --- a/internal/core/application/server.go +++ b/internal/core/application/server.go @@ -20,13 +20,15 @@ func StartHTTPServer( tlsMinVersion uint16, loggers ldlog.Loggers, ) (*http.Server, <-chan error) { - srv := &http.Server{ + srv := &http.Server{ //nolint:gosec // see comment on next line + // The linter helpfully points out that setting ReadHeaderTimeout is advisable to avoid certain + // DDOS attacks. We will be doing this, but in a separate changeset. Addr: fmt.Sprintf(":%d", port), Handler: handler, } if tlsEnabled && tlsMinVersion != 0 { - srv.TLSConfig = &tls.Config{ + srv.TLSConfig = &tls.Config{ //nolint:gosec // linter doesn't want to see MinVersion being set to a variable MinVersion: tlsMinVersion, } } diff --git a/internal/core/application/server_test.go b/internal/core/application/server_test.go index d5f67b54..e4f10071 100644 --- a/internal/core/application/server_test.go +++ b/internal/core/application/server_test.go @@ -4,9 +4,9 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "io/ioutil" "net" "net/http" + "os" "strings" "testing" "time" @@ -27,7 +27,7 @@ func withSelfSignedCert(t *testing.T, action func(certFilePath, keyFilePath stri helpers.WithTempFile(func(keyFilePath string) { err := httphelpers.MakeSelfSignedCert(certFilePath, keyFilePath) require.NoError(t, err) - certData, err := ioutil.ReadFile(certFilePath) + certData, err := os.ReadFile(certFilePath) require.NoError(t, err) certPool, err := x509.SystemCertPool() if err != nil { @@ -101,7 +101,9 @@ func TestStartHTTPServerSecureWithMinTLSVersion(t *testing.T) { require.Eventually(t, func() bool { _, err := client.Get(fmt.Sprintf("https://127.0.0.1:%d", port)) require.Error(t, err) - return strings.Contains(err.Error(), "protocol version not supported") + // the exact error message varies by Go version + return strings.Contains(err.Error(), "protocol version not supported") || + strings.Contains(err.Error(), "tls: no supported versions") }, time.Second, time.Millisecond*10) mockLog.AssertMessageMatch(t, true, ldlog.Info, fmt.Sprintf("listening on port %d", port)) mockLog.AssertMessageMatch(t, true, ldlog.Info, "TLS enabled for server \\(minimum TLS version: 1.2\\)") diff --git a/internal/core/bigsegments/store.go b/internal/core/bigsegments/store.go index 8f838cda..94e88061 100644 --- a/internal/core/bigsegments/store.go +++ b/internal/core/bigsegments/store.go @@ -7,8 +7,6 @@ import ( "gopkg.in/launchdarkly/go-sdk-common.v2/ldlog" "gopkg.in/launchdarkly/go-sdk-common.v2/ldtime" - - "github.com/aws/aws-sdk-go/aws" ) // BigSegmentStore is the interface for interacting with an external big segment store. Each instance @@ -58,7 +56,7 @@ func DefaultBigSegmentStoreFactory( } return bigSegmentRedis, nil } else if allConfig.DynamoDB.Enabled { - return newDynamoDBBigSegmentStore(allConfig.DynamoDB, envConfig, aws.Config{}, loggers) + return newDynamoDBBigSegmentStore(allConfig.DynamoDB, envConfig, nil, loggers) } return nil, nil } diff --git a/internal/core/bigsegments/store_dynamodb.go b/internal/core/bigsegments/store_dynamodb.go index 918c5802..857a9271 100644 --- a/internal/core/bigsegments/store_dynamodb.go +++ b/internal/core/bigsegments/store_dynamodb.go @@ -1,6 +1,8 @@ package bigsegments import ( + "context" + "errors" "strconv" "github.com/launchdarkly/ld-relay/v6/config" @@ -8,10 +10,10 @@ import ( "gopkg.in/launchdarkly/go-sdk-common.v2/ldlog" "gopkg.in/launchdarkly/go-sdk-common.v2/ldtime" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/dynamodb" - "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface" + "github.com/aws/aws-sdk-go-v2/aws" + awsconfig "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/dynamodb" + "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" ) const ( @@ -28,10 +30,12 @@ const ( // dynamoDBBigSegmentStore implements BigSegmentStore for DynamoDB. type dynamoDBBigSegmentStore struct { - client dynamodbiface.DynamoDBAPI - loggers ldlog.Loggers - table string - prefix string + client *dynamodb.Client + context context.Context + cancelContext context.CancelFunc + loggers ldlog.Loggers + table string + prefix string } func dynamoDBMetadataKey(prefix string) string { @@ -52,25 +56,31 @@ func dynamoDBPrefixedKey(prefix, key string) string { func newDynamoDBBigSegmentStore( dbConfig config.DynamoDBConfig, envConfig config.EnvConfig, - config aws.Config, + optFns []func(*dynamodb.Options), loggers ldlog.Loggers, ) (*dynamoDBBigSegmentStore, error) { - endpoint, table, prefix := sdks.GetDynamoDBBasicProperties(dbConfig, envConfig) + config, err := awsconfig.LoadDefaultConfig(context.Background()) + if err != nil { + return nil, err + } + endpoint, table, prefix := sdks.GetDynamoDBBasicProperties(dbConfig, envConfig) if endpoint != nil { - config.Endpoint = endpoint + optFns = append(optFns, func(o *dynamodb.Options) { + o.EndpointResolver = dynamodb.EndpointResolverFromURL(*endpoint) + }) } - sess, err := session.NewSession(&config) - if err != nil { - return nil, err - } + client := dynamodb.NewFromConfig(config, optFns...) + context, cancelContext := context.WithCancel(context.Background()) store := dynamoDBBigSegmentStore{ - table: table, - loggers: loggers, - prefix: prefix, - client: dynamodb.New(sess), + table: table, + loggers: loggers, + prefix: prefix, + client: client, + context: context, + cancelContext: cancelContext, } store.loggers.SetPrefix("DynamoDBBigSegmentStore:") @@ -79,32 +89,32 @@ func newDynamoDBBigSegmentStore( return &store, nil } -func (store *dynamoDBBigSegmentStore) makeTransactionItem(updateExpression, attribute, segmentID, userKey string) *dynamodb.TransactWriteItem { - return &dynamodb.TransactWriteItem{ - Update: &dynamodb.Update{ +func (store *dynamoDBBigSegmentStore) makeTransactionItem(updateExpression, attribute, segmentID, userKey string) types.TransactWriteItem { + return types.TransactWriteItem{ + Update: &types.Update{ TableName: aws.String(store.table), UpdateExpression: aws.String(updateExpression), - ExpressionAttributeNames: map[string]*string{ - "#0": aws.String(attribute), + ExpressionAttributeNames: map[string]string{ + "#0": attribute, }, - ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ - ":0": {SS: []*string{aws.String(segmentID)}}, + ExpressionAttributeValues: map[string]types.AttributeValue{ + ":0": &types.AttributeValueMemberSS{Value: []string{segmentID}}, }, - Key: map[string]*dynamodb.AttributeValue{ - tablePartitionKey: {S: aws.String(dynamoDBUserDataKey(store.prefix))}, - tableSortKey: {S: aws.String(userKey)}, + Key: map[string]types.AttributeValue{ + tablePartitionKey: attrValueOfString(dynamoDBUserDataKey(store.prefix)), + tableSortKey: attrValueOfString(userKey), }, }, } } -func makeCursorUpdateCondition(previousVersion string) (string, map[string]*string, map[string]*dynamodb.AttributeValue) { - names := map[string]*string{"#0": aws.String(dynamoDBCursorAttr)} +func makeCursorUpdateCondition(previousVersion string) (string, map[string]string, map[string]types.AttributeValue) { + names := map[string]string{"#0": dynamoDBCursorAttr} if previousVersion == "" { return "attribute_not_exists(#0)", names, nil } - return "#0 = :0", names, map[string]*dynamodb.AttributeValue{ - ":0": {S: aws.String(previousVersion)}, + return "#0 = :0", names, map[string]types.AttributeValue{ + ":0": attrValueOfString(previousVersion), } } @@ -113,23 +123,23 @@ func (store *dynamoDBBigSegmentStore) applyPatch(patch bigSegmentPatch) (bool, e txConditionExpression, txExprAttrNames, txExprAttrValues := makeCursorUpdateCondition(patch.PreviousVersion) - conditionCheckItem := &dynamodb.TransactWriteItem{ - ConditionCheck: &dynamodb.ConditionCheck{ + conditionCheckItem := types.TransactWriteItem{ + ConditionCheck: &types.ConditionCheck{ ConditionExpression: aws.String(txConditionExpression), TableName: aws.String(store.table), ExpressionAttributeNames: txExprAttrNames, ExpressionAttributeValues: txExprAttrValues, - Key: map[string]*dynamodb.AttributeValue{ - tablePartitionKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, - tableSortKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, + Key: map[string]types.AttributeValue{ + tablePartitionKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), + tableSortKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), }, - ReturnValuesOnConditionCheckFailure: aws.String(dynamodb.ReturnValuesOnConditionCheckFailureNone), + ReturnValuesOnConditionCheckFailure: types.ReturnValuesOnConditionCheckFailureNone, }, } totalItems := len(patch.Changes.Included.Add) + len(patch.Changes.Included.Remove) + len(patch.Changes.Excluded.Add) + len(patch.Changes.Excluded.Remove) - transactionItems := make([]*dynamodb.TransactWriteItem, 0, totalItems) + transactionItems := make([]types.TransactWriteItem, 0, totalItems) for _, user := range patch.Changes.Included.Add { item := store.makeTransactionItem(updateExpressionAdd, dynamoDBIncludedAttr, patch.SegmentID, user) @@ -151,7 +161,7 @@ func (store *dynamoDBBigSegmentStore) applyPatch(patch bigSegmentPatch) (bool, e transactionItems = append(transactionItems, item) } - transactionBatch := make([]*dynamodb.TransactWriteItem, 0, dynamoTransactionMaxItems) + transactionBatch := make([]types.TransactWriteItem, 0, dynamoTransactionMaxItems) for batchStart := 0; batchStart < len(transactionItems); batchStart += dynamoTransactionMaxItems - 1 { batchEnd := batchStart + dynamoTransactionMaxItems - 1 @@ -160,7 +170,7 @@ func (store *dynamoDBBigSegmentStore) applyPatch(patch bigSegmentPatch) (bool, e } transactionBatch = append(transactionBatch, conditionCheckItem) transactionBatch = append(transactionBatch, transactionItems[batchStart:batchEnd]...) - _, err := store.client.TransactWriteItems(&dynamodb.TransactWriteItemsInput{ + _, err := store.client.TransactWriteItems(store.context, &dynamodb.TransactWriteItemsInput{ TransactItems: transactionBatch, }) if err != nil { @@ -168,8 +178,9 @@ func (store *dynamoDBBigSegmentStore) applyPatch(patch bigSegmentPatch) (bool, e // "transaction was cancelled due to the condition check" from other errors here; we // need to go to this trouble because we want the synchronizer to be able to log an // out-of-order update in a clear way that doesn't look like a random database error. - if tce, ok := err.(*dynamodb.TransactionCanceledException); ok { - for _, reason := range tce.CancellationReasons { + var canceledErr *types.TransactionCanceledException + if errors.As(err, &canceledErr) { + for _, reason := range canceledErr.CancellationReasons { if reason.Code != nil && *reason.Code == "ConditionalCheckFailed" { return false, nil } @@ -182,24 +193,22 @@ func (store *dynamoDBBigSegmentStore) applyPatch(patch bigSegmentPatch) (bool, e updateConditionExpression, updateExprAttrNames, updateExprAttrValues := makeCursorUpdateCondition(patch.PreviousVersion) if updateExprAttrValues == nil { - updateExprAttrValues = map[string]*dynamodb.AttributeValue{} - } - updateExprAttrValues[":1"] = &dynamodb.AttributeValue{ - S: aws.String(patch.Version), + updateExprAttrValues = map[string]types.AttributeValue{} } + updateExprAttrValues[":1"] = &types.AttributeValueMemberS{Value: patch.Version} updateCursorInput := dynamodb.UpdateItemInput{ ConditionExpression: aws.String(updateConditionExpression), TableName: aws.String(store.table), ExpressionAttributeNames: updateExprAttrNames, ExpressionAttributeValues: updateExprAttrValues, - Key: map[string]*dynamodb.AttributeValue{ - tablePartitionKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, - tableSortKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, + Key: map[string]types.AttributeValue{ + tablePartitionKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), + tableSortKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), }, UpdateExpression: aws.String("SET #0 = :1"), } - _, err := store.client.UpdateItem(&updateCursorInput) + _, err := store.client.UpdateItem(store.context, &updateCursorInput) if err == nil { return true, nil } @@ -208,15 +217,15 @@ func (store *dynamoDBBigSegmentStore) applyPatch(patch bigSegmentPatch) (bool, e func (store *dynamoDBBigSegmentStore) getCursor() (string, error) { metadataKey := dynamoDBMetadataKey(store.prefix) - result, err := store.client.GetItem(&dynamodb.GetItemInput{ + result, err := store.client.GetItem(store.context, &dynamodb.GetItemInput{ TableName: aws.String(store.table), ConsistentRead: aws.Bool(true), - ExpressionAttributeNames: map[string]*string{ - "#0": aws.String(dynamoDBCursorAttr), + ExpressionAttributeNames: map[string]string{ + "#0": dynamoDBCursorAttr, }, - Key: map[string]*dynamodb.AttributeValue{ - tablePartitionKey: {S: aws.String(metadataKey)}, - tableSortKey: {S: aws.String(metadataKey)}, + Key: map[string]types.AttributeValue{ + tablePartitionKey: attrValueOfString(metadataKey), + tableSortKey: attrValueOfString(metadataKey), }, ProjectionExpression: aws.String("#0"), }) @@ -224,27 +233,25 @@ func (store *dynamoDBBigSegmentStore) getCursor() (string, error) { return "", err } item := result.Item[dynamoDBCursorAttr] - if item == nil || item.S == nil { - return "", nil + if sValue, ok := item.(*types.AttributeValueMemberS); ok { + return sValue.Value, nil } - return *item.S, nil + return "", nil } func (store *dynamoDBBigSegmentStore) setSynchronizedOn(synchronizedOn ldtime.UnixMillisecondTime) error { bigSegmentsMetadataKeyWithPrefix := dynamoDBMetadataKey(store.prefix) unixMilliseconds := strconv.FormatUint(uint64(synchronizedOn), 10) - _, err := store.client.UpdateItem(&dynamodb.UpdateItemInput{ + _, err := store.client.UpdateItem(store.context, &dynamodb.UpdateItemInput{ TableName: aws.String(store.table), - Key: map[string]*dynamodb.AttributeValue{ - tablePartitionKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, - tableSortKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, + Key: map[string]types.AttributeValue{ + tablePartitionKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), + tableSortKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), }, UpdateExpression: aws.String("SET #0 = :0"), - ExpressionAttributeNames: map[string]*string{"#0": aws.String(dynamoDBSyncTimeAttr)}, - ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ - ":0": { - N: aws.String(unixMilliseconds), - }, + ExpressionAttributeNames: map[string]string{"#0": dynamoDBSyncTimeAttr}, + ExpressionAttributeValues: map[string]types.AttributeValue{ + ":0": &types.AttributeValueMemberN{Value: unixMilliseconds}, }, }) return err @@ -252,12 +259,12 @@ func (store *dynamoDBBigSegmentStore) setSynchronizedOn(synchronizedOn ldtime.Un func (store *dynamoDBBigSegmentStore) GetSynchronizedOn() (ldtime.UnixMillisecondTime, error) { bigSegmentsMetadataKeyWithPrefix := dynamoDBMetadataKey(store.prefix) - result, err := store.client.GetItem(&dynamodb.GetItemInput{ + result, err := store.client.GetItem(store.context, &dynamodb.GetItemInput{ TableName: aws.String(store.table), ConsistentRead: aws.Bool(true), - Key: map[string]*dynamodb.AttributeValue{ - tablePartitionKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, - tableSortKey: {S: aws.String(bigSegmentsMetadataKeyWithPrefix)}, + Key: map[string]types.AttributeValue{ + tablePartitionKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), + tableSortKey: attrValueOfString(bigSegmentsMetadataKeyWithPrefix), }, ProjectionExpression: aws.String(dynamoDBSyncTimeAttr), }) @@ -265,16 +272,20 @@ func (store *dynamoDBBigSegmentStore) GetSynchronizedOn() (ldtime.UnixMillisecon return 0, err } item := result.Item[dynamoDBSyncTimeAttr] - if item == nil || item.N == nil { - return 0, nil - } - value, err := strconv.Atoi(*item.N) - if err != nil { - return 0, nil + if nValue, ok := item.(*types.AttributeValueMemberN); ok { + value, err := strconv.ParseUint(nValue.Value, 10, 64) + if err != nil { + return 0, err + } + return ldtime.UnixMillisecondTime(value), nil } - return ldtime.UnixMillisecondTime(value), nil + return 0, nil } func (store *dynamoDBBigSegmentStore) Close() error { return nil } + +func attrValueOfString(value string) types.AttributeValue { + return &types.AttributeValueMemberS{Value: value} +} diff --git a/internal/core/bigsegments/store_dynamodb_test.go b/internal/core/bigsegments/store_dynamodb_test.go index f7f3d1e0..0af6cba5 100644 --- a/internal/core/bigsegments/store_dynamodb_test.go +++ b/internal/core/bigsegments/store_dynamodb_test.go @@ -4,6 +4,8 @@ package bigsegments import ( + "context" + "errors" "fmt" "math" "strings" @@ -13,12 +15,10 @@ import ( "github.com/launchdarkly/ld-relay/v6/config" "gopkg.in/launchdarkly/go-sdk-common.v2/ldlog" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/dynamodb" - "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/dynamodb" + "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/stretchr/testify/require" ) @@ -27,14 +27,6 @@ const ( localEndpoint = "http://localhost:8000" ) -var ( - testDynamoDBConfig = aws.Config{ - Region: aws.String("us-west-2"), - Endpoint: aws.String(localEndpoint), - Credentials: credentials.NewStaticCredentials("dummy", "not", "used"), - } -) - func TestDynamoDBGenericAll(t *testing.T) { require.NoError(t, createTableIfNecessary()) @@ -45,26 +37,24 @@ func TestDynamoDBGenericAll(t *testing.T) { func (store *dynamoDBBigSegmentStore) checkSetIncludes(attribute, segmentKey, userKey string) (bool, error) { bigSegmentsUserDataKeyWithPrefix := dynamoDBUserDataKey(store.prefix) - result, err := store.client.GetItem(&dynamodb.GetItemInput{ + result, err := store.client.GetItem(context.Background(), &dynamodb.GetItemInput{ TableName: aws.String(store.table), ConsistentRead: aws.Bool(true), - Key: map[string]*dynamodb.AttributeValue{ - tablePartitionKey: {S: aws.String(bigSegmentsUserDataKeyWithPrefix)}, - tableSortKey: {S: aws.String(userKey)}, + Key: map[string]types.AttributeValue{ + tablePartitionKey: attrValueOfString(bigSegmentsUserDataKeyWithPrefix), + tableSortKey: attrValueOfString(userKey), }, }) if err != nil || len(result.Item) == 0 { return false, err } item := result.Item[attribute] - if item == nil || item.SS == nil { + ssValue, ok := item.(*types.AttributeValueMemberSS) + if !ok { return false, nil } - for _, v := range item.SS { - if v == nil { - continue - } - if *v == segmentKey { + for _, v := range ssValue.Value { + if v == segmentKey { return true, nil } } @@ -88,7 +78,7 @@ func withDynamoDBStoreGeneric(prefix string) func(*testing.T, func(BigSegmentSto store, err := newDynamoDBBigSegmentStore( config.DynamoDBConfig{TableName: testTableName}, config.EnvConfig{Prefix: prefix}, - testDynamoDBConfig, + []func(*dynamodb.Options){setTestDynamoDBOptions}, ldlog.NewDisabledLoggers(), ) require.NoError(t, err) @@ -98,13 +88,8 @@ func withDynamoDBStoreGeneric(prefix string) func(*testing.T, func(BigSegmentSto } } -func createTestClient() (*dynamodb.DynamoDB, error) { - sess, err := session.NewSession(&testDynamoDBConfig) - if err != nil { - return nil, err - } - - return dynamodb.New(sess), nil +func createTestClient() *dynamodb.Client { + return dynamodb.New(dynamodb.Options{}, setTestDynamoDBOptions) } func clearTestData(prefix string) error { @@ -112,79 +97,80 @@ func clearTestData(prefix string) error { prefix += ":" } - client, err := createTestClient() - if err != nil { - return err - } - var items []map[string]*dynamodb.AttributeValue + client := createTestClient() + var items []map[string]types.AttributeValue - err = client.ScanPages(&dynamodb.ScanInput{ + scanInput := dynamodb.ScanInput{ TableName: aws.String(testTableName), ConsistentRead: aws.Bool(true), ProjectionExpression: aws.String("#namespace, #key"), - ExpressionAttributeNames: map[string]*string{ - "#namespace": aws.String(tablePartitionKey), - "#key": aws.String(tableSortKey), + ExpressionAttributeNames: map[string]string{ + "#namespace": tablePartitionKey, + "#key": tableSortKey, }, - }, func(out *dynamodb.ScanOutput, lastPage bool) bool { + } + for { + out, err := client.Scan(context.Background(), &scanInput) + if err != nil { + return err + } items = append(items, out.Items...) - return !lastPage - }) - if err != nil { - return err + if out.LastEvaluatedKey == nil { + break + } + scanInput.ExclusiveStartKey = out.LastEvaluatedKey } - var requests []*dynamodb.WriteRequest + var requests []types.WriteRequest for _, item := range items { - if strings.HasPrefix(*item[tablePartitionKey].S, prefix) { - requests = append(requests, &dynamodb.WriteRequest{ - DeleteRequest: &dynamodb.DeleteRequest{Key: item}, + if strings.HasPrefix(attrValueToString(item[tablePartitionKey]), prefix) { + requests = append(requests, types.WriteRequest{ + DeleteRequest: &types.DeleteRequest{Key: item}, }) } } - return batchWriteRequests(client, testTableName, requests) + return batchWriteRequests(context.Background(), client, testTableName, requests) } func createTableIfNecessary() error { - client, err := createTestClient() - if err != nil { - return err - } - _, err = client.DescribeTable(&dynamodb.DescribeTableInput{TableName: aws.String(testTableName)}) + client := createTestClient() + _, err := client.DescribeTable(context.Background(), + &dynamodb.DescribeTableInput{TableName: aws.String(testTableName)}) if err == nil { return nil } - if e, ok := err.(awserr.Error); !ok || e.Code() != dynamodb.ErrCodeResourceNotFoundException { + var resNotFoundErr *types.ResourceNotFoundException + if !errors.As(err, &resNotFoundErr) { return err } createParams := dynamodb.CreateTableInput{ - AttributeDefinitions: []*dynamodb.AttributeDefinition{ + AttributeDefinitions: []types.AttributeDefinition{ { AttributeName: aws.String(tablePartitionKey), - AttributeType: aws.String(dynamodb.ScalarAttributeTypeS), + AttributeType: types.ScalarAttributeTypeS, }, { AttributeName: aws.String(tableSortKey), - AttributeType: aws.String(dynamodb.ScalarAttributeTypeS), + AttributeType: types.ScalarAttributeTypeS, }, }, - KeySchema: []*dynamodb.KeySchemaElement{ + KeySchema: []types.KeySchemaElement{ { AttributeName: aws.String(tablePartitionKey), - KeyType: aws.String(dynamodb.KeyTypeHash), + KeyType: types.KeyTypeHash, }, { AttributeName: aws.String(tableSortKey), - KeyType: aws.String(dynamodb.KeyTypeRange), + KeyType: types.KeyTypeRange, }, }, - ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ + ProvisionedThroughput: &types.ProvisionedThroughput{ ReadCapacityUnits: aws.Int64(1), WriteCapacityUnits: aws.Int64(1), }, TableName: aws.String(testTableName), } - _, err = client.CreateTable(&createParams) + _, err = client.CreateTable(context.Background(), &createParams) if err != nil { return err } @@ -197,8 +183,9 @@ func createTableIfNecessary() error { case <-deadline: return fmt.Errorf("timed out waiting for new table to be ready") case <-retry.C: - tableInfo, err := client.DescribeTable(&dynamodb.DescribeTableInput{TableName: aws.String(testTableName)}) - if err == nil && *tableInfo.Table.TableStatus == dynamodb.TableStatusActive { + tableInfo, err := client.DescribeTable(context.Background(), + &dynamodb.DescribeTableInput{TableName: aws.String(testTableName)}) + if err == nil && tableInfo.Table.TableStatus == types.TableStatusActive { return nil } } @@ -208,17 +195,18 @@ func createTableIfNecessary() error { // batchWriteRequests executes a list of write requests (PutItem or DeleteItem) // in batches of 25, which is the maximum BatchWriteItem can handle. func batchWriteRequests( - client dynamodbiface.DynamoDBAPI, + context context.Context, + client *dynamodb.Client, table string, - requests []*dynamodb.WriteRequest, + requests []types.WriteRequest, ) error { for len(requests) > 0 { batchSize := int(math.Min(float64(len(requests)), 25)) batch := requests[:batchSize] requests = requests[batchSize:] - _, err := client.BatchWriteItem(&dynamodb.BatchWriteItemInput{ - RequestItems: map[string][]*dynamodb.WriteRequest{table: batch}, + _, err := client.BatchWriteItem(context, &dynamodb.BatchWriteItemInput{ + RequestItems: map[string][]types.WriteRequest{table: batch}, }) if err != nil { // COVERAGE: can't simulate this condition in unit tests because we will only get this @@ -229,3 +217,20 @@ func batchWriteRequests( } return nil } + +func attrValueToString(value types.AttributeValue) string { + switch v := value.(type) { + case *types.AttributeValueMemberS: + return v.Value + case *types.AttributeValueMemberN: + return v.Value + default: + return "" + } +} + +func setTestDynamoDBOptions(o *dynamodb.Options) { + o.Region = "us-west-2" + o.EndpointResolver = dynamodb.EndpointResolverFromURL(localEndpoint) + o.Credentials = credentials.NewStaticCredentialsProvider("dummy", "not", "used") +} diff --git a/internal/core/bigsegments/store_redis.go b/internal/core/bigsegments/store_redis.go index c81e60fa..cce85630 100644 --- a/internal/core/bigsegments/store_redis.go +++ b/internal/core/bigsegments/store_redis.go @@ -69,7 +69,10 @@ func newRedisBigSegmentStore( opts.Password = redisConfig.Password } if redisConfig.TLS && opts.TLSConfig == nil { - opts.TLSConfig = &tls.Config{ServerName: redisConfig.URL.Get().Hostname()} + opts.TLSConfig = &tls.Config{ + ServerName: redisConfig.URL.Get().Hostname(), + MinVersion: tls.VersionTLS12, + } } store := redisBigSegmentStore{ diff --git a/internal/core/bigsegments/sync.go b/internal/core/bigsegments/sync.go index 28c5800f..29108e2e 100644 --- a/internal/core/bigsegments/sync.go +++ b/internal/core/bigsegments/sync.go @@ -3,7 +3,7 @@ package bigsegments import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "strings" "sync" @@ -329,7 +329,7 @@ func (s *defaultBigSegmentSynchronizer) poll() (bool, segmentChangesSummary, err return false, segmentChangesSummary{}, &httpStatusError{response.StatusCode} } - responseBody, err := ioutil.ReadAll(response.Body) + responseBody, err := io.ReadAll(response.Body) if err != nil { return false, segmentChangesSummary{}, err } diff --git a/internal/core/bigsegments/sync_test.go b/internal/core/bigsegments/sync_test.go index 9952a123..1e03c30d 100644 --- a/internal/core/bigsegments/sync_test.go +++ b/internal/core/bigsegments/sync_test.go @@ -98,7 +98,7 @@ func requireNoMorePatches(t *testing.T, s *bigSegmentStoreMock) { for len(s.patchCh) > 0 { patches = append(patches, <-s.patchCh) } - require.Fail(t, "did not expect any more patches, but got: %+v", patches) + require.Fail(t, "did not expect any more patches, but got some", "patches: %+v", patches) } } diff --git a/internal/core/httpconfig/httpconfig_test.go b/internal/core/httpconfig/httpconfig_test.go index 310bf286..c5ccf190 100644 --- a/internal/core/httpconfig/httpconfig_test.go +++ b/internal/core/httpconfig/httpconfig_test.go @@ -2,9 +2,9 @@ package httpconfig import ( "crypto/x509" - "io/ioutil" "net/http" "net/http/httptest" + "os" "testing" "github.com/launchdarkly/ld-relay/v6/config" @@ -72,7 +72,7 @@ func TestSimpleProxyWithCACert(t *testing.T) { httphelpers.WithSelfSignedServer(handler, func(server *httptest.Server, certData []byte, certPool *x509.CertPool) { helpers.WithTempFile(func(certFilePath string) { - require.NoError(t, ioutil.WriteFile(certFilePath, certData, 0)) + require.NoError(t, os.WriteFile(certFilePath, certData, 0)) proxyConfig := config.ProxyConfig{} proxyConfig.URL, _ = configtypes.NewOptURLAbsoluteFromString(server.URL) proxyConfig.CACertFiles = configtypes.NewOptStringList([]string{certFilePath}) diff --git a/internal/core/internal/events/event-relay.go b/internal/core/internal/events/event-relay.go index c92a1f5f..9c2eafe7 100644 --- a/internal/core/internal/events/event-relay.go +++ b/internal/core/internal/events/event-relay.go @@ -2,7 +2,7 @@ package events import ( "encoding/json" - "io/ioutil" + "io" "net/http" "reflect" "strings" @@ -142,7 +142,7 @@ func (d *diagnosticEventEndpointDispatcher) dispatch(w http.ResponseWriter, req } func consumeEvents(w http.ResponseWriter, req *http.Request, loggers ldlog.Loggers, thenExecute func([]byte)) { - body, bodyErr := ioutil.ReadAll(req.Body) + body, bodyErr := io.ReadAll(req.Body) if bodyErr != nil { // COVERAGE: can't make this happen in unit tests loggers.Errorf("Error reading event post body: %+v", bodyErr) diff --git a/internal/core/internal/metrics/metrics.go b/internal/core/internal/metrics/metrics.go index 8eae45e4..96ac4209 100644 --- a/internal/core/internal/metrics/metrics.go +++ b/internal/core/internal/metrics/metrics.go @@ -176,5 +176,5 @@ func sanitizeTagValue(v string) string { if strings.TrimSpace(v) == "" { return "_" } - return strings.Replace(v, "/", "_", -1) + return strings.ReplaceAll(v, "/", "_") } diff --git a/internal/core/internal/metrics/prometheus.go b/internal/core/internal/metrics/prometheus.go index d6733ed5..846490ec 100644 --- a/internal/core/internal/metrics/prometheus.go +++ b/internal/core/internal/metrics/prometheus.go @@ -61,7 +61,9 @@ func (p prometheusExporterTypeImpl) createExporterIfEnabled( exporterMux := http.NewServeMux() exporterMux.Handle("/metrics", exporter) - server := &http.Server{ + server := &http.Server{ //nolint:gosec // see comment on next line + // The linter helpfully points out that setting ReadHeaderTimeout is advisable to avoid certain + // DDOS attacks. We will be doing this, but in a separate changeset. Addr: fmt.Sprintf(":%d", port), Handler: exporterMux, } diff --git a/internal/core/internal/metrics/stackdriver.go b/internal/core/internal/metrics/stackdriver.go index 637a9cef..e82bae5b 100644 --- a/internal/core/internal/metrics/stackdriver.go +++ b/internal/core/internal/metrics/stackdriver.go @@ -5,7 +5,7 @@ import ( "gopkg.in/launchdarkly/go-sdk-common.v2/ldlog" - "contrib.go.opencensus.io/exporter/stackdriver" + stackdriver "github.com/launchdarkly/opencensus-go-exporter-stackdriver" "go.opencensus.io/stats/view" "go.opencensus.io/trace" ) diff --git a/internal/core/internal/metrics/stackdriver_test.go b/internal/core/internal/metrics/stackdriver_test.go index d3b203bb..59d07d90 100644 --- a/internal/core/internal/metrics/stackdriver_test.go +++ b/internal/core/internal/metrics/stackdriver_test.go @@ -1,7 +1,6 @@ package metrics import ( - "io/ioutil" "os" "testing" @@ -84,7 +83,7 @@ func TestStackdriverExporterType(t *testing.T) { func withDefaultGoogleApplicationCredentials(data []byte, action func()) { varName := "GOOGLE_APPLICATION_CREDENTIALS" helpers.WithTempFile(func(filename string) { - ioutil.WriteFile(filename, data, 0644) + os.WriteFile(filename, data, 0644) oldVar := os.Getenv(varName) defer os.Setenv(varName, oldVar) os.Setenv(varName, filename) diff --git a/internal/core/relay_core.go b/internal/core/relay_core.go index 03f3dc9b..b746a98b 100644 --- a/internal/core/relay_core.go +++ b/internal/core/relay_core.go @@ -344,7 +344,7 @@ func (r *RelayCore) WaitForAllClients(timeout time.Duration) error { case failed := <-resultCh: if failed { if r.config.Main.ExitOnError { - os.Exit(1) + os.Exit(1) //nolint:gocritic // yes, we know the defer will not run after Exit } return errSomeEnvironmentFailed } diff --git a/internal/core/relay_core_end_to_end_test.go b/internal/core/relay_core_end_to_end_test.go index b1331a81..349e30d8 100644 --- a/internal/core/relay_core_end_to_end_test.go +++ b/internal/core/relay_core_end_to_end_test.go @@ -1,7 +1,7 @@ package core import ( - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -140,7 +140,7 @@ func (p relayCoreEndToEndTestParams) expectEvalResult(testEnv st.TestEnv, kind b require.NoError(p.t, err) defer resp.Body.Close() require.Equal(p.t, 200, resp.StatusCode) - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) require.NoError(p.t, err) return ldvalue.Parse(body) } diff --git a/internal/core/relay_core_endpoints.go b/internal/core/relay_core_endpoints.go index 47d6f31f..621e0351 100644 --- a/internal/core/relay_core_endpoints.go +++ b/internal/core/relay_core_endpoints.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "sort" "strconv" @@ -44,7 +43,7 @@ func getClientSideUserProperties( _, _ = w.Write([]byte("Content-Type must be application/json.")) return user, false } - body, _ := ioutil.ReadAll(req.Body) + body, _ := io.ReadAll(req.Body) userDecodeErr = json.Unmarshal(body, &user) } else { base64User := mux.Vars(req)["user"] @@ -119,7 +118,7 @@ func pollAllFlagsHandler(w http.ResponseWriter, req *http.Request) { } respData := serializeFlagsAsMap(data) // Compute an overall Etag for the data set by hashing flag keys and versions - hash := sha1.New() // nolint:gas // just used for insecure hashing + hash := sha1.New() //nolint:gas // just used for insecure hashing sort.Slice(data, func(i, j int) bool { return data[i].Key < data[j].Key }) // makes the hash deterministic for _, item := range data { _, _ = io.WriteString(hash, fmt.Sprintf("%s:%d", item.Key, item.Item.Version)) diff --git a/internal/core/relay_core_endpoints_status.go b/internal/core/relay_core_endpoints_status.go index 3e99d81a..82ce58bc 100644 --- a/internal/core/relay_core_endpoints_status.go +++ b/internal/core/relay_core_endpoints_status.go @@ -88,8 +88,8 @@ type DataStoreStatusRep struct { } var ( - hexDigitRegex = regexp.MustCompile(`[a-fA-F\d]`) //nolint:gochecknoglobals - alphaPrefixRegex = regexp.MustCompile(`^[a-z][a-z][a-z]-`) //nolint:gochecknoglobals + hexDigitRegex = regexp.MustCompile(`[a-fA-F\d]`) + alphaPrefixRegex = regexp.MustCompile(`^[a-z][a-z][a-z]-`) ) // ObscureKey returns an obfuscated version of an SDK key or mobile key. diff --git a/internal/core/relay_core_endpoints_test.go b/internal/core/relay_core_endpoints_test.go index 80bf7826..c927a33c 100644 --- a/internal/core/relay_core_endpoints_test.go +++ b/internal/core/relay_core_endpoints_test.go @@ -1,7 +1,7 @@ package core import ( - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -46,7 +46,7 @@ func TestReportFlagEvalFailsallowMethodOptionsHandlerWithUninitializedClientAndS assert.Equal(t, http.StatusServiceUnavailable, resp.Code) - b, _ := ioutil.ReadAll(resp.Body) + b, _ := io.ReadAll(resp.Body) assert.JSONEq(t, `{"message":"Service not initialized"}`, string(b)) } @@ -61,6 +61,6 @@ func TestReportFlagEvalWorksWithUninitializedClientButInitializedStore(t *testin assert.Equal(t, http.StatusOK, resp.Code) - b, _ := ioutil.ReadAll(resp.Body) + b, _ := io.ReadAll(resp.Body) assert.JSONEq(t, st.MakeEvalBody(st.ClientSideFlags, false, false), string(b)) } diff --git a/internal/core/sdks/big_segments_test.go b/internal/core/sdks/big_segments_test.go index e6393e66..c1a9ace1 100644 --- a/internal/core/sdks/big_segments_test.go +++ b/internal/core/sdks/big_segments_test.go @@ -3,7 +3,6 @@ package sdks import ( "testing" - lddynamodb "github.com/launchdarkly/go-server-sdk-dynamodb" "github.com/launchdarkly/ld-relay/v6/config" "github.com/launchdarkly/go-configtypes" @@ -76,43 +75,8 @@ func TestBigSegmentsRedis(t *testing.T) { }) } -func TestBigSegmentsDynamoDB(t *testing.T) { - table := "my-table" - - t.Run("basic properties - global table name", func(t *testing.T) { - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - TableName: table, - }, - } - expected := ldcomponents.BigSegments(lddynamodb.DataStore(table)) - log := assertBigSegmentsConfigured(t, expected, c, config.EnvConfig{}) - log.AssertMessageMatch(t, true, ldlog.Info, "Using DynamoDB big segment store: "+table) - }) - - t.Run("basic properties - per-environment table name", func(t *testing.T) { - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - }, - } - ec := config.EnvConfig{TableName: table} - expected := ldcomponents.BigSegments(lddynamodb.DataStore(table)) - log := assertBigSegmentsConfigured(t, expected, c, ec) - log.AssertMessageMatch(t, true, ldlog.Info, "Using DynamoDB big segment store: "+table) - }) - - t.Run("prefix", func(t *testing.T) { - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - TableName: table, - }, - } - ec := config.EnvConfig{Prefix: "abc"} - expected := ldcomponents.BigSegments(lddynamodb.DataStore(table).Prefix("abc")) - log := assertBigSegmentsConfigured(t, expected, c, ec) - log.AssertMessageMatch(t, true, ldlog.Info, "Using DynamoDB big segment store: "+table+" with prefix: abc") - }) -} +// Unfortunately, there's no good way to test the DynamoDB builder property setters, because the +// internal configuration object that it creates has some function values inside it-- which makes +// equality tests impossible, and there's no way to inspect the fields directly. However, our +// unit tests and integration tests that run against a local DynamoDB instance do indirectly verify +// that we're setting most of these properties, since otherwise those tests wouldn't work. diff --git a/internal/core/sdks/data_stores.go b/internal/core/sdks/data_stores.go index 7a38b51f..e95e7ecd 100644 --- a/internal/core/sdks/data_stores.go +++ b/internal/core/sdks/data_stores.go @@ -1,6 +1,7 @@ package sdks import ( + "context" "errors" "strings" @@ -8,14 +9,15 @@ import ( "github.com/launchdarkly/ld-relay/v6/internal/util" ldconsul "github.com/launchdarkly/go-server-sdk-consul" - lddynamodb "github.com/launchdarkly/go-server-sdk-dynamodb" + lddynamodb "github.com/launchdarkly/go-server-sdk-dynamodb/v2" ldredis "github.com/launchdarkly/go-server-sdk-redis-redigo" "gopkg.in/launchdarkly/go-sdk-common.v2/ldlog" "gopkg.in/launchdarkly/go-server-sdk.v5/interfaces" "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go-v2/aws" + awsconfig "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/dynamodb" redigo "github.com/gomodule/redigo/redis" consul "github.com/hashicorp/consul/api" ) @@ -197,8 +199,16 @@ func makeDynamoDBDataStoreBuilder( } builder := lddynamodb.DataStore(tableName). Prefix(prefix) + config, err := awsconfig.LoadDefaultConfig(context.Background()) + if err != nil { + return nil, "", err + } + var options []func(*dynamodb.Options) if endpoint != nil { - builder.SessionOptions(session.Options{Config: aws.Config{Endpoint: endpoint}}) + options = append(options, func(o *dynamodb.Options) { + o.EndpointResolver = dynamodb.EndpointResolverFromURL(*endpoint) + }) } + builder.ClientConfig(config, options...) return builder, tableName, nil } diff --git a/internal/core/sdks/data_stores_test.go b/internal/core/sdks/data_stores_test.go index 883de66a..d6d367b8 100644 --- a/internal/core/sdks/data_stores_test.go +++ b/internal/core/sdks/data_stores_test.go @@ -8,15 +8,12 @@ import ( "github.com/launchdarkly/go-configtypes" ldconsul "github.com/launchdarkly/go-server-sdk-consul" - lddynamodb "github.com/launchdarkly/go-server-sdk-dynamodb" ldredis "github.com/launchdarkly/go-server-sdk-redis-redigo" "gopkg.in/launchdarkly/go-sdk-common.v2/ldlog" "gopkg.in/launchdarkly/go-sdk-common.v2/ldlogtest" "gopkg.in/launchdarkly/go-server-sdk.v5/interfaces" "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" consul "github.com/hashicorp/consul/api" "github.com/stretchr/testify/assert" ) @@ -224,89 +221,11 @@ func TestConfigureDataStoreConsul(t *testing.T) { } func TestConfigureDataStoreDynamoDB(t *testing.T) { - table := "my-table" - - t.Run("basic properties - global table name", func(t *testing.T) { - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - TableName: table, - }, - } - expected := ldcomponents.PersistentDataStore( - lddynamodb.DataStore(table), - ).CacheTime(config.DefaultDatabaseCacheTTL) - expectedInfo := DataStoreEnvironmentInfo{DBType: "dynamodb", DBTable: table} - log := assertFactoryConfigured(t, expected, expectedInfo, c, config.EnvConfig{}) - log.AssertMessageMatch(t, true, ldlog.Info, "Using DynamoDB data store: "+table) - }) - - t.Run("basic properties - per-environment table name", func(t *testing.T) { - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - }, - } - ec := config.EnvConfig{TableName: table} - expected := ldcomponents.PersistentDataStore( - lddynamodb.DataStore(table), - ).CacheTime(config.DefaultDatabaseCacheTTL) - expectedInfo := DataStoreEnvironmentInfo{DBType: "dynamodb", DBTable: table} - log := assertFactoryConfigured(t, expected, expectedInfo, c, ec) - log.AssertMessageMatch(t, true, ldlog.Info, "Using DynamoDB data store: "+table) - }) - - t.Run("prefix", func(t *testing.T) { - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - TableName: table, - }, - } - ec := config.EnvConfig{Prefix: "abc"} - expected := ldcomponents.PersistentDataStore( - lddynamodb.DataStore(table).Prefix("abc"), - ).CacheTime(config.DefaultDatabaseCacheTTL) - expectedInfo := DataStoreEnvironmentInfo{DBType: "dynamodb", DBTable: table, DBPrefix: "abc"} - log := assertFactoryConfigured(t, expected, expectedInfo, c, ec) - - log.AssertMessageMatch(t, true, ldlog.Info, "Using DynamoDB data store: "+table+" with prefix: abc") - }) - - t.Run("TTL", func(t *testing.T) { - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - TableName: table, - LocalTTL: configtypes.NewOptDuration(time.Hour), - }, - } - expected := ldcomponents.PersistentDataStore( - lddynamodb.DataStore(table), - ).CacheTime(time.Hour) - expectedInfo := DataStoreEnvironmentInfo{DBType: "dynamodb", DBTable: table} - assertFactoryConfigured(t, expected, expectedInfo, c, config.EnvConfig{}) - }) - - t.Run("URL", func(t *testing.T) { - url := "http://fake-dynamodb" - c := config.Config{ - DynamoDB: config.DynamoDBConfig{ - Enabled: true, - TableName: table, - }, - } - c.DynamoDB.URL, _ = configtypes.NewOptURLAbsoluteFromString(url) - expected := ldcomponents.PersistentDataStore( - lddynamodb.DataStore(table).SessionOptions(session.Options{ - Config: aws.Config{ - Endpoint: aws.String(url), - }, - }), - ).CacheTime(config.DefaultDatabaseCacheTTL) - expectedInfo := DataStoreEnvironmentInfo{DBType: "dynamodb", DBServer: url, DBTable: table} - assertFactoryConfigured(t, expected, expectedInfo, c, config.EnvConfig{}) - }) + // Unfortunately, there's no good way to test the DynamoDB builder property setters, because the + // internal configuration object that it creates has some function values inside it-- which makes + // equality tests impossible, and there's no way to inspect the fields directly. However, our + // unit tests and integration tests that run against a local DynamoDB instance do indirectly verify + // that we're setting most of these properties, since otherwise those tests wouldn't work. t.Run("error - no table", func(t *testing.T) { c := config.Config{ diff --git a/internal/core/sharedtest/os_helpers.go b/internal/core/sharedtest/os_helpers.go index 6f5ac4e0..f171dc9f 100644 --- a/internal/core/sharedtest/os_helpers.go +++ b/internal/core/sharedtest/os_helpers.go @@ -1,13 +1,12 @@ package sharedtest import ( - "io/ioutil" "os" ) // WithTempDir creates a temporary directory, calls the function with its path, then removes it. func WithTempDir(fn func(path string)) { - path, err := ioutil.TempDir("", "relay-test-") + path, err := os.MkdirTemp("", "relay-test-") if err != nil { panic(err) } diff --git a/internal/core/sharedtest/requests.go b/internal/core/sharedtest/requests.go index a06d35e2..7c16788e 100644 --- a/internal/core/sharedtest/requests.go +++ b/internal/core/sharedtest/requests.go @@ -3,7 +3,6 @@ package sharedtest import ( "bytes" "io" - "io/ioutil" "net/http" "net/http/httptest" "strings" @@ -58,7 +57,7 @@ func DoRequest(req *http.Request, handler http.Handler) (*http.Response, []byte) result := w.Result() var body []byte if result.Body != nil { - body, _ = ioutil.ReadAll(result.Body) + body, _ = io.ReadAll(result.Body) _ = result.Body.Close() } diff --git a/internal/core/sharedtest/testsuites/endpoints_events.go b/internal/core/sharedtest/testsuites/endpoints_events.go index a36d7667..a8d3c3f4 100644 --- a/internal/core/sharedtest/testsuites/endpoints_events.go +++ b/internal/core/sharedtest/testsuites/endpoints_events.go @@ -3,7 +3,7 @@ package testsuites import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "strconv" @@ -56,7 +56,7 @@ func relayEventsTest(t *testing.T, config c.Config, constructor TestConstructor, eventsCh := make(chan publishedEvent, 10) eventsServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - data, _ := ioutil.ReadAll(req.Body) + data, _ := io.ReadAll(req.Body) eventsCh <- publishedEvent{url: req.URL.String(), data: data, authKey: req.Header.Get("Authorization")} w.WriteHeader(http.StatusAccepted) })) diff --git a/internal/core/sharedtest/testsuites/endpoints_other.go b/internal/core/sharedtest/testsuites/endpoints_other.go index 45982ab0..8c35746a 100644 --- a/internal/core/sharedtest/testsuites/endpoints_other.go +++ b/internal/core/sharedtest/testsuites/endpoints_other.go @@ -2,7 +2,7 @@ package testsuites import ( "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -23,7 +23,7 @@ func DoJSClientGoalsEndpointTest(t *testing.T, constructor TestConstructor) { fakeGoalsEndpoint := mux.NewRouter() fakeGoalsEndpoint.HandleFunc("/sdk/goals/{envId}", func(w http.ResponseWriter, req *http.Request) { - _, _ = ioutil.ReadAll(req.Body) + _, _ = io.ReadAll(req.Body) if mux.Vars(req)["envId"] != string(envID) { w.WriteHeader(http.StatusNotFound) return diff --git a/internal/core/sharedtest/testsuites/endpoints_streams.go b/internal/core/sharedtest/testsuites/endpoints_streams.go index 226b6889..5cfcb1b5 100644 --- a/internal/core/sharedtest/testsuites/endpoints_streams.go +++ b/internal/core/sharedtest/testsuites/endpoints_streams.go @@ -2,7 +2,7 @@ package testsuites import ( "encoding/json" - "io/ioutil" + "io" "net/http" "testing" "time" @@ -171,7 +171,7 @@ func doStreamRequestExpectingError(req *http.Request, handler http.Handler) *htt w, bodyReader := st.NewStreamRecorder() handler.ServeHTTP(w, req) go func() { - _, _ = ioutil.ReadAll(bodyReader) + _, _ = io.ReadAll(bodyReader) }() return w.Result() } diff --git a/internal/filedata/archive_manager_test.go b/internal/filedata/archive_manager_test.go index ed415a23..483d8446 100644 --- a/internal/filedata/archive_manager_test.go +++ b/internal/filedata/archive_manager_test.go @@ -2,7 +2,6 @@ package filedata import ( "fmt" - "io/ioutil" "os" "strings" "testing" @@ -63,7 +62,7 @@ func TestStartWithFileWithOneBadEnvironment(t *testing.T) { archiveManagerTest(t, func(filePath string) { writeArchive(t, filePath, false, func(dirPath string) { badData := []byte("that doesn't look like anything to me") - require.NoError(t, ioutil.WriteFile(envMetadataFilePath(dirPath, testEnv1.rep.EnvID), badData, 0660)) + require.NoError(t, os.WriteFile(envMetadataFilePath(dirPath, testEnv1.rep.EnvID), badData, 0660)) rehash(dirPath, testEnv1.rep.EnvID, testEnv2.rep.EnvID) }, testEnv1, testEnv2) }, func(p archiveManagerTestParams) { diff --git a/internal/filedata/archive_reader.go b/internal/filedata/archive_reader.go index 9f2d65c8..39117a0d 100644 --- a/internal/filedata/archive_reader.go +++ b/internal/filedata/archive_reader.go @@ -10,7 +10,6 @@ import ( "fmt" "hash" "io" - "io/ioutil" "os" "path/filepath" "sort" @@ -21,6 +20,8 @@ import ( "gopkg.in/launchdarkly/go-server-sdk.v5/interfaces/ldstoretypes" "gopkg.in/launchdarkly/go-server-sdk.v5/ldcomponents/ldstoreimpl" + + securejoin "github.com/cyphar/filepath-securejoin" ) const ( @@ -72,7 +73,7 @@ func getEnvIDFromMetadataFileName(filename string) config.EnvironmentID { // It verifies the checksum, but does not try to read the individual environment data until you call // GetEnvironmentMetadata or GetEnvironmentSDKData. func newArchiveReader(filePath string) (*archiveReader, error) { - dirPath, err := ioutil.TempDir("", "ld-relay-") + dirPath, err := os.MkdirTemp("", "ld-relay-") if err != nil { return nil, err // COVERAGE: can't cause this condition in unit tests (unexpected OS error) } @@ -82,7 +83,7 @@ func newArchiveReader(filePath string) (*archiveReader, error) { } } envIDs := discoverEnvironmentIDs(dirPath) - expectedChecksum, err := ioutil.ReadFile(checksumFilePath(dirPath)) + expectedChecksum, err := os.ReadFile(checksumFilePath(dirPath)) if err != nil { return nil, errMissingEnvironmentFile(environmentsChecksumFileName, err) } @@ -112,7 +113,7 @@ func (ar *archiveReader) GetEnvironmentIDs() []config.EnvironmentID { // GetEnvironmentMetadata attempts to read the "$ENVID.json" file for the specified environment. func (ar *archiveReader) GetEnvironmentMetadata(envID config.EnvironmentID) (environmentMetadata, error) { - data, err := ioutil.ReadFile(envMetadataFilePath(ar.dirPath, envID)) + data, err := os.ReadFile(envMetadataFilePath(ar.dirPath, envID)) if err != nil { return environmentMetadata{}, err // COVERAGE: should be impossible if the checksum passed } @@ -134,7 +135,7 @@ func (ar *archiveReader) GetEnvironmentMetadata(envID config.EnvironmentID) (env // data might not have changed for all environments. We check the metadata first, and if the DataID // property has not changed then we won't bother re-parsing the SDK data. func (ar *archiveReader) GetEnvironmentSDKData(envID config.EnvironmentID) ([]ldstoretypes.Collection, error) { - data, err := ioutil.ReadFile(envSDKDataFilePath(ar.dirPath, envID)) + data, err := os.ReadFile(envSDKDataFilePath(ar.dirPath, envID)) if err != nil { return nil, err // COVERAGE: should be impossible if the checksum passed } @@ -209,8 +210,11 @@ func readTar(r io.Reader, targetDir string) error { if h.Typeflag != tar.TypeReg { continue } - outPath := filepath.Join(targetDir, h.Name) - outFile, err := os.OpenFile(outPath, os.O_CREATE|os.O_RDWR, os.FileMode(h.Mode)) + outPath, err := securejoin.SecureJoin(targetDir, h.Name) + if err != nil { + return err // COVERAGE: can't cause this condition in unit tests + } + outFile, err := os.OpenFile(outPath, os.O_CREATE|os.O_RDWR, os.FileMode(h.Mode)) //nolint:gosec // yes, we know the file path is a variable if err != nil { return err // COVERAGE: can't cause this condition in unit tests } @@ -227,7 +231,7 @@ func readTar(r io.Reader, targetDir string) error { } func discoverEnvironmentIDs(dirPath string) []config.EnvironmentID { - files, _ := ioutil.ReadDir(dirPath) // should never fail, but if it does, files will be nil anyway + files, _ := os.ReadDir(dirPath) // should never fail, but if it does, files will be nil anyway var ret []config.EnvironmentID for _, file := range files { if isMetadataFileName(file.Name()) { diff --git a/internal/filedata/archive_reader_test.go b/internal/filedata/archive_reader_test.go index db00a7ae..3a27806c 100644 --- a/internal/filedata/archive_reader_test.go +++ b/internal/filedata/archive_reader_test.go @@ -1,7 +1,6 @@ package filedata import ( - "io/ioutil" "os" "sort" "testing" @@ -86,7 +85,7 @@ func TestEnvironmentHasMalformedMetadata(t *testing.T) { helpers.WithTempFile(func(filePath string) { writeArchive(t, filePath, false, func(dirPath string) { badData := []byte("whatever") - require.NoError(t, ioutil.WriteFile(envMetadataFilePath(dirPath, testEnv1.id()), badData, 0600)) + require.NoError(t, os.WriteFile(envMetadataFilePath(dirPath, testEnv1.id()), badData, 0600)) rehash(dirPath, testEnv1.id()) }, testEnv1) ar, err := newArchiveReader(filePath) diff --git a/internal/filedata/testdata_test.go b/internal/filedata/testdata_test.go index 9160f66a..e57cc0ce 100644 --- a/internal/filedata/testdata_test.go +++ b/internal/filedata/testdata_test.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "os" "path/filepath" "sort" @@ -154,15 +153,15 @@ func withTestData(fn func(dirPath string), envs ...testEnv) { if err != nil { panic(err) } - ioutil.WriteFile(envMetadataFilePath(dirPath, te.rep.EnvID), fileData, 0600) - ioutil.WriteFile(envSDKDataFilePath(dirPath, te.rep.EnvID), te.sdkDataJSON(), 0600) + os.WriteFile(envMetadataFilePath(dirPath, te.rep.EnvID), fileData, 0600) + os.WriteFile(envSDKDataFilePath(dirPath, te.rep.EnvID), te.sdkDataJSON(), 0600) h.Write(fileData) } checksum, err := computeEnvironmentsChecksum(dirPath, envIDs) if err != nil { panic(err) } - err = ioutil.WriteFile(checksumFilePath(dirPath), checksum, 0600) + err = os.WriteFile(checksumFilePath(dirPath), checksum, 0600) if err != nil { panic(err) } @@ -225,7 +224,7 @@ func writeArchive(t *testing.T, filePath string, compressed bool, modifyFn func( func writeMalformedArchive(filePath string) { _ = os.Remove(filePath) data := []byte("not valid") - err := ioutil.WriteFile(filePath, data, 0600) + err := os.WriteFile(filePath, data, 0600) if err != nil { panic(err) } @@ -256,7 +255,7 @@ func rehash(dirPath string, envIDs ...config.EnvironmentID) { if err != nil { panic(err) } - err = ioutil.WriteFile(checksumFilePath(dirPath), newHash, 0660) + err = os.WriteFile(checksumFilePath(dirPath), newHash, 0660) if err != nil { panic(err) } diff --git a/internal/util/closers.go b/internal/util/closers.go index 3d0c06f9..2f50c2ee 100644 --- a/internal/util/closers.go +++ b/internal/util/closers.go @@ -7,18 +7,18 @@ import ( // CleanupTasks accumulates a list of things which should be done at the end of a method unless Clear() // is called. Intended usage: // -// var cleanup CleanupTasks -// defer cleanup.Run() +// var cleanup CleanupTasks +// defer cleanup.Run() // -// thing1 := createThing1() -// cleanup.AddCloser(thing1) +// thing1 := createThing1() +// cleanup.AddCloser(thing1) // -// err := doSomethingElse() -// if err != nil { -// return err // thing1 will be disposed of automatically -// } +// err := doSomethingElse() +// if err != nil { +// return err // thing1 will be disposed of automatically +// } // -// cleanup.Clear() // everything succeeded so we don't want thing1 to be disposed of +// cleanup.Clear() // everything succeeded so we don't want thing1 to be disposed of type CleanupTasks []func() // AddCloser adds a task for calling Close on an object