mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
ensure destroy plan contains valid state values
Some prior refactors left the detroyPlan method a bit confusing, and ran into a case where the previous run state could be returned as nil. Get rid of the no longer used pendingPlan value, and track the prior and prev states directly, making sure we always have a value for both.
This commit is contained in:
parent
3ea704ef81
commit
3db3ed03fb
@ -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))
|
||||
@ -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)
|
||||
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user