diff --git a/terraform/transform_destroy_cbd.go b/terraform/transform_destroy_cbd.go index 21b75c141..5945eeadd 100644 --- a/terraform/transform_destroy_cbd.go +++ b/terraform/transform_destroy_cbd.go @@ -160,23 +160,27 @@ func (t *CBDEdgeTransformer) Transform(g *Graph) error { continue } - // Find the destroy edge. There should only be one. + // Find the resource edges for _, e := range g.EdgesTo(v) { - // Not a destroy edge, ignore it - de, ok := e.(*DestroyEdge) - if !ok { - continue + switch de := e.(type) { + case *DestroyEdge: + // we need to invert the destroy edge from the create node + log.Printf("[TRACE] CBDEdgeTransformer: inverting edge: %s => %s", + dag.VertexName(de.Source()), dag.VertexName(de.Target())) + + // Found it! Invert. + g.RemoveEdge(de) + applyNode := de.Source() + destroyNode := de.Target() + g.Connect(&DestroyEdge{S: destroyNode, T: applyNode}) + default: + // We cannot have any direct dependencies from creators when + // the node is CBD without inducing a cycle. + if _, ok := e.Source().(GraphNodeCreator); ok { + log.Printf("[TRACE] CBDEdgeTransformer: removing non DestroyEdge to CBD destroy node: %s => %s", dag.VertexName(e.Source()), dag.VertexName(e.Target())) + g.RemoveEdge(e) + } } - - log.Printf("[TRACE] CBDEdgeTransformer: inverting edge: %s => %s", - dag.VertexName(de.Source()), dag.VertexName(de.Target())) - - // Found it! Invert. - g.RemoveEdge(de) - applyNode := de.Source() - destroyNode := de.Target() - g.Connect(&DestroyEdge{S: destroyNode, T: applyNode}) - break } // If the address has an index, we strip that. Our depMap creation @@ -289,7 +293,11 @@ func (t *CBDEdgeTransformer) depMap(g *Graph, destroyMap map[string][]dag.Vertex // Keep track of the destroy nodes that this address // needs to depend on. key := rn.ResourceAddr().String() - depMap[key] = append(depMap[key], dns...) + + // we only need to record the same dns once + if _, ok := depMap[key]; !ok { + depMap[key] = append(depMap[key], dns...) + } } } diff --git a/terraform/transform_destroy_edge.go b/terraform/transform_destroy_edge.go index c25bdce7e..df3872a1d 100644 --- a/terraform/transform_destroy_edge.go +++ b/terraform/transform_destroy_edge.go @@ -122,6 +122,12 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error { for _, resAddr := range ri.StateDependencies() { for _, desDep := range destroyersByResource[resAddr.String()] { + // TODO: don't connect this if c is CreateBeforeDestroy. + // This will require getting the actual change action at + // this point, since the lifecycle may have been forced + // by a dependent. This should prevent needing to prune + // the edge back out in CBDEdgeTransformer, and allow + // non-CBD nodes to depend on CBD destroys directly. log.Printf("[TRACE] DestroyEdgeTransformer: %s has stored dependency of %s\n", dag.VertexName(c), dag.VertexName(desDep)) g.Connect(dag.BasicEdge(c, desDep))