Skip to content

Commit

Permalink
Merge pull request #32207 from hashicorp/jbardin/destroy-plan-state
Browse files Browse the repository at this point in the history
Ensure destroy plan contains valid state values
  • Loading branch information
jbardin committed Nov 17, 2022
2 parents b5168eb + 3db3ed0 commit 62a8b9e
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 14 deletions.
24 changes: 11 additions & 13 deletions internal/terraform/context_plan.go
Expand Up @@ -325,7 +325,6 @@ func (c *Context) refreshOnlyPlan(config *configs.Config, prevRunState *states.S

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

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

// insert the refreshed state into the destroy plan result, and ignore
// the changes recorded from the refresh.
pendingPlan.PriorState = refreshPlan.PriorState.DeepCopy()
pendingPlan.PrevRunState = refreshPlan.PrevRunState.DeepCopy()
log.Printf("[TRACE] Context.destroyPlan: now _really_ creating a destroy plan")

// We'll use the refreshed state -- which is the "prior state" from
// the perspective of this "pending plan" -- as the starting state
// the perspective of this "destroy plan" -- as the starting state
// for our destroy-plan walk, so it can take into account if we
// detected during refreshing that anything was already deleted outside
// of Terraform.
priorState = pendingPlan.PriorState
priorState = refreshPlan.PriorState.DeepCopy()

// The refresh plan may have upgraded state for some resources, make
// sure we store the new version.
prevRunState = refreshPlan.PrevRunState.DeepCopy()
log.Printf("[TRACE] Context.destroyPlan: now _really_ creating a destroy plan")
}

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

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

relevantAttrs, rDiags := c.relevantResourceAttrsForPlan(config, destroyPlan)
Expand Down
10 changes: 9 additions & 1 deletion internal/terraform/context_plan2_test.go
Expand Up @@ -3676,11 +3676,19 @@ output "out" {
},
})

_, diags := ctx.Plan(m, state, &PlanOpts{
plan, diags := ctx.Plan(m, state, &PlanOpts{
Mode: plans.DestroyMode,
})

assertNoErrors(t, diags)

// ensure that the given states are valid and can be serialized
if plan.PrevRunState == nil {
t.Fatal("nil plan.PrevRunState")
}
if plan.PriorState == nil {
t.Fatal("nil plan.PriorState")
}
}

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

0 comments on commit 62a8b9e

Please sign in to comment.