From 34d90d4be0e123f3ec34bbff2c4f0401542cdd02 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Tue, 30 Jul 2019 19:17:33 +0100 Subject: [PATCH] httpclient: Introduce composable UserAgent() This interface is meant to replace the following ones (in use by some providers): - httpclient.UserAgentString() (e.g. AzureRM, Google) - terraform.UserAgentString (e.g. OpenStack, ProfitBricks) - terraform.VersionString (e.g. AWS, AzureStack, DigitalOcean, Kubernetes) This also proposes the initial UA string to be set to HashiCorp Terraform/X.Y.Z (+https://www.terraform.io) --- httpclient/useragent.go | 15 +++++++++++++++ httpclient/useragent_test.go | 33 ++++++++++++++++++++++++++++++++- terraform/user_agent.go | 3 +-- terraform/version.go | 2 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/httpclient/useragent.go b/httpclient/useragent.go index 5e2801768..c1ccf2096 100644 --- a/httpclient/useragent.go +++ b/httpclient/useragent.go @@ -13,6 +13,7 @@ import ( const userAgentFormat = "Terraform/%s" const uaEnvVar = "TF_APPEND_USER_AGENT" +// Deprecated: Use UserAgent(version) instead func UserAgentString() string { ua := fmt.Sprintf(userAgentFormat, version.Version) @@ -38,3 +39,17 @@ func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, e } return rt.inner.RoundTrip(req) } + +func TerraformUserAgent(version string) string { + ua := fmt.Sprintf("HashiCorp Terraform/%s (+https://www.terraform.io)", version) + + if add := os.Getenv(uaEnvVar); add != "" { + add = strings.TrimSpace(add) + if len(add) > 0 { + ua += " " + add + log.Printf("[DEBUG] Using modified User-Agent: %s", ua) + } + } + + return ua +} diff --git a/httpclient/useragent_test.go b/httpclient/useragent_test.go index 9c577da72..f5aa47c5f 100644 --- a/httpclient/useragent_test.go +++ b/httpclient/useragent_test.go @@ -43,5 +43,36 @@ func TestUserAgentString_env(t *testing.T) { } }) } - +} + +func TestUserAgentAppendViaEnvVar(t *testing.T) { + if oldenv, isSet := os.LookupEnv(uaEnvVar); isSet { + defer os.Setenv(uaEnvVar, oldenv) + } else { + defer os.Unsetenv(uaEnvVar) + } + + expectedBase := "HashiCorp Terraform/0.0.0 (+https://www.terraform.io)" + + testCases := []struct { + envVarValue string + expected string + }{ + {"", expectedBase}, + {" ", expectedBase}, + {" \n", expectedBase}, + {"test/1", expectedBase + " test/1"}, + {"test/1 (comment)", expectedBase + " test/1 (comment)"}, + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + os.Unsetenv(uaEnvVar) + os.Setenv(uaEnvVar, tc.envVarValue) + givenUA := TerraformUserAgent("0.0.0") + if givenUA != tc.expected { + t.Fatalf("Expected User-Agent '%s' does not match '%s'", tc.expected, givenUA) + } + }) + } } diff --git a/terraform/user_agent.go b/terraform/user_agent.go index a42613e85..97f1ec1f6 100644 --- a/terraform/user_agent.go +++ b/terraform/user_agent.go @@ -6,8 +6,7 @@ import ( // Generate a UserAgent string // -// Deprecated: Use httpclient.UserAgentString if you are setting your -// own User-Agent header. +// Deprecated: Use httpclient.UserAgent(version) instead func UserAgentString() string { return httpclient.UserAgentString() } diff --git a/terraform/version.go b/terraform/version.go index ac730154f..0caeca0ad 100644 --- a/terraform/version.go +++ b/terraform/version.go @@ -4,7 +4,7 @@ import ( "github.com/hashicorp/terraform/version" ) -// TODO: update providers to use the version package directly +// Deprecated: Providers should use schema.Provider.TerraformVersion instead func VersionString() string { return version.String() }