Merge pull request #23717 from hashicorp/jbardin/destroy-plan-values
Always prune unused values
This commit is contained in:
commit
8b0888798f
|
@ -10526,7 +10526,6 @@ func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxOpts.ProviderResolver = providerResolver
|
ctxOpts.ProviderResolver = providerResolver
|
||||||
ctxOpts.Destroy = true
|
|
||||||
ctx, diags = NewContext(ctxOpts)
|
ctx, diags = NewContext(ctxOpts)
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
t.Fatalf("err: %s", diags.Err())
|
t.Fatalf("err: %s", diags.Err())
|
||||||
|
|
|
@ -175,17 +175,20 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||||
// Reverse the edges from outputs and locals, so that
|
// Reverse the edges from outputs and locals, so that
|
||||||
// interpolations don't fail during destroy.
|
// interpolations don't fail during destroy.
|
||||||
// Create a destroy node for outputs to remove them from the state.
|
// Create a destroy node for outputs to remove them from the state.
|
||||||
// Prune unreferenced values, which may have interpolations that can't
|
|
||||||
// be resolved.
|
|
||||||
GraphTransformIf(
|
GraphTransformIf(
|
||||||
func() bool { return b.Destroy },
|
func() bool { return b.Destroy },
|
||||||
GraphTransformMulti(
|
GraphTransformMulti(
|
||||||
&DestroyValueReferenceTransformer{},
|
&DestroyValueReferenceTransformer{},
|
||||||
&DestroyOutputTransformer{},
|
&DestroyOutputTransformer{},
|
||||||
&PruneUnusedValuesTransformer{},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Prune unreferenced values, which may have interpolations that can't
|
||||||
|
// be resolved.
|
||||||
|
&PruneUnusedValuesTransformer{
|
||||||
|
Destroy: b.Destroy,
|
||||||
|
},
|
||||||
|
|
||||||
// Add the node to fix the state count boundaries
|
// Add the node to fix the state count boundaries
|
||||||
&CountBoundaryTransformer{
|
&CountBoundaryTransformer{
|
||||||
Config: b.Config,
|
Config: b.Config,
|
||||||
|
|
|
@ -406,9 +406,7 @@ module.child:
|
||||||
<no state>
|
<no state>
|
||||||
Outputs:
|
Outputs:
|
||||||
|
|
||||||
aws_access_key = YYYYY
|
|
||||||
aws_route53_zone_id = XXXX
|
aws_route53_zone_id = XXXX
|
||||||
aws_secret_key = ZZZZ
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const testTerraformApplyDependsCreateBeforeStr = `
|
const testTerraformApplyDependsCreateBeforeStr = `
|
||||||
|
@ -693,11 +691,6 @@ foo = bar
|
||||||
|
|
||||||
const testTerraformApplyOutputOrphanModuleStr = `
|
const testTerraformApplyOutputOrphanModuleStr = `
|
||||||
<no state>
|
<no state>
|
||||||
module.child:
|
|
||||||
<no state>
|
|
||||||
Outputs:
|
|
||||||
|
|
||||||
foo = bar
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const testTerraformApplyProvisionerStr = `
|
const testTerraformApplyProvisionerStr = `
|
||||||
|
|
|
@ -3,9 +3,18 @@ variable "list" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_instance" "a" {
|
resource "aws_instance" "a" {
|
||||||
count = "${length(var.list)}"
|
count = length(var.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
locals {
|
||||||
|
ids = aws_instance.a[*].id
|
||||||
|
}
|
||||||
|
|
||||||
|
module "empty" {
|
||||||
|
source = "./mod"
|
||||||
|
input = zipmap(var.list, local.ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
output "out" {
|
output "out" {
|
||||||
value = "${aws_instance.a.*.id}"
|
value = aws_instance.a[*].id
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
variable "input" {
|
||||||
|
}
|
|
@ -206,21 +206,30 @@ func (t *DestroyValueReferenceTransformer) Transform(g *Graph) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PruneUnusedValuesTransformer is s GraphTransformer that removes local and
|
// PruneUnusedValuesTransformer is a GraphTransformer that removes local,
|
||||||
// output values which are not referenced in the graph. Since outputs and
|
// variable, and output values which are not referenced in the graph. If these
|
||||||
// locals always need to be evaluated, if they reference a resource that is not
|
// values reference a resource that is no longer in the state the interpolation
|
||||||
// available in the state the interpolation could fail.
|
// could fail.
|
||||||
type PruneUnusedValuesTransformer struct{}
|
type PruneUnusedValuesTransformer struct {
|
||||||
|
Destroy bool
|
||||||
|
}
|
||||||
|
|
||||||
func (t *PruneUnusedValuesTransformer) Transform(g *Graph) error {
|
func (t *PruneUnusedValuesTransformer) Transform(g *Graph) error {
|
||||||
// this might need multiple runs in order to ensure that pruning a value
|
// Pruning a value can effect previously checked edges, so loop until there
|
||||||
// doesn't effect a previously checked value.
|
// are no more changes.
|
||||||
for removed := 0; ; removed = 0 {
|
for removed := 0; ; removed = 0 {
|
||||||
for _, v := range g.Vertices() {
|
for _, v := range g.Vertices() {
|
||||||
switch v.(type) {
|
switch v := v.(type) {
|
||||||
case *NodeApplyableOutput, *NodeLocal:
|
case *NodeApplyableOutput:
|
||||||
|
// If we're not certain this is a full destroy, we need to keep any
|
||||||
|
// root module outputs
|
||||||
|
if v.Addr.Module.IsRoot() && !t.Destroy {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case *NodeLocal, *NodeApplyableModuleVariable:
|
||||||
// OK
|
// OK
|
||||||
default:
|
default:
|
||||||
|
// We're only concerned with variables, locals and outputs
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +238,7 @@ func (t *PruneUnusedValuesTransformer) Transform(g *Graph) error {
|
||||||
switch dependants.Len() {
|
switch dependants.Len() {
|
||||||
case 0:
|
case 0:
|
||||||
// nothing at all depends on this
|
// nothing at all depends on this
|
||||||
|
log.Printf("[TRACE] PruneUnusedValuesTransformer: removing unused value %s", dag.VertexName(v))
|
||||||
g.Remove(v)
|
g.Remove(v)
|
||||||
removed++
|
removed++
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -236,6 +246,7 @@ func (t *PruneUnusedValuesTransformer) Transform(g *Graph) error {
|
||||||
// we need to check for the case of a single destroy node.
|
// we need to check for the case of a single destroy node.
|
||||||
d := dependants.List()[0]
|
d := dependants.List()[0]
|
||||||
if _, ok := d.(*NodeDestroyableOutput); ok {
|
if _, ok := d.(*NodeDestroyableOutput); ok {
|
||||||
|
log.Printf("[TRACE] PruneUnusedValuesTransformer: removing unused value %s", dag.VertexName(v))
|
||||||
g.Remove(v)
|
g.Remove(v)
|
||||||
removed++
|
removed++
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue