From d88729d922386e1aee5ce52bd7da6902f5ae9a62 Mon Sep 17 00:00:00 2001 From: Kim Ngo Date: Thu, 5 Mar 2020 10:37:06 -0600 Subject: [PATCH] registry: configurable client timeout (#24259) * registry: configurable client timeout * Update registry/client_test.go Fix env test cleanup Co-Authored-By: Alisdair McDiarmid --- registry/client.go | 31 ++++++++++++++-- registry/client_test.go | 37 +++++++++++++++++++ .../commands/environment-variables.html.md | 8 ++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/registry/client.go b/registry/client.go index e9cfcab79..5da890c4c 100644 --- a/registry/client.go +++ b/registry/client.go @@ -26,7 +26,6 @@ import ( const ( xTerraformGet = "X-Terraform-Get" xTerraformVersion = "X-Terraform-Version" - requestTimeout = 10 * time.Second modulesServiceID = "modules.v1" providersServiceID = "providers.v1" @@ -35,14 +34,27 @@ const ( // discovery requests with the remote registry. registryDiscoveryRetryEnvName = "TF_REGISTRY_DISCOVERY_RETRY" defaultRetry = 1 + + // registryClientTimeoutEnvName is the name of the environment variable that + // can be configured to customize the timeout duration (seconds) for module + // and provider discovery with the remote registry. + registryClientTimeoutEnvName = "TF_REGISTRY_CLIENT_TIMEOUT" + + // defaultRequestTimeout is the default timeout duration for requests to the + // remote registry. + defaultRequestTimeout = 10 * time.Second ) -var discoveryRetry int +var ( + tfVersion = version.String() -var tfVersion = version.String() + discoveryRetry int + requestTimeout time.Duration +) func init() { configureDiscoveryRetry() + configureRequestTimeout() } // Client provides methods to query Terraform Registries. @@ -411,3 +423,16 @@ func maxRetryErrorHandler(resp *http.Response, err error, numTries int) (*http.R } return resp, fmt.Errorf("the request failed, please try again later: %d%s", resp.StatusCode, errMsg) } + +// configureRequestTimeout configures the registry client request timeout from +// environment variables +func configureRequestTimeout() { + requestTimeout = defaultRequestTimeout + + if v := os.Getenv(registryClientTimeoutEnvName); v != "" { + timeout, err := strconv.Atoi(v) + if err == nil && timeout > 0 { + requestTimeout = time.Duration(timeout) * time.Second + } + } +} diff --git a/registry/client_test.go b/registry/client_test.go index 27cf7d49d..cf48fdb9e 100644 --- a/registry/client_test.go +++ b/registry/client_test.go @@ -7,6 +7,7 @@ import ( "os" "strings" "testing" + "time" version "github.com/hashicorp/go-version" "github.com/hashicorp/terraform-svchost/disco" @@ -51,6 +52,42 @@ func TestConfigureDiscoveryRetry(t *testing.T) { }) } +func TestConfigureRegistryClientTimeout(t *testing.T) { + t.Run("default timeout", func(t *testing.T) { + if requestTimeout != defaultRequestTimeout { + t.Fatalf("expected timeout %q, got %q", + defaultRequestTimeout.String(), requestTimeout.String()) + } + + rc := NewClient(nil, nil) + if rc.client.HTTPClient.Timeout != defaultRequestTimeout { + t.Fatalf("expected client timeout %q, got %q", + defaultRequestTimeout.String(), rc.client.HTTPClient.Timeout.String()) + } + }) + + t.Run("configured timeout", func(t *testing.T) { + defer func(timeoutEnv string) { + os.Setenv(registryClientTimeoutEnvName, timeoutEnv) + requestTimeout = defaultRequestTimeout + }(os.Getenv(registryClientTimeoutEnvName)) + os.Setenv(registryClientTimeoutEnvName, "20") + + configureRequestTimeout() + expected := 20 * time.Second + if requestTimeout != expected { + t.Fatalf("expected timeout %q, got %q", + expected, requestTimeout.String()) + } + + rc := NewClient(nil, nil) + if rc.client.HTTPClient.Timeout != expected { + t.Fatalf("expected client timeout %q, got %q", + expected, rc.client.HTTPClient.Timeout.String()) + } + }) +} + func TestLookupModuleVersions(t *testing.T) { server := test.Registry() defer server.Close() diff --git a/website/docs/commands/environment-variables.html.md b/website/docs/commands/environment-variables.html.md index 0a79aa9d6..9a15198cd 100644 --- a/website/docs/commands/environment-variables.html.md +++ b/website/docs/commands/environment-variables.html.md @@ -120,6 +120,14 @@ Set `TF_REGISTRY_DISCOVERY_RETRY` to configure the max number of request retries the remote registry client will attempt for client connection errors or 500-range responses that are safe to retry. +## TF_REGISTRY_CLIENT_TIMEOUT + +The default client timeout for requests to the remote registry is 10s. `TF_REGISTRY_CLIENT_TIMEOUT` can be configured and increased during extraneous circumstances. + +```shell +export TF_REGISTRY_CLIENT_TIMEOUT=15 +``` + ## TF_CLI_CONFIG_FILE The location of the [Terraform CLI configuration file](/docs/commands/cli-config.html).