diff --git a/internal/cloud/backend_test.go b/internal/cloud/backend_test.go index d3b5d7c5f2..0b0bb316a2 100644 --- a/internal/cloud/backend_test.go +++ b/internal/cloud/backend_test.go @@ -305,6 +305,58 @@ func TestCloud_configVerifyMinimumTFEVersion(t *testing.T) { } } +func TestCloud_setUnavailableTerraformVersion(t *testing.T) { + // go-tfe returns an error IRL if you try to set a Terraform version that's + // not available in your TFC instance. To test this, tfe_client_mock errors if + // you try to set any Terraform version for this specific workspace name. + workspaceName := "unavailable-terraform-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.NullVal(cty.String), + "tags": cty.SetVal( + []cty.Value{ + cty.StringVal("sometag"), + }, + ), + }), + }) + + b, bCleanup := testBackend(t, config) + defer bCleanup() + + // Make sure the workspace doesn't exist yet -- otherwise, we can't test what + // happens when a workspace gets created. This is why we can't use "name" in + // the backend config above, btw: if you do, testBackend() creates the default + // workspace before we get a chance to do anything. + _, err := b.client.Workspaces.Read(context.Background(), b.organization, workspaceName) + if err != tfe.ErrResourceNotFound { + t.Fatalf("the workspace we were about to try and create (%s/%s) already exists in the mocks somehow, so this test isn't trustworthy anymore", b.organization, workspaceName) + } + + _, err = b.StateMgr(workspaceName) + if err != nil { + t.Fatalf("expected no error from StateMgr, despite not being able to set remote Terraform version: %#v", err) + } + // Make sure the workspace was created: + workspace, err := b.client.Workspaces.Read(context.Background(), b.organization, workspaceName) + if err != nil { + t.Fatalf("b.StateMgr() didn't actually create the desired workspace") + } + // Make sure our mocks still error as expected, using the same update function b.StateMgr() would call: + _, err = b.client.Workspaces.UpdateByID( + context.Background(), + workspace.ID, + tfe.WorkspaceUpdateOptions{TerraformVersion: tfe.String("1.1.0")}, + ) + if err == nil { + t.Fatalf("the mocks aren't emulating a nonexistent remote Terraform version correctly, so this test isn't trustworthy anymore") + } +} + func TestCloud_setConfigurationFields(t *testing.T) { originalForceBackendEnv := os.Getenv("TF_FORCE_LOCAL_BACKEND") diff --git a/internal/cloud/tfe_client_mock.go b/internal/cloud/tfe_client_mock.go index 518602c3c8..8ba6883c3a 100644 --- a/internal/cloud/tfe_client_mock.go +++ b/internal/cloud/tfe_client_mock.go @@ -1159,6 +1159,10 @@ func (m *MockWorkspaces) List(ctx context.Context, organization string, options } func (m *MockWorkspaces) Create(ctx context.Context, organization string, options tfe.WorkspaceCreateOptions) (*tfe.Workspace, error) { + // for TestCloud_setUnavailableTerraformVersion + if *options.Name == "unavailable-terraform-version" && options.TerraformVersion != nil { + return nil, fmt.Errorf("requested Terraform version not available in this TFC instance") + } if strings.HasSuffix(*options.Name, "no-operations") { options.Operations = tfe.Bool(false) } else if options.Operations == nil { @@ -1234,17 +1238,9 @@ func (m *MockWorkspaces) Update(ctx context.Context, organization, workspace str return nil, tfe.ErrResourceNotFound } - if options.Operations != nil { - w.Operations = *options.Operations - } - if options.Name != nil { - w.Name = *options.Name - } - if options.TerraformVersion != nil { - w.TerraformVersion = *options.TerraformVersion - } - if options.WorkingDirectory != nil { - w.WorkingDirectory = *options.WorkingDirectory + err := updateMockWorkspaceAttributes(w, options) + if err != nil { + return nil, err } delete(m.workspaceNames, workspace) @@ -1259,6 +1255,26 @@ func (m *MockWorkspaces) UpdateByID(ctx context.Context, workspaceID string, opt return nil, tfe.ErrResourceNotFound } + err := updateMockWorkspaceAttributes(w, options) + if err != nil { + return nil, err + } + + delete(m.workspaceNames, w.Name) + m.workspaceNames[w.Name] = w + + return w, nil +} + +func updateMockWorkspaceAttributes(w *tfe.Workspace, options tfe.WorkspaceUpdateOptions) error { + // for TestCloud_setUnavailableTerraformVersion + if w.Name == "unavailable-terraform-version" && options.TerraformVersion != nil { + return fmt.Errorf("requested Terraform version not available in this TFC instance") + } + + if options.Operations != nil { + w.Operations = *options.Operations + } if options.Name != nil { w.Name = *options.Name } @@ -1268,11 +1284,7 @@ func (m *MockWorkspaces) UpdateByID(ctx context.Context, workspaceID string, opt if options.WorkingDirectory != nil { w.WorkingDirectory = *options.WorkingDirectory } - - delete(m.workspaceNames, w.Name) - m.workspaceNames[w.Name] = w - - return w, nil + return nil } func (m *MockWorkspaces) Delete(ctx context.Context, organization, workspace string) error {