terraform: put destroy nodes into the graph
This commit is contained in:
parent
4caab6870b
commit
d7dc0291f5
|
@ -95,6 +95,9 @@ func (b *BuiltinGraphBuilder) Steps() []GraphTransformer {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Create the destruction nodes
|
||||||
|
&DestroyTransformer{},
|
||||||
|
|
||||||
// Make sure we create one root
|
// Make sure we create one root
|
||||||
&RootTransformer{},
|
&RootTransformer{},
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,8 +106,12 @@ const testBasicGraphBuilderStr = `
|
||||||
|
|
||||||
const testBuiltinGraphBuilderBasicStr = `
|
const testBuiltinGraphBuilderBasicStr = `
|
||||||
aws_instance.db
|
aws_instance.db
|
||||||
|
aws_instance.db (destroy)
|
||||||
|
aws_instance.db (destroy)
|
||||||
provider.aws
|
provider.aws
|
||||||
aws_instance.web
|
aws_instance.web
|
||||||
|
aws_instance.web (destroy)
|
||||||
|
aws_instance.web (destroy)
|
||||||
aws_instance.db
|
aws_instance.db
|
||||||
provider.aws
|
provider.aws
|
||||||
provider.aws
|
provider.aws
|
||||||
|
@ -115,10 +119,14 @@ provider.aws
|
||||||
|
|
||||||
const testBuiltinGraphBuilderModuleStr = `
|
const testBuiltinGraphBuilderModuleStr = `
|
||||||
aws_instance.web
|
aws_instance.web
|
||||||
|
aws_instance.web (destroy)
|
||||||
|
aws_instance.web (destroy)
|
||||||
aws_security_group.firewall
|
aws_security_group.firewall
|
||||||
module.consul (expanded)
|
module.consul (expanded)
|
||||||
provider.aws
|
provider.aws
|
||||||
aws_security_group.firewall
|
aws_security_group.firewall
|
||||||
|
aws_security_group.firewall (destroy)
|
||||||
|
aws_security_group.firewall (destroy)
|
||||||
provider.aws
|
provider.aws
|
||||||
module.consul (expanded)
|
module.consul (expanded)
|
||||||
aws_security_group.firewall
|
aws_security_group.firewall
|
||||||
|
|
|
@ -243,6 +243,21 @@ func (n *GraphNodeConfigResource) ProvisionedBy() []string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GraphNodeDestroyable
|
||||||
|
func (n *GraphNodeConfigResource) DestroyNode() dag.Vertex {
|
||||||
|
return &GraphNodeConfigResourceDestroy{Resource: n.Resource}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeConfigResourceDestroy represents the logical destroy step for
|
||||||
|
// a resource.
|
||||||
|
type GraphNodeConfigResourceDestroy struct {
|
||||||
|
Resource *config.Resource
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *GraphNodeConfigResourceDestroy) Name() string {
|
||||||
|
return fmt.Sprintf("%s (destroy)", n.Resource.Id())
|
||||||
|
}
|
||||||
|
|
||||||
// graphNodeModuleExpanded represents a module where the graph has
|
// graphNodeModuleExpanded represents a module where the graph has
|
||||||
// been expanded. It stores the graph of the module as well as a reference
|
// been expanded. It stores the graph of the module as well as a reference
|
||||||
// to the map of variables.
|
// to the map of variables.
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
resource "aws_instance" "foo" {}
|
||||||
|
|
||||||
|
resource "aws_instance" "bar" {
|
||||||
|
value = "${aws_instance.foo.value}"
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/dag"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GraphNodeDestroyable is the interface that nodes that can be destroyed
|
||||||
|
// must implement. This is used to automatically handle the creation of
|
||||||
|
// destroy nodes in the graph and the dependency ordering of those destroys.
|
||||||
|
type GraphNodeDestroyable interface {
|
||||||
|
// DestroyNode returns the node used for the destroy. This vertex
|
||||||
|
// should not be in the graph yet.
|
||||||
|
DestroyNode() dag.Vertex
|
||||||
|
}
|
||||||
|
|
||||||
|
// DestroyTransformer is a GraphTransformer that creates the destruction
|
||||||
|
// nodes for things that _might_ be destroyed.
|
||||||
|
type DestroyTransformer struct{}
|
||||||
|
|
||||||
|
func (t *DestroyTransformer) Transform(g *Graph) error {
|
||||||
|
for _, v := range g.Vertices() {
|
||||||
|
// If it is not a destroyable, we don't care
|
||||||
|
dn, ok := v.(GraphNodeDestroyable)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the destroy side of the node and connect it through
|
||||||
|
n := dn.DestroyNode()
|
||||||
|
if n == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add it to the graph
|
||||||
|
g.Add(n)
|
||||||
|
|
||||||
|
// Inherit all the edges from the old node
|
||||||
|
downEdges := g.DownEdges(v).List()
|
||||||
|
for _, edgeRaw := range downEdges {
|
||||||
|
g.Connect(dag.BasicEdge(n, edgeRaw.(dag.Vertex)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all the edges from the old now
|
||||||
|
for _, edgeRaw := range downEdges {
|
||||||
|
g.RemoveEdge(dag.BasicEdge(v, edgeRaw.(dag.Vertex)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new edge to connect the node to be created to
|
||||||
|
// the destroy node.
|
||||||
|
g.Connect(dag.BasicEdge(v, n))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDestroyTransformer(t *testing.T) {
|
||||||
|
mod := testModule(t, "transform-destroy-basic")
|
||||||
|
|
||||||
|
g := Graph{Path: RootModulePath}
|
||||||
|
{
|
||||||
|
tf := &ConfigTransformer{Module: mod}
|
||||||
|
if err := tf.Transform(&g); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
tf := &DestroyTransformer{}
|
||||||
|
if err := tf.Transform(&g); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(g.String())
|
||||||
|
expected := strings.TrimSpace(testTransformDestroyBasicStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("bad:\n\n%s", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testTransformDestroyBasicStr = `
|
||||||
|
aws_instance.bar
|
||||||
|
aws_instance.bar (destroy)
|
||||||
|
aws_instance.bar (destroy)
|
||||||
|
aws_instance.foo
|
||||||
|
aws_instance.foo
|
||||||
|
aws_instance.foo (destroy)
|
||||||
|
aws_instance.foo (destroy)
|
||||||
|
`
|
Loading…
Reference in New Issue