mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-27 17:06:27 -06:00
terraform: destroy edge must include resources through outputs
This fixes: `TestContext2Apply_moduleDestroyOrder` The new destroy graph wasn't properly creating edges that happened _through_ an output, it was only created the edges for _direct_ dependents. To fix this, the DestroyEdgeTransformer now creates the full transitive list of destroy edges by walking all ancestors. This will create more edges than are necessary but also will no longer miss resources through an output.
This commit is contained in:
parent
008b8b4c23
commit
f6161a7dc9
@ -0,0 +1,5 @@
|
|||||||
|
resource "aws_instance" "b" {
|
||||||
|
value = "foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "output" { value = "${aws_instance.b.value}" }
|
@ -0,0 +1,7 @@
|
|||||||
|
resource "aws_instance" "a" {
|
||||||
|
value = "${module.child.output}"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "child" {
|
||||||
|
source = "./child"
|
||||||
|
}
|
@ -116,8 +116,10 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
|
|||||||
// in the graph. BUT if resource A is just pure destroy, then only
|
// in the graph. BUT if resource A is just pure destroy, then only
|
||||||
// destroy A is in the graph, and create A is not.
|
// destroy A is in the graph, and create A is not.
|
||||||
steps := []GraphTransformer{
|
steps := []GraphTransformer{
|
||||||
|
&OutputTransformer{Module: t.Module},
|
||||||
&AttachResourceConfigTransformer{Module: t.Module},
|
&AttachResourceConfigTransformer{Module: t.Module},
|
||||||
&AttachStateTransformer{State: t.State},
|
&AttachStateTransformer{State: t.State},
|
||||||
|
&ReferenceTransformer{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through all the nodes being destroyed and create a graph.
|
// Go through all the nodes being destroyed and create a graph.
|
||||||
@ -127,6 +129,7 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
|
|||||||
// A, B (with no edges)
|
// A, B (with no edges)
|
||||||
//
|
//
|
||||||
var tempG Graph
|
var tempG Graph
|
||||||
|
var tempDestroyed []dag.Vertex
|
||||||
for d, _ := range destroyers {
|
for d, _ := range destroyers {
|
||||||
// d is what is being destroyed. We parse the resource address
|
// d is what is being destroyed. We parse the resource address
|
||||||
// which it came from it is a panic if this fails.
|
// which it came from it is a panic if this fails.
|
||||||
@ -140,6 +143,7 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
|
|||||||
// attach config and state transformers then ask for references.
|
// attach config and state transformers then ask for references.
|
||||||
node := &NodeAbstractResource{Addr: addr}
|
node := &NodeAbstractResource{Addr: addr}
|
||||||
tempG.Add(node)
|
tempG.Add(node)
|
||||||
|
tempDestroyed = append(tempDestroyed, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the graph transforms so we have the information we need to
|
// Run the graph transforms so we have the information we need to
|
||||||
@ -150,14 +154,22 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a reference map for easy lookup
|
log.Printf("[TRACE] DestroyEdgeTransformer: reference graph: %s", tempG.String())
|
||||||
refMap := NewReferenceMap(tempG.Vertices())
|
|
||||||
|
|
||||||
// Go through all the nodes in the graph and determine what they
|
// Go through all the nodes in the graph and determine what they
|
||||||
// depend on.
|
// depend on.
|
||||||
for _, v := range tempG.Vertices() {
|
for _, v := range tempDestroyed {
|
||||||
// Find all the references
|
// Find all descendents of this to determine the edges we'll depend on
|
||||||
refs, _ := refMap.References(v)
|
vs, err := tempG.Ancestors(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
refs := make([]dag.Vertex, 0, vs.Len())
|
||||||
|
for _, raw := range vs.List() {
|
||||||
|
refs = append(refs, raw.(dag.Vertex))
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"[TRACE] DestroyEdgeTransformer: creation node %q references %v",
|
"[TRACE] DestroyEdgeTransformer: creation node %q references %v",
|
||||||
dag.VertexName(v), refs)
|
dag.VertexName(v), refs)
|
||||||
|
@ -78,6 +78,24 @@ func TestDestroyEdgeTransformer_selfRef(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDestroyEdgeTransformer_module(t *testing.T) {
|
||||||
|
g := Graph{Path: RootModulePath}
|
||||||
|
g.Add(&graphNodeDestroyerTest{AddrString: "module.child.aws_instance.b"})
|
||||||
|
g.Add(&graphNodeDestroyerTest{AddrString: "aws_instance.a"})
|
||||||
|
tf := &DestroyEdgeTransformer{
|
||||||
|
Module: testModule(t, "transform-destroy-edge-module"),
|
||||||
|
}
|
||||||
|
if err := tf.Transform(&g); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(g.String())
|
||||||
|
expected := strings.TrimSpace(testTransformDestroyEdgeModuleStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("bad:\n\n%s", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type graphNodeCreatorTest struct {
|
type graphNodeCreatorTest struct {
|
||||||
AddrString string
|
AddrString string
|
||||||
}
|
}
|
||||||
@ -125,6 +143,7 @@ test.B (destroy)
|
|||||||
const testTransformDestroyEdgeMultiStr = `
|
const testTransformDestroyEdgeMultiStr = `
|
||||||
test.A (destroy)
|
test.A (destroy)
|
||||||
test.B (destroy)
|
test.B (destroy)
|
||||||
|
test.C (destroy)
|
||||||
test.B (destroy)
|
test.B (destroy)
|
||||||
test.C (destroy)
|
test.C (destroy)
|
||||||
test.C (destroy)
|
test.C (destroy)
|
||||||
@ -133,3 +152,9 @@ test.C (destroy)
|
|||||||
const testTransformDestroyEdgeSelfRefStr = `
|
const testTransformDestroyEdgeSelfRefStr = `
|
||||||
test.A (destroy)
|
test.A (destroy)
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testTransformDestroyEdgeModuleStr = `
|
||||||
|
aws_instance.a (destroy)
|
||||||
|
module.child.aws_instance.b (destroy)
|
||||||
|
aws_instance.a (destroy)
|
||||||
|
`
|
||||||
|
Loading…
Reference in New Issue
Block a user