diff --git a/internal/cloud/backend.go b/internal/cloud/backend.go index cff9d7e2b..188996177 100644 --- a/internal/cloud/backend.go +++ b/internal/cloud/backend.go @@ -636,7 +636,7 @@ func (b *Cloud) Operation(ctx context.Context, op *backend.Operation) (*backend. b.IgnoreVersionConflict() // Check if we need to use the local backend to run the operation. - if b.forceLocal || !w.Operations { + if b.forceLocal || isLocalExecutionMode(w.ExecutionMode) { // Record that we're forced to run operations locally to allow the // command package UI to operate correctly b.forceLocal = true @@ -825,9 +825,9 @@ func (b *Cloud) VerifyWorkspaceTerraformVersion(workspaceName string) tfdiags.Di return nil } - // If the workspace has remote operations disabled, the remote Terraform + // If the workspace has execution-mode set to local, the remote Terraform // version is effectively meaningless, so we'll skip version verification. - if !workspace.Operations { + if isLocalExecutionMode(workspace.ExecutionMode) { return nil } @@ -965,6 +965,10 @@ func (wm WorkspaceMapping) Strategy() workspaceStrategy { } } +func isLocalExecutionMode(execMode string) bool { + return execMode == "local" +} + func (wm WorkspaceMapping) tfeTags() []*tfe.Tag { var tags []*tfe.Tag diff --git a/internal/cloud/backend_apply_test.go b/internal/cloud/backend_apply_test.go index d741662cd..6c4ea4106 100644 --- a/internal/cloud/backend_apply_test.go +++ b/internal/cloud/backend_apply_test.go @@ -1447,36 +1447,36 @@ func TestCloud_applyVersionCheck(t *testing.T) { localVersion string remoteVersion string forceLocal bool - hasOperations bool + executionMode string wantErr string }{ "versions can be different for remote apply": { localVersion: "0.14.0", remoteVersion: "0.13.5", - hasOperations: true, + executionMode: "remote", }, "versions can be different for local apply": { localVersion: "0.14.0", remoteVersion: "0.13.5", - hasOperations: false, + executionMode: "local", }, "force local with remote operations and different versions is acceptable": { localVersion: "0.14.0", remoteVersion: "0.14.0-acme-provider-bundle", forceLocal: true, - hasOperations: true, + executionMode: "remote", }, "no error if versions are identical": { localVersion: "0.14.0", remoteVersion: "0.14.0", forceLocal: true, - hasOperations: true, + executionMode: "remote", }, "no error if force local but workspace has remote operations disabled": { localVersion: "0.14.0", remoteVersion: "0.13.5", forceLocal: true, - hasOperations: false, + executionMode: "local", }, } @@ -1512,7 +1512,7 @@ func TestCloud_applyVersionCheck(t *testing.T) { b.organization, b.WorkspaceMapping.Name, tfe.WorkspaceUpdateOptions{ - Operations: tfe.Bool(tc.hasOperations), + ExecutionMode: tfe.String(tc.executionMode), TerraformVersion: tfe.String(tc.remoteVersion), }, ) @@ -1566,7 +1566,7 @@ func TestCloud_applyVersionCheck(t *testing.T) { hasRemote := strings.Contains(output, "Running apply in Terraform Cloud") hasSummary := strings.Contains(output, "1 added, 0 changed, 0 destroyed") hasResources := run.State.HasManagedResourceInstanceObjects() - if !tc.forceLocal && tc.hasOperations { + if !tc.forceLocal && !isLocalExecutionMode(tc.executionMode) { if !hasRemote { t.Errorf("missing TFC header in output: %s", output) } diff --git a/internal/cloud/backend_test.go b/internal/cloud/backend_test.go index 3bb9e148d..68e3c4167 100644 --- a/internal/cloud/backend_test.go +++ b/internal/cloud/backend_test.go @@ -680,31 +680,31 @@ func TestCloud_StateMgr_versionCheckLatest(t *testing.T) { func TestCloud_VerifyWorkspaceTerraformVersion(t *testing.T) { testCases := []struct { - local string - remote string - operations bool - wantErr bool + local string + remote string + executionMode string + wantErr bool }{ - {"0.13.5", "0.13.5", true, false}, - {"0.14.0", "0.13.5", true, true}, - {"0.14.0", "0.13.5", false, false}, - {"0.14.0", "0.14.1", true, false}, - {"0.14.0", "1.0.99", true, false}, - {"0.14.0", "1.1.0", true, false}, - {"0.14.0", "1.2.0", true, true}, - {"1.2.0", "1.2.99", true, false}, - {"1.2.0", "1.3.0", true, true}, - {"0.15.0", "latest", true, false}, - {"1.1.5", "~> 1.1.1", true, false}, - {"1.1.5", "> 1.1.0, < 1.3.0", true, false}, - {"1.1.5", "~> 1.0.1", true, true}, + {"0.13.5", "0.13.5", "agent", false}, + {"0.14.0", "0.13.5", "remote", true}, + {"0.14.0", "0.13.5", "local", false}, + {"0.14.0", "0.14.1", "remote", false}, + {"0.14.0", "1.0.99", "remote", false}, + {"0.14.0", "1.1.0", "remote", false}, + {"0.14.0", "1.2.0", "remote", true}, + {"1.2.0", "1.2.99", "remote", false}, + {"1.2.0", "1.3.0", "remote", true}, + {"0.15.0", "latest", "remote", false}, + {"1.1.5", "~> 1.1.1", "remote", false}, + {"1.1.5", "> 1.1.0, < 1.3.0", "remote", false}, + {"1.1.5", "~> 1.0.1", "remote", true}, // pre-release versions are comparable within their pre-release stage (dev, // alpha, beta), but not comparable to different stages and not comparable // to final releases. - {"1.1.0-beta1", "1.1.0-beta1", true, false}, - {"1.1.0-beta1", "~> 1.1.0-beta", true, false}, - {"1.1.0", "~> 1.1.0-beta", true, true}, - {"1.1.0-beta1", "~> 1.1.0-dev", true, true}, + {"1.1.0-beta1", "1.1.0-beta1", "remote", false}, + {"1.1.0-beta1", "~> 1.1.0-beta", "remote", false}, + {"1.1.0", "~> 1.1.0-beta", "remote", true}, + {"1.1.0-beta1", "~> 1.1.0-dev", "remote", true}, } for _, tc := range testCases { t.Run(fmt.Sprintf("local %s, remote %s", tc.local, tc.remote), func(t *testing.T) { @@ -735,7 +735,7 @@ func TestCloud_VerifyWorkspaceTerraformVersion(t *testing.T) { b.organization, b.WorkspaceMapping.Name, tfe.WorkspaceUpdateOptions{ - Operations: tfe.Bool(tc.operations), + ExecutionMode: &tc.executionMode, TerraformVersion: tfe.String(tc.remote), }, ); err != nil { diff --git a/internal/cloud/tfe_client_mock.go b/internal/cloud/tfe_client_mock.go index 929e39b89..2725d8178 100644 --- a/internal/cloud/tfe_client_mock.go +++ b/internal/cloud/tfe_client_mock.go @@ -1165,13 +1165,16 @@ func (m *MockWorkspaces) Create(ctx context.Context, organization string, option } if strings.HasSuffix(*options.Name, "no-operations") { options.Operations = tfe.Bool(false) + options.ExecutionMode = tfe.String("local") } else if options.Operations == nil { options.Operations = tfe.Bool(true) + options.ExecutionMode = tfe.String("remote") } w := &tfe.Workspace{ - ID: GenerateID("ws-"), - Name: *options.Name, - Operations: *options.Operations, + ID: GenerateID("ws-"), + Name: *options.Name, + ExecutionMode: *options.ExecutionMode, + Operations: *options.Operations, Permissions: &tfe.WorkspacePermissions{ CanQueueApply: true, CanQueueRun: true, @@ -1276,6 +1279,9 @@ func updateMockWorkspaceAttributes(w *tfe.Workspace, options tfe.WorkspaceUpdate if options.Operations != nil { w.Operations = *options.Operations } + if options.ExecutionMode != nil { + w.ExecutionMode = *options.ExecutionMode + } if options.Name != nil { w.Name = *options.Name }