diff --git a/terraform/test-fixtures/transform-destroy-edge-module/child/main.tf b/terraform/test-fixtures/transform-destroy-edge-module/child/main.tf new file mode 100644 index 000000000..cc2f3b7ff --- /dev/null +++ b/terraform/test-fixtures/transform-destroy-edge-module/child/main.tf @@ -0,0 +1,5 @@ +resource "aws_instance" "b" { + value = "foo" +} + +output "output" { value = "${aws_instance.b.value}" } diff --git a/terraform/test-fixtures/transform-destroy-edge-module/main.tf b/terraform/test-fixtures/transform-destroy-edge-module/main.tf new file mode 100644 index 000000000..207e6d043 --- /dev/null +++ b/terraform/test-fixtures/transform-destroy-edge-module/main.tf @@ -0,0 +1,7 @@ +resource "aws_instance" "a" { + value = "${module.child.output}" +} + +module "child" { + source = "./child" +} diff --git a/terraform/transform_destroy_edge.go b/terraform/transform_destroy_edge.go index dd6ed114c..789586ef0 100644 --- a/terraform/transform_destroy_edge.go +++ b/terraform/transform_destroy_edge.go @@ -116,8 +116,10 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error { // in the graph. BUT if resource A is just pure destroy, then only // destroy A is in the graph, and create A is not. steps := []GraphTransformer{ + &OutputTransformer{Module: t.Module}, &AttachResourceConfigTransformer{Module: t.Module}, &AttachStateTransformer{State: t.State}, + &ReferenceTransformer{}, } // 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) // var tempG Graph + var tempDestroyed []dag.Vertex for d, _ := range destroyers { // d is what is being destroyed. We parse the resource address // 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. node := &NodeAbstractResource{Addr: addr} tempG.Add(node) + tempDestroyed = append(tempDestroyed, node) } // 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 - refMap := NewReferenceMap(tempG.Vertices()) + log.Printf("[TRACE] DestroyEdgeTransformer: reference graph: %s", tempG.String()) // Go through all the nodes in the graph and determine what they // depend on. - for _, v := range tempG.Vertices() { - // Find all the references - refs, _ := refMap.References(v) + for _, v := range tempDestroyed { + // Find all ancestors of this to determine the edges we'll depend on + 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( "[TRACE] DestroyEdgeTransformer: creation node %q references %v", dag.VertexName(v), refs) diff --git a/terraform/transform_destroy_edge_test.go b/terraform/transform_destroy_edge_test.go index 9475e5165..873b01eac 100644 --- a/terraform/transform_destroy_edge_test.go +++ b/terraform/transform_destroy_edge_test.go @@ -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 { AddrString string } @@ -125,6 +143,7 @@ test.B (destroy) const testTransformDestroyEdgeMultiStr = ` test.A (destroy) test.B (destroy) + test.C (destroy) test.B (destroy) test.C (destroy) test.C (destroy) @@ -133,3 +152,9 @@ test.C (destroy) const testTransformDestroyEdgeSelfRefStr = ` test.A (destroy) ` + +const testTransformDestroyEdgeModuleStr = ` +aws_instance.a (destroy) +module.child.aws_instance.b (destroy) + aws_instance.a (destroy) +`