From 50997d9a32c40604b33bd56ca7abb2f62ffe1bb3 Mon Sep 17 00:00:00 2001 From: Chris Arcand Date: Fri, 22 Oct 2021 15:08:22 -0500 Subject: [PATCH] Restore API version checking, with internal usage accounted for --- internal/cloud/backend.go | 39 +++++++++++++++++++++++--------- internal/cloud/backend_cli.go | 1 + internal/cloud/backend_test.go | 41 ++++++++++++++++++++++++++++++++-- internal/cloud/versioning.go | 12 ---------- 4 files changed, 68 insertions(+), 25 deletions(-) delete mode 100644 internal/cloud/versioning.go diff --git a/internal/cloud/backend.go b/internal/cloud/backend.go index f043378f6..786309fed 100644 --- a/internal/cloud/backend.go +++ b/internal/cloud/backend.go @@ -85,6 +85,8 @@ type Cloud struct { // version. This will also cause VerifyWorkspaceTerraformVersion to return // a warning diagnostic instead of an error. ignoreVersionConflict bool + + runningInAutomation bool } var _ backend.Backend = (*Cloud)(nil) @@ -296,15 +298,25 @@ func (b *Cloud) Configure(obj cty.Value) tfdiags.Diagnostics { if parseErr != nil || currentAPIVersion.LessThan(desiredAPIVersion) { log.Printf("[TRACE] API version check failed; want: >= %s, got: %s", desiredAPIVersion.Original(), currentAPIVersion) - // FIXME: Skip version checking temporarily. - // diags = diags.Append(tfdiags.Sourceless( - // tfdiags.Error, - // "Unsupported Terraform Enterprise version", - // fmt.Sprintf( - // `The 'cloud' option requires Terraform Enterprise %s or later.`, - // apiToMinimumTFEVersion["2.5"], - // ), - // )) + if b.runningInAutomation { + // It should never be possible for this Terraform process to be mistakenly + // used internally within an unsupported Terraform Enterprise install - but + // just in case it happens, give an actionable error. + diags = diags.Append( + tfdiags.Sourceless( + tfdiags.Error, + "Unsupported Terraform Enterprise version", + cloudIntegrationUsedInUnsupportedTFE, + ), + ) + } else { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Unsupported Terraform Enterprise version", + `The 'cloud' option is not supported with this version of Terraform Enterprise.`, + ), + ) + } } // Configure a local backend for when we need to run operations locally. @@ -967,8 +979,13 @@ const refreshToApplyRefresh = `[bold][yellow]Proceeding with 'terraform apply -r const unavailableTerraformVersion = ` [reset][yellow]The local Terraform version (%s) is not available in Terraform Cloud, or your organization does not have access to it. The new workspace will use %s. You can -change this later in the workspace settings.[reset] -` +change this later in the workspace settings.[reset]` + +const cloudIntegrationUsedInUnsupportedTFE = ` +This version of Terraform Cloud/Enterprise does not support the state mechanism +attempting to be used by the platform. This should never happen. + +Please reach out to HashiCorp Support to resolve this issue.` var ( workspaceConfigurationHelp = fmt.Sprintf( diff --git a/internal/cloud/backend_cli.go b/internal/cloud/backend_cli.go index 8dac9bf3e..cd0549616 100644 --- a/internal/cloud/backend_cli.go +++ b/internal/cloud/backend_cli.go @@ -15,6 +15,7 @@ func (b *Cloud) CLIInit(opts *backend.CLIOpts) error { b.CLI = opts.CLI b.CLIColor = opts.CLIColor b.ContextOpts = opts.ContextOpts + b.runningInAutomation = opts.RunningInAutomation return nil } diff --git a/internal/cloud/backend_test.go b/internal/cloud/backend_test.go index 0b0bb316a..87f7a91f2 100644 --- a/internal/cloud/backend_test.go +++ b/internal/cloud/backend_test.go @@ -269,7 +269,6 @@ func TestCloud_config(t *testing.T) { } func TestCloud_configVerifyMinimumTFEVersion(t *testing.T) { - t.Skip("skipping, as TFE version checking has been temporarily disabled") config := cty.ObjectVal(map[string]cty.Value{ "hostname": cty.NullVal(cty.String), "organization": cty.StringVal("hashicorp"), @@ -299,7 +298,45 @@ func TestCloud_configVerifyMinimumTFEVersion(t *testing.T) { t.Fatalf("expected configure to error") } - expected := "The 'cloud' option requires Terraform Enterprise v202201-1 or later." + expected := `The 'cloud' option is not supported with this version of Terraform Enterprise.` + if !strings.Contains(confDiags.Err().Error(), expected) { + t.Fatalf("expected configure to error with %q, got %q", expected, confDiags.Err().Error()) + } +} + +func TestCloud_configVerifyMinimumTFEVersionInAutomation(t *testing.T) { + config := cty.ObjectVal(map[string]cty.Value{ + "hostname": cty.NullVal(cty.String), + "organization": cty.StringVal("hashicorp"), + "token": cty.NullVal(cty.String), + "workspaces": cty.ObjectVal(map[string]cty.Value{ + "name": cty.NullVal(cty.String), + "tags": cty.SetVal( + []cty.Value{ + cty.StringVal("billing"), + }, + ), + }), + }) + + handlers := map[string]func(http.ResponseWriter, *http.Request){ + "/api/v2/ping": func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("TFP-API-Version", "2.4") + }, + } + s := testServerWithHandlers(handlers) + + b := New(testDisco(s)) + b.runningInAutomation = true + + confDiags := b.Configure(config) + if confDiags.Err() == nil { + t.Fatalf("expected configure to error") + } + + expected := `This version of Terraform Cloud/Enterprise does not support the state mechanism +attempting to be used by the platform. This should never happen.` if !strings.Contains(confDiags.Err().Error(), expected) { t.Fatalf("expected configure to error with %q, got %q", expected, confDiags.Err().Error()) } diff --git a/internal/cloud/versioning.go b/internal/cloud/versioning.go deleted file mode 100644 index 4b9ee52e1..000000000 --- a/internal/cloud/versioning.go +++ /dev/null @@ -1,12 +0,0 @@ -package cloud - -// This simple map exists to translate TFP-API-Version strings to the TFE release where it was -// introduced, to provide actionable feedback on features that may be unsupported by the TFE -// installation but present in this version of Terraform. -// -// The cloud package here, introduced in Terraform 1.1.0, requires a minimum of 2.5 (v202201-1) -// The TFP-API-Version header that this refers to was introduced in 2.3 (v202006-1), so an absent -// header can be considered < 2.3. -// var apiToMinimumTFEVersion = map[string]string{ -// "2.5": "v202201-1", -// }