Skip to content

Commit 62a8b9e

Browse files
authored
Merge pull request #32207 from hashicorp/jbardin/destroy-plan-state
Ensure destroy plan contains valid state values
2 parents b5168eb + 3db3ed0 commit 62a8b9e

File tree

2 files changed

+20
-14
lines changed

2 files changed

+20
-14
lines changed

internal/terraform/context_plan.go

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,6 @@ func (c *Context) refreshOnlyPlan(config *configs.Config, prevRunState *states.S
325325

326326
func (c *Context) destroyPlan(config *configs.Config, prevRunState *states.State, opts *PlanOpts) (*plans.Plan, tfdiags.Diagnostics) {
327327
var diags tfdiags.Diagnostics
328-
pendingPlan := &plans.Plan{}
329328

330329
if opts.Mode != plans.DestroyMode {
331330
panic(fmt.Sprintf("called Context.destroyPlan with %s", opts.Mode))
@@ -373,18 +372,17 @@ func (c *Context) destroyPlan(config *configs.Config, prevRunState *states.State
373372
return nil, diags
374373
}
375374

376-
// insert the refreshed state into the destroy plan result, and ignore
377-
// the changes recorded from the refresh.
378-
pendingPlan.PriorState = refreshPlan.PriorState.DeepCopy()
379-
pendingPlan.PrevRunState = refreshPlan.PrevRunState.DeepCopy()
380-
log.Printf("[TRACE] Context.destroyPlan: now _really_ creating a destroy plan")
381-
382375
// We'll use the refreshed state -- which is the "prior state" from
383-
// the perspective of this "pending plan" -- as the starting state
376+
// the perspective of this "destroy plan" -- as the starting state
384377
// for our destroy-plan walk, so it can take into account if we
385378
// detected during refreshing that anything was already deleted outside
386379
// of Terraform.
387-
priorState = pendingPlan.PriorState
380+
priorState = refreshPlan.PriorState.DeepCopy()
381+
382+
// The refresh plan may have upgraded state for some resources, make
383+
// sure we store the new version.
384+
prevRunState = refreshPlan.PrevRunState.DeepCopy()
385+
log.Printf("[TRACE] Context.destroyPlan: now _really_ creating a destroy plan")
388386
}
389387

390388
destroyPlan, walkDiags := c.planWalk(config, priorState, opts)
@@ -394,10 +392,10 @@ func (c *Context) destroyPlan(config *configs.Config, prevRunState *states.State
394392
}
395393

396394
if !opts.SkipRefresh {
397-
// If we didn't skip refreshing then we want the previous run state
398-
// prior state to be the one we originally fed into the c.plan call
399-
// above, not the refreshed version we used for the destroy walk.
400-
destroyPlan.PrevRunState = pendingPlan.PrevRunState
395+
// If we didn't skip refreshing then we want the previous run state to
396+
// be the one we originally fed into the c.refreshOnlyPlan call above,
397+
// not the refreshed version we used for the destroy planWalk.
398+
destroyPlan.PrevRunState = prevRunState
401399
}
402400

403401
relevantAttrs, rDiags := c.relevantResourceAttrsForPlan(config, destroyPlan)

internal/terraform/context_plan2_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3676,11 +3676,19 @@ output "out" {
36763676
},
36773677
})
36783678

3679-
_, diags := ctx.Plan(m, state, &PlanOpts{
3679+
plan, diags := ctx.Plan(m, state, &PlanOpts{
36803680
Mode: plans.DestroyMode,
36813681
})
36823682

36833683
assertNoErrors(t, diags)
3684+
3685+
// ensure that the given states are valid and can be serialized
3686+
if plan.PrevRunState == nil {
3687+
t.Fatal("nil plan.PrevRunState")
3688+
}
3689+
if plan.PriorState == nil {
3690+
t.Fatal("nil plan.PriorState")
3691+
}
36843692
}
36853693

36863694
// A deposed instances which no longer exists during ReadResource creates NoOp

0 commit comments

Comments
 (0)