Merge pull request #31858 from hashicorp/jbardin/prune-plan-destroy

prune unused nodes from a destroy plan graph
This commit is contained in:
James Bardin 2022-09-26 14:24:07 -04:00 committed by GitHub
commit 008810f593
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 0 deletions

View File

@ -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)
}

View File

@ -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},

View File

@ -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

View File

@ -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