From d0a88b806b4105facc47bbc964d0da09b5fbf91e Mon Sep 17 00:00:00 2001 From: Gabriel Paradiso Date: Fri, 15 Mar 2024 16:16:26 +0100 Subject: [PATCH] [FUN-1313] implement retry strategy for external adapter (#12391) * feat: implement retry strategy with exponential backoff for external adapter * fix: integration-tests go.mod * fix: core/scripts go.mod * fix: integration-tests/load go.mod * chore: set retryMax and exponentialBackoffBase as jobspec config parameters * chore: rename maxRetry to maxRetries * chore: adjust exponential backoff base and improve logs * chore: remove redundant log --- core/scripts/go.mod | 2 + core/scripts/go.sum | 3 + .../functions/external_adapter_client.go | 43 ++++--- .../functions/external_adapter_client_test.go | 106 +++++++++++++++--- .../ocr2/plugins/functions/config/config.go | 58 +++++----- .../services/ocr2/plugins/functions/plugin.go | 21 +++- go.mod | 2 + go.sum | 3 + integration-tests/go.mod | 1 + integration-tests/go.sum | 5 +- integration-tests/load/go.mod | 1 + integration-tests/load/go.sum | 5 +- 12 files changed, 189 insertions(+), 61 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index e9f31ae2ed8..8b8a757a76c 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -170,10 +170,12 @@ require ( github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/consul/sdk v0.14.1 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index d59e0db8d58..38d053c98fc 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -701,6 +701,7 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -709,6 +710,8 @@ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= diff --git a/core/services/functions/external_adapter_client.go b/core/services/functions/external_adapter_client.go index fb64924a922..9dc77ca78e9 100644 --- a/core/services/functions/external_adapter_client.go +++ b/core/services/functions/external_adapter_client.go @@ -10,6 +10,7 @@ import ( "net/url" "time" + "github.com/hashicorp/go-retryablehttp" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -42,8 +43,10 @@ type ExternalAdapterClient interface { } type externalAdapterClient struct { - adapterURL url.URL - maxResponseBytes int64 + adapterURL url.URL + maxResponseBytes int64 + maxRetries int + exponentialBackoffBase time.Duration } var _ ExternalAdapterClient = (*externalAdapterClient)(nil) @@ -54,9 +57,11 @@ type BridgeAccessor interface { } type bridgeAccessor struct { - bridgeORM bridges.ORM - bridgeName string - maxResponseBytes int64 + bridgeORM bridges.ORM + bridgeName string + maxResponseBytes int64 + maxRetries int + exponentialBackoffBase time.Duration } var _ BridgeAccessor = (*bridgeAccessor)(nil) @@ -112,10 +117,12 @@ var ( ) ) -func NewExternalAdapterClient(adapterURL url.URL, maxResponseBytes int64) ExternalAdapterClient { +func NewExternalAdapterClient(adapterURL url.URL, maxResponseBytes int64, maxRetries int, exponentialBackoffBase time.Duration) ExternalAdapterClient { return &externalAdapterClient{ - adapterURL: adapterURL, - maxResponseBytes: maxResponseBytes, + adapterURL: adapterURL, + maxResponseBytes: maxResponseBytes, + maxRetries: maxRetries, + exponentialBackoffBase: exponentialBackoffBase, } } @@ -190,7 +197,13 @@ func (ea *externalAdapterClient) request( req.Header.Set("Content-Type", "application/json") start := time.Now() - client := &http.Client{} + + // retry will only happen on a 5XX error response code (except 501) + retryClient := retryablehttp.NewClient() + retryClient.RetryMax = ea.maxRetries + retryClient.RetryWaitMin = ea.exponentialBackoffBase + + client := retryClient.StandardClient() resp, err := client.Do(req) if err != nil { promEAClientErrors.WithLabelValues(label).Inc() @@ -244,11 +257,13 @@ func (ea *externalAdapterClient) request( } } -func NewBridgeAccessor(bridgeORM bridges.ORM, bridgeName string, maxResponseBytes int64) BridgeAccessor { +func NewBridgeAccessor(bridgeORM bridges.ORM, bridgeName string, maxResponseBytes int64, maxRetries int, exponentialBackoffBase time.Duration) BridgeAccessor { return &bridgeAccessor{ - bridgeORM: bridgeORM, - bridgeName: bridgeName, - maxResponseBytes: maxResponseBytes, + bridgeORM: bridgeORM, + bridgeName: bridgeName, + maxResponseBytes: maxResponseBytes, + maxRetries: maxRetries, + exponentialBackoffBase: exponentialBackoffBase, } } @@ -257,5 +272,5 @@ func (b *bridgeAccessor) NewExternalAdapterClient() (ExternalAdapterClient, erro if err != nil { return nil, err } - return NewExternalAdapterClient(url.URL(bridge.URL), b.maxResponseBytes), nil + return NewExternalAdapterClient(url.URL(bridge.URL), b.maxResponseBytes, b.maxRetries, b.exponentialBackoffBase), nil } diff --git a/core/services/functions/external_adapter_client_test.go b/core/services/functions/external_adapter_client_test.go index 9fd40ba8280..4ce78ee3fc3 100644 --- a/core/services/functions/external_adapter_client_test.go +++ b/core/services/functions/external_adapter_client_test.go @@ -27,7 +27,7 @@ func runFetcherTest(t *testing.T, adapterJSONResponse, expectedSecrets, expected adapterUrl, err := url.Parse(ts.URL) assert.NoError(t, err, "Unexpected error") - ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000) + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 0, 0) encryptedSecrets, userError, err := ea.FetchEncryptedSecrets(testutils.Context(t), []byte("urls to secrets"), "requestID1234", "TestJob") if expectedError != nil { @@ -50,7 +50,7 @@ func runRequestTest(t *testing.T, adapterJSONResponse, expectedUserResult, expec adapterUrl, err := url.Parse(ts.URL) assert.NoError(t, err, "Unexpected error") - ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000) + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 0, 0) userResult, userError, domains, err := ea.RunComputation(testutils.Context(t), "requestID1234", "TestJob", "SubOwner", 1, functions.RequestFlags{}, "", &functions.RequestData{}) if expectedError != nil { @@ -144,15 +144,7 @@ func TestFetchEncryptedSecrets_UnexpectedResult(t *testing.T) { } func TestRunComputation_Success(t *testing.T) { - runRequestTest(t, `{ - "result": "success", - "data": { - "result": "0x616263646566", - "error": "", - "domains": ["domain1", "domain2"] - }, - "statusCode": 200 - }`, "abcdef", "", []string{"domain1", "domain2"}, nil) + runRequestTest(t, runComputationSuccessResponse, "abcdef", "", []string{"domain1", "domain2"}, nil) } func TestRunComputation_MissingData(t *testing.T) { @@ -177,7 +169,7 @@ func TestRunComputation_CorrectAdapterRequest(t *testing.T) { adapterUrl, err := url.Parse(ts.URL) assert.NoError(t, err) - ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000) + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 0, 0) reqData := &functions.RequestData{ Source: "abcd", Language: 7, @@ -199,7 +191,7 @@ func TestRunComputation_HTTP500(t *testing.T) { adapterUrl, err := url.Parse(ts.URL) assert.NoError(t, err) - ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000) + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 0, 0) _, _, _, err = ea.RunComputation(testutils.Context(t), "requestID1234", "TestJob", "SubOwner", 1, functions.RequestFlags{}, "secRETS", &functions.RequestData{}) assert.Error(t, err) } @@ -214,10 +206,96 @@ func TestRunComputation_ContextRespected(t *testing.T) { adapterUrl, err := url.Parse(ts.URL) assert.NoError(t, err) - ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000) + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 0, 0) ctx, cancel := context.WithTimeout(testutils.Context(t), 10*time.Millisecond) defer cancel() _, _, _, err = ea.RunComputation(ctx, "requestID1234", "TestJob", "SubOwner", 1, functions.RequestFlags{}, "secRETS", &functions.RequestData{}) assert.Error(t, err) close(done) } + +func TestRunComputationRetrial(t *testing.T) { + + t.Run("OK-retry_succeeds_after_one_failure", func(t *testing.T) { + counter := 0 + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch counter { + case 0: + counter++ + w.WriteHeader(http.StatusInternalServerError) + return + case 1: + counter++ + fmt.Fprintln(w, runComputationSuccessResponse) + return + default: + t.Errorf("invalid amount of retries: %d", counter) + t.FailNow() + } + })) + defer ts.Close() + + adapterUrl, err := url.Parse(ts.URL) + assert.NoError(t, err) + + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 1, 1*time.Nanosecond) + _, _, _, err = ea.RunComputation(testutils.Context(t), "requestID1234", "TestJob", "SubOwner", 1, functions.RequestFlags{}, "secRETS", &functions.RequestData{}) + assert.NoError(t, err) + }) + + t.Run("NOK-retry_fails_after_retrial", func(t *testing.T) { + counter := 0 + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch counter { + case 0, 1: + counter++ + w.WriteHeader(http.StatusInternalServerError) + return + default: + t.Errorf("invalid amount of retries: %d", counter) + t.FailNow() + } + })) + defer ts.Close() + + adapterUrl, err := url.Parse(ts.URL) + assert.NoError(t, err) + + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 1, 1*time.Nanosecond) + _, _, _, err = ea.RunComputation(testutils.Context(t), "requestID1234", "TestJob", "SubOwner", 1, functions.RequestFlags{}, "secRETS", &functions.RequestData{}) + assert.Error(t, err) + }) + + t.Run("NOK-dont_retry_on_4XX_errors", func(t *testing.T) { + counter := 0 + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch counter { + case 0: + counter++ + w.WriteHeader(http.StatusBadRequest) + return + default: + t.Errorf("invalid amount of retries: %d", counter) + t.FailNow() + } + })) + defer ts.Close() + + adapterUrl, err := url.Parse(ts.URL) + assert.NoError(t, err) + + ea := functions.NewExternalAdapterClient(*adapterUrl, 100_000, 1, 1*time.Nanosecond) + _, _, _, err = ea.RunComputation(testutils.Context(t), "requestID1234", "TestJob", "SubOwner", 1, functions.RequestFlags{}, "secRETS", &functions.RequestData{}) + assert.Error(t, err) + }) +} + +const runComputationSuccessResponse = `{ + "result": "success", + "data": { + "result": "0x616263646566", + "error": "", + "domains": ["domain1", "domain2"] + }, + "statusCode": 200 + }` diff --git a/core/services/ocr2/plugins/functions/config/config.go b/core/services/ocr2/plugins/functions/config/config.go index e0e1ba3bfa0..2e18d6727f6 100644 --- a/core/services/ocr2/plugins/functions/config/config.go +++ b/core/services/ocr2/plugins/functions/config/config.go @@ -21,34 +21,36 @@ import ( // This config is part of the job spec and is loaded only once on node boot/job creation. type PluginConfig struct { - EnableRequestSignatureCheck bool `json:"enableRequestSignatureCheck"` - DONID string `json:"donID"` - ContractVersion uint32 `json:"contractVersion"` - MinRequestConfirmations uint32 `json:"minRequestConfirmations"` - MinResponseConfirmations uint32 `json:"minResponseConfirmations"` - MinIncomingConfirmations uint32 `json:"minIncomingConfirmations"` - PastBlocksToPoll uint32 `json:"pastBlocksToPoll"` - LogPollerCacheDurationSec uint32 `json:"logPollerCacheDurationSec"` // Duration to cache previously detected request or response logs such that they can be filtered when calling logpoller_wrapper.LatestEvents() - RequestTimeoutSec uint32 `json:"requestTimeoutSec"` - RequestTimeoutCheckFrequencySec uint32 `json:"requestTimeoutCheckFrequencySec"` - RequestTimeoutBatchLookupSize uint32 `json:"requestTimeoutBatchLookupSize"` - PruneMaxStoredRequests uint32 `json:"pruneMaxStoredRequests"` - PruneCheckFrequencySec uint32 `json:"pruneCheckFrequencySec"` - PruneBatchSize uint32 `json:"pruneBatchSize"` - ListenerEventHandlerTimeoutSec uint32 `json:"listenerEventHandlerTimeoutSec"` - ListenerEventsCheckFrequencyMillis uint32 `json:"listenerEventsCheckFrequencyMillis"` - ContractUpdateCheckFrequencySec uint32 `json:"contractUpdateCheckFrequencySec"` - MaxRequestSizeBytes uint32 `json:"maxRequestSizeBytes"` - MaxRequestSizesList []uint32 `json:"maxRequestSizesList"` - MaxSecretsSizesList []uint32 `json:"maxSecretsSizesList"` - MinimumSubscriptionBalance assets.Link `json:"minimumSubscriptionBalance"` - AllowedHeartbeatInitiators []string `json:"allowedHeartbeatInitiators"` - GatewayConnectorConfig *connector.ConnectorConfig `json:"gatewayConnectorConfig"` - OnchainAllowlist *allowlist.OnchainAllowlistConfig `json:"onchainAllowlist"` - OnchainSubscriptions *subscriptions.OnchainSubscriptionsConfig `json:"onchainSubscriptions"` - RateLimiter *common.RateLimiterConfig `json:"rateLimiter"` - S4Constraints *s4.Constraints `json:"s4Constraints"` - DecryptionQueueConfig *DecryptionQueueConfig `json:"decryptionQueueConfig"` + EnableRequestSignatureCheck bool `json:"enableRequestSignatureCheck"` + DONID string `json:"donID"` + ContractVersion uint32 `json:"contractVersion"` + MinRequestConfirmations uint32 `json:"minRequestConfirmations"` + MinResponseConfirmations uint32 `json:"minResponseConfirmations"` + MinIncomingConfirmations uint32 `json:"minIncomingConfirmations"` + PastBlocksToPoll uint32 `json:"pastBlocksToPoll"` + LogPollerCacheDurationSec uint32 `json:"logPollerCacheDurationSec"` // Duration to cache previously detected request or response logs such that they can be filtered when calling logpoller_wrapper.LatestEvents() + RequestTimeoutSec uint32 `json:"requestTimeoutSec"` + RequestTimeoutCheckFrequencySec uint32 `json:"requestTimeoutCheckFrequencySec"` + RequestTimeoutBatchLookupSize uint32 `json:"requestTimeoutBatchLookupSize"` + PruneMaxStoredRequests uint32 `json:"pruneMaxStoredRequests"` + PruneCheckFrequencySec uint32 `json:"pruneCheckFrequencySec"` + PruneBatchSize uint32 `json:"pruneBatchSize"` + ListenerEventHandlerTimeoutSec uint32 `json:"listenerEventHandlerTimeoutSec"` + ListenerEventsCheckFrequencyMillis uint32 `json:"listenerEventsCheckFrequencyMillis"` + ContractUpdateCheckFrequencySec uint32 `json:"contractUpdateCheckFrequencySec"` + MaxRequestSizeBytes uint32 `json:"maxRequestSizeBytes"` + MaxRequestSizesList []uint32 `json:"maxRequestSizesList"` + MaxSecretsSizesList []uint32 `json:"maxSecretsSizesList"` + MinimumSubscriptionBalance assets.Link `json:"minimumSubscriptionBalance"` + AllowedHeartbeatInitiators []string `json:"allowedHeartbeatInitiators"` + GatewayConnectorConfig *connector.ConnectorConfig `json:"gatewayConnectorConfig"` + OnchainAllowlist *allowlist.OnchainAllowlistConfig `json:"onchainAllowlist"` + OnchainSubscriptions *subscriptions.OnchainSubscriptionsConfig `json:"onchainSubscriptions"` + RateLimiter *common.RateLimiterConfig `json:"rateLimiter"` + S4Constraints *s4.Constraints `json:"s4Constraints"` + DecryptionQueueConfig *DecryptionQueueConfig `json:"decryptionQueueConfig"` + ExternalAdapterMaxRetries *uint32 `json:"externalAdapterMaxRetries"` + ExternalAdapterExponentialBackoffBaseSec *uint32 `json:"externalAdapterExponentialBackoffBaseSec"` } type DecryptionQueueConfig struct { diff --git a/core/services/ocr2/plugins/functions/plugin.go b/core/services/ocr2/plugins/functions/plugin.go index 5a7a152d950..92b15892885 100644 --- a/core/services/ocr2/plugins/functions/plugin.go +++ b/core/services/ocr2/plugins/functions/plugin.go @@ -57,6 +57,8 @@ const ( FunctionsS4Namespace string = "functions" MaxAdapterResponseBytes int64 = 1_000_000 DefaultOffchainTransmitterChannelSize uint32 = 1000 + DefaultMaxAdapterRetry int = 3 + DefaultExponentialBackoffBase = 5 * time.Second ) // Create all OCR2 plugin Oracles and all extra services needed to run a Functions job. @@ -106,7 +108,24 @@ func NewFunctionsServices(ctx context.Context, functionsOracleArgs, thresholdOra offchainTransmitter := functions.NewOffchainTransmitter(DefaultOffchainTransmitterChannelSize) listenerLogger := conf.Logger.Named("FunctionsListener") - bridgeAccessor := functions.NewBridgeAccessor(conf.BridgeORM, FunctionsBridgeName, MaxAdapterResponseBytes) + + var maxRetries int + if pluginConfig.ExternalAdapterMaxRetries != nil { + maxRetries = int(*pluginConfig.ExternalAdapterMaxRetries) + } else { + maxRetries = DefaultMaxAdapterRetry + } + conf.Logger.Debugf("external adapter maxRetries configured to: %d", maxRetries) + + var exponentialBackoffBase time.Duration + if pluginConfig.ExternalAdapterExponentialBackoffBaseSec != nil { + exponentialBackoffBase = time.Duration(*pluginConfig.ExternalAdapterExponentialBackoffBaseSec) * time.Second + } else { + exponentialBackoffBase = DefaultExponentialBackoffBase + } + conf.Logger.Debugf("external adapter exponentialBackoffBase configured to: %g sec", exponentialBackoffBase.Seconds()) + + bridgeAccessor := functions.NewBridgeAccessor(conf.BridgeORM, FunctionsBridgeName, MaxAdapterResponseBytes, maxRetries, exponentialBackoffBase) functionsListener := functions.NewFunctionsListener( conf.Job, conf.Chain.Client(), diff --git a/go.mod b/go.mod index 979f6b03a4e..77d2b20c09e 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/hashicorp/consul/sdk v0.14.1 github.com/hashicorp/go-envparse v0.1.0 github.com/hashicorp/go-plugin v1.6.0 + github.com/hashicorp/go-retryablehttp v0.7.5 github.com/hdevalence/ed25519consensus v0.1.0 github.com/jackc/pgconn v1.14.1 github.com/jackc/pgtype v1.14.0 @@ -220,6 +221,7 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect diff --git a/go.sum b/go.sum index 5784268d323..b64249e2094 100644 --- a/go.sum +++ b/go.sum @@ -692,6 +692,7 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -700,6 +701,8 @@ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 2752cb58342..70b95162e79 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -257,6 +257,7 @@ require ( github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 4819179aad4..9275fabd5a8 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -913,6 +913,7 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -926,8 +927,8 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+ 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-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index f7d947909cc..3dca77447b0 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -239,6 +239,7 @@ require ( github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 23c01d55223..21845553680 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -904,6 +904,7 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -917,8 +918,8 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+ 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-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=