diff --git a/backend/remote/backend.go b/backend/remote/backend.go index 9d432e4bc..8823384e0 100644 --- a/backend/remote/backend.go +++ b/backend/remote/backend.go @@ -224,7 +224,7 @@ func (b *Remote) Configure(obj cty.Value) tfdiags.Diagnostics { } // Check any retrieved constraints to make sure we are compatible. - if constraints == nil { + if constraints != nil { diags = diags.Append(b.checkConstraints(constraints)) } diff --git a/backend/remote/backend_test.go b/backend/remote/backend_test.go index 8be7a4059..c250b3745 100644 --- a/backend/remote/backend_test.go +++ b/backend/remote/backend_test.go @@ -128,6 +128,84 @@ func TestRemote_config(t *testing.T) { } } +func TestRemote_versionConstraints(t *testing.T) { + cases := map[string]struct { + config cty.Value + prerelease string + version string + result string + }{ + "compatible version": { + 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.StringVal("prod"), + "prefix": cty.NullVal(cty.String), + }), + }), + version: "0.11.1", + }, + "version too old": { + 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.StringVal("prod"), + "prefix": cty.NullVal(cty.String), + }), + }), + version: "0.10.1", + result: "upgrade Terraform to >= 0.11.8", + }, + "version too new": { + 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.StringVal("prod"), + "prefix": cty.NullVal(cty.String), + }), + }), + version: "0.12.0", + result: "downgrade Terraform to <= 0.11.11", + }, + } + + // Save and restore the actual version. + p := version.Prerelease + v := version.Version + defer func() { + version.Prerelease = p + version.Version = v + }() + + for name, tc := range cases { + s := testServer(t) + b := New(testDisco(s)) + + // Set the version for this test. + version.Prerelease = tc.prerelease + version.Version = tc.version + + // Validate + valDiags := b.ValidateConfig(tc.config) + if valDiags.HasErrors() { + t.Fatalf("%s: unexpected validation result: %v", name, valDiags.Err()) + } + + // Configure + confDiags := b.Configure(tc.config) + if (confDiags.Err() != nil || tc.result != "") && + (confDiags.Err() == nil || !strings.Contains(confDiags.Err().Error(), tc.result)) { + t.Fatalf("%s: unexpected configure result: %v", name, confDiags.Err()) + } + } +} + func TestRemote_localBackend(t *testing.T) { b := testBackendDefault(t) @@ -323,7 +401,16 @@ func TestRemote_checkConstraints(t *testing.T) { }, } + // Save and restore the actual version. + p := version.Prerelease + v := version.Version + defer func() { + version.Prerelease = p + version.Version = v + }() + for name, tc := range cases { + // Set the version for this test. version.Prerelease = tc.prerelease version.Version = tc.version diff --git a/backend/remote/testing.go b/backend/remote/testing.go index 385d2eaf2..c42d6efcb 100644 --- a/backend/remote/testing.go +++ b/backend/remote/testing.go @@ -181,7 +181,21 @@ func testServer(t *testing.T) *httptest.Server { // Respond to service discovery calls. mux.HandleFunc("/well-known/terraform.json", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - io.WriteString(w, `{"tfe.v2.1":"/api/v2/"}`) + io.WriteString(w, `{ + "tfe.v2.1": "/api/v2/", + "versions.v1": "/v1/versions/" +}`) + }) + + // Respond to service version constraints calls. + mux.HandleFunc("/v1/versions/", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + io.WriteString(w, `{ + "service": "tfe.v2.1", + "product": "terraform", + "minimum": "0.11.8", + "maximum": "0.11.11" +}`) }) // Respond to the initial query to read the hashicorp org entitlements. @@ -243,7 +257,8 @@ func testServer(t *testing.T) *httptest.Server { // localhost to a local test server. func testDisco(s *httptest.Server) *disco.Disco { services := map[string]interface{}{ - "tfe.v2.1": fmt.Sprintf("%s/api/v2/", s.URL), + "tfe.v2.1": fmt.Sprintf("%s/api/v2/", s.URL), + "versions.v1": fmt.Sprintf("%s/v1/versions/", s.URL), } d := disco.NewWithCredentialsSource(credsSrc)