Skip to content

Commit 8cc551a

Browse files
authored
Merge pull request #31873 from hashicorp/backport/jbardin/prune-plan-destroy/inherently-close-fly
Backport of prune unused nodes from a destroy plan graph into v1.3
2 parents 1fede24 + 0406709 commit 8cc551a

File tree

4 files changed

+58
-0
lines changed

4 files changed

+58
-0
lines changed

internal/terraform/context_plan2_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3518,3 +3518,44 @@ resource "test_object" "b" {
35183518
t.Fatalf("no cycle error found:\n got: %s\n", msg)
35193519
}
35203520
}
3521+
3522+
// plan a destroy with no state where configuration could fail to evaluate
3523+
// expansion indexes.
3524+
func TestContext2Plan_emptyDestroy(t *testing.T) {
3525+
m := testModuleInline(t, map[string]string{
3526+
"main.tf": `
3527+
locals {
3528+
enable = true
3529+
value = local.enable ? module.example[0].out : null
3530+
}
3531+
3532+
module "example" {
3533+
count = local.enable ? 1 : 0
3534+
source = "./example"
3535+
}
3536+
`,
3537+
"example/main.tf": `
3538+
resource "test_resource" "x" {
3539+
}
3540+
3541+
output "out" {
3542+
value = test_resource.x
3543+
}
3544+
`,
3545+
})
3546+
3547+
p := testProvider("test")
3548+
state := states.NewState()
3549+
3550+
ctx := testContext2(t, &ContextOpts{
3551+
Providers: map[addrs.Provider]providers.Factory{
3552+
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
3553+
},
3554+
})
3555+
3556+
_, diags := ctx.Plan(m, state, &PlanOpts{
3557+
Mode: plans.DestroyMode,
3558+
})
3559+
3560+
assertNoErrors(t, diags)
3561+
}

internal/terraform/graph_builder_plan.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
170170
// TargetsTransformer can determine which nodes to keep in the graph.
171171
&DestroyEdgeTransformer{},
172172

173+
&pruneUnusedNodesTransformer{
174+
skip: b.Operation != walkPlanDestroy,
175+
},
176+
173177
// Target
174178
&TargetsTransformer{Targets: b.Targets},
175179

internal/terraform/node_resource_plan.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,16 @@ var (
5353
_ GraphNodeAttachResourceConfig = (*nodeExpandPlannableResource)(nil)
5454
_ GraphNodeAttachDependencies = (*nodeExpandPlannableResource)(nil)
5555
_ GraphNodeTargetable = (*nodeExpandPlannableResource)(nil)
56+
_ graphNodeExpandsInstances = (*nodeExpandPlannableResource)(nil)
5657
)
5758

5859
func (n *nodeExpandPlannableResource) Name() string {
5960
return n.NodeAbstractResource.Name() + " (expand)"
6061
}
6162

63+
func (n *nodeExpandPlannableResource) expandsInstances() {
64+
}
65+
6266
// GraphNodeAttachDependencies
6367
func (n *nodeExpandPlannableResource) AttachDependencies(deps []addrs.ConfigResource) {
6468
n.dependencies = deps

internal/terraform/transform_destroy_edge.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,18 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
227227
// closers also need to disable their use of expansion if the module itself is
228228
// no longer present.
229229
type pruneUnusedNodesTransformer struct {
230+
// The plan graph builder will skip this transformer except during a full
231+
// destroy. Planing normally involves all nodes, but during a destroy plan
232+
// we may need to prune things which are in the configuration but do not
233+
// exist in state to evaluate.
234+
skip bool
230235
}
231236

232237
func (t *pruneUnusedNodesTransformer) Transform(g *Graph) error {
238+
if t.skip {
239+
return nil
240+
}
241+
233242
// We need a reverse depth first walk of modules, processing them in order
234243
// from the leaf modules to the root. This allows us to remove unneeded
235244
// dependencies from child modules, freeing up nodes in the parent module

0 commit comments

Comments
 (0)