Skip to content

Commit

Permalink
Merge pull request #36453 from hashicorp/IPL-7602/saved-plan-apply-ha…
Browse files Browse the repository at this point in the history
…ngs-with-auto-approve-flag (#36532)

Fix: Saved plan apply hangs with `-auto-approve` flag using cloud backend

Co-authored-by: Mark DeCrane <mark.decrane@hashicorp.com>
  • Loading branch information
dbanck and Maed223 authored Feb 19, 2025
1 parent 1f2b2f7 commit 1996c85
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changes/v1.11/BUG FIXES-20250206-155025.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: BUG FIXES
body: Fixes hanging behavior seen when applying a saved plan with -auto-approve using the cloud backend
time: 2025-02-06T15:50:25.767607-05:00
custom:
Issue: "36453"
8 changes: 5 additions & 3 deletions internal/cloud/backend_apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Opera

var r *tfe.Run
var err error

if cp, ok := op.PlanFile.Cloud(); ok {
cp, hasSavedPlanFile := op.PlanFile.Cloud()
if hasSavedPlanFile {
log.Printf("[TRACE] Loading saved cloud plan for apply")
// Check hostname first, for a more actionable error than a generic 404 later
if cp.Hostname != b.Hostname {
Expand Down Expand Up @@ -182,7 +182,9 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Opera
}

// Do the apply!
if !op.AutoApprove && err != errRunApproved {
// If we have a saved plan file, we proceed to apply the run without confirmation
// regardless of the value of AutoApprove.
if (!op.AutoApprove || hasSavedPlanFile) && err != errRunApproved {
if err = b.client.Runs.Apply(stopCtx, r.ID, tfe.RunApplyOptions{}); err != nil {
return r, b.generalError("Failed to approve the apply command", err)
}
Expand Down
67 changes: 67 additions & 0 deletions internal/cloud/backend_apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,73 @@ func TestCloud_applyWithCloudPlan(t *testing.T) {
}
}

func TestCloud_applyAutoApprove_with_CloudPlan(t *testing.T) {
b, bCleanup := testBackendWithName(t)
defer bCleanup()

op, configCleanup, done := testOperationApply(t, "./testdata/apply-json")
defer configCleanup()
defer done(t)

op.AutoApprove = true
op.UIOut = b.CLI
op.Workspace = testBackendSingleWorkspaceName

mockSROWorkspace(t, b, op.Workspace)

ws, err := b.client.Workspaces.Read(context.Background(), b.Organization, b.WorkspaceMapping.Name)
if err != nil {
t.Fatalf("Couldn't read workspace: %s", err)
}

planRun, err := b.plan(context.Background(), context.Background(), op, ws)
if err != nil {
t.Fatalf("Couldn't perform plan: %s", err)
}

// Synthesize a cloud plan file with the plan's run ID
pf := &cloudplan.SavedPlanBookmark{
RemotePlanFormat: 1,
RunID: planRun.ID,
Hostname: b.Hostname,
}
op.PlanFile = planfile.NewWrappedCloud(pf)

// Start spying on the apply output (now that the plan's done)
stream, close := terminal.StreamsForTesting(t)

b.renderer = &jsonformat.Renderer{
Streams: stream,
Colorize: mockColorize(),
}

// Try apply
run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("error starting operation: %v", err)
}

<-run.Done()
output := close(t)
if run.Result != backendrun.OperationSuccess {
t.Fatal("expected apply operation to succeed")
}
if run.PlanEmpty {
t.Fatalf("expected plan to not be empty")
}

gotOut := output.Stdout()
if !strings.Contains(gotOut, "1 added, 0 changed, 0 destroyed") {
t.Fatalf("expected apply summary in output: %s", gotOut)
}

stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
}
}

func TestCloud_applyWithoutRefresh(t *testing.T) {
b, bCleanup := testBackendWithName(t)
defer bCleanup()
Expand Down

0 comments on commit 1996c85

Please # to comment.