Merge pull request #10068 from hashicorp/b-destroy-edge

terraform: destroy edge must include resources through outputs
This commit is contained in:
Mitchell Hashimoto 2016-11-14 09:34:36 -08:00 committed by GitHub
commit 9205d25d38
4 changed files with 54 additions and 5 deletions

View File

@ -0,0 +1,5 @@
resource "aws_instance" "b" {
value = "foo"
}
output "output" { value = "${aws_instance.b.value}" }

View File

@ -0,0 +1,7 @@
resource "aws_instance" "a" {
value = "${module.child.output}"
}
module "child" {
source = "./child"
}

View File

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

View File

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