From 0eea4e7c6226307c2494fb90fff4a814ea0c355f Mon Sep 17 00:00:00 2001 From: CJ Horton <17039873+radditude@users.noreply.github.com> Date: Thu, 14 May 2020 20:01:55 -0700 Subject: [PATCH] prevent targeting for unsupported API versions --- backend/remote/backend_apply.go | 21 +++++++++++++++++++++ backend/remote/backend_plan.go | 21 +++++++++++++++++++++ backend/remote/testing.go | 6 ++++++ 3 files changed, 48 insertions(+) diff --git a/backend/remote/backend_apply.go b/backend/remote/backend_apply.go index 0dd78c6ced..5db412baa2 100644 --- a/backend/remote/backend_apply.go +++ b/backend/remote/backend_apply.go @@ -8,6 +8,7 @@ import ( "log" tfe "github.com/hashicorp/go-tfe" + version "github.com/hashicorp/go-version" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/tfdiags" @@ -94,6 +95,26 @@ func (b *Remote) opApply(stopCtx, cancelCtx context.Context, op *backend.Operati )) } + if len(op.Targets) != 0 { + // For API versions prior to 2.3, RemoteAPIVersion will return an empty string, + // so if there's an error when parsing the RemoteAPIVersion, it's handled as + // equivalent to an API version < 2.3. + currentAPIVersion, parseErr := version.NewVersion(b.client.RemoteAPIVersion()) + desiredAPIVersion, _ := version.NewVersion("2.3") + + if parseErr != nil || currentAPIVersion.LessThan(desiredAPIVersion) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Resource targeting is not supported", + fmt.Sprintf( + `The host %s does not support the -target option for `+ + `remote plans.`, + b.hostname, + ), + )) + } + } + // Return if there are any errors. if diags.HasErrors() { return nil, diags.Err() diff --git a/backend/remote/backend_plan.go b/backend/remote/backend_plan.go index 957b28aead..f9fcf82b63 100644 --- a/backend/remote/backend_plan.go +++ b/backend/remote/backend_plan.go @@ -15,6 +15,7 @@ import ( "time" tfe "github.com/hashicorp/go-tfe" + version "github.com/hashicorp/go-version" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/tfdiags" ) @@ -98,6 +99,26 @@ func (b *Remote) opPlan(stopCtx, cancelCtx context.Context, op *backend.Operatio )) } + if len(op.Targets) != 0 { + // For API versions prior to 2.3, RemoteAPIVersion will return an empty string, + // so if there's an error when parsing the RemoteAPIVersion, it's handled as + // equivalent to an API version < 2.3. + currentAPIVersion, parseErr := version.NewVersion(b.client.RemoteAPIVersion()) + desiredAPIVersion, _ := version.NewVersion("2.3") + + if parseErr != nil || currentAPIVersion.LessThan(desiredAPIVersion) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Resource targeting is not supported", + fmt.Sprintf( + `The host %s does not support the -target option for `+ + `remote plans.`, + b.hostname, + ), + )) + } + } + // Return if there are any errors. if diags.HasErrors() { return nil, diags.Err() diff --git a/backend/remote/testing.go b/backend/remote/testing.go index e506f28f9b..3afaf97aa7 100644 --- a/backend/remote/testing.go +++ b/backend/remote/testing.go @@ -207,6 +207,12 @@ func testServer(t *testing.T) *httptest.Server { }`, path.Base(r.URL.Path))) }) + // Respond to pings to get the API version header. + mux.HandleFunc("/api/v2/ping", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("TFP-API-Version", "2.3") + }) + // Respond to the initial query to read the hashicorp org entitlements. mux.HandleFunc("/api/v2/organizations/hashicorp/entitlement-set", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/vnd.api+json")