Skip to content

Commit

Permalink
Merge pull request #31858 from hashicorp/jbardin/prune-plan-destroy
Browse files Browse the repository at this point in the history
prune unused nodes from a destroy plan graph
  • Loading branch information
jbardin committed Sep 26, 2022
2 parents 1c8352d + aedd95a commit 008810f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
41 changes: 41 additions & 0 deletions internal/terraform/context_plan2_test.go
Expand Up @@ -3518,3 +3518,44 @@ resource "test_object" "b" {
t.Fatalf("no cycle error found:\n got: %s\n", msg)
}
}

// plan a destroy with no state where configuration could fail to evaluate
// expansion indexes.
func TestContext2Plan_emptyDestroy(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
locals {
enable = true
value = local.enable ? module.example[0].out : null
}
module "example" {
count = local.enable ? 1 : 0
source = "./example"
}
`,
"example/main.tf": `
resource "test_resource" "x" {
}
output "out" {
value = test_resource.x
}
`,
})

p := testProvider("test")
state := states.NewState()

ctx := testContext2(t, &ContextOpts{
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})

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

assertNoErrors(t, diags)
}
4 changes: 4 additions & 0 deletions internal/terraform/graph_builder_plan.go
Expand Up @@ -170,6 +170,10 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
// TargetsTransformer can determine which nodes to keep in the graph.
&DestroyEdgeTransformer{},

&pruneUnusedNodesTransformer{
skip: b.Operation != walkPlanDestroy,
},

// Target
&TargetsTransformer{Targets: b.Targets},

Expand Down
4 changes: 4 additions & 0 deletions internal/terraform/node_resource_plan.go
Expand Up @@ -53,12 +53,16 @@ var (
_ GraphNodeAttachResourceConfig = (*nodeExpandPlannableResource)(nil)
_ GraphNodeAttachDependencies = (*nodeExpandPlannableResource)(nil)
_ GraphNodeTargetable = (*nodeExpandPlannableResource)(nil)
_ graphNodeExpandsInstances = (*nodeExpandPlannableResource)(nil)
)

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

func (n *nodeExpandPlannableResource) expandsInstances() {
}

// GraphNodeAttachDependencies
func (n *nodeExpandPlannableResource) AttachDependencies(deps []addrs.ConfigResource) {
n.dependencies = deps
Expand Down
9 changes: 9 additions & 0 deletions internal/terraform/transform_destroy_edge.go
Expand Up @@ -227,9 +227,18 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
// closers also need to disable their use of expansion if the module itself is
// no longer present.
type pruneUnusedNodesTransformer struct {
// The plan graph builder will skip this transformer except during a full
// destroy. Planing normally involves all nodes, but during a destroy plan
// we may need to prune things which are in the configuration but do not
// exist in state to evaluate.
skip bool
}

func (t *pruneUnusedNodesTransformer) Transform(g *Graph) error {
if t.skip {
return nil
}

// We need a reverse depth first walk of modules, processing them in order
// from the leaf modules to the root. This allows us to remove unneeded
// dependencies from child modules, freeing up nodes in the parent module
Expand Down

0 comments on commit 008810f

Please sign in to comment.