From 7031cb145c7c24aceb00f6002689452df75d2771 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 23 Jun 2015 20:41:02 -0700 Subject: [PATCH] terraform: orphan dependencies should be inverted --- terraform/graph_builder_test.go | 53 +++++++++++++++++++ .../graph-builder-orphan-deps/main.tf | 1 + terraform/transform_destroy.go | 10 +++- terraform/transform_orphan.go | 36 +++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 terraform/test-fixtures/graph-builder-orphan-deps/main.tf diff --git a/terraform/graph_builder_test.go b/terraform/graph_builder_test.go index ee6a5e140..dbc8ae61e 100644 --- a/terraform/graph_builder_test.go +++ b/terraform/graph_builder_test.go @@ -154,6 +154,49 @@ func TestBuiltinGraphBuilder_multiLevelModule(t *testing.T) { } } +func TestBuiltinGraphBuilder_orphanDeps(t *testing.T) { + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_instance.foo": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + + "aws_instance.bar": &ResourceState{ + Type: "aws_instance", + Dependencies: []string{"aws_instance.foo"}, + Primary: &InstanceState{ + ID: "bar", + }, + }, + }, + }, + }, + } + + b := &BuiltinGraphBuilder{ + Root: testModule(t, "graph-builder-orphan-deps"), + State: state, + Validate: true, + } + + g, err := b.Build(RootModulePath) + if err != nil { + t.Fatalf("err: %s", err) + } + + actual := strings.TrimSpace(g.String()) + expected := strings.TrimSpace(testBuiltinGraphBuilderOrphanDepsStr) + if actual != expected { + t.Fatalf("bad: %s", actual) + } +} + /* TODO: This exposes a really bad bug we need to fix after we merge the f-ast-branch. This bug still exists in master. @@ -233,6 +276,16 @@ root module.foo.plan-destroy ` +const testBuiltinGraphBuilderOrphanDepsStr = ` +aws_instance.bar (orphan) + provider.aws +aws_instance.foo (orphan) + aws_instance.bar (orphan) +provider.aws +provider.aws (close) + aws_instance.foo (orphan) +` + /* TODO: Commented out this const as it's likely this needs to be updated when the TestBuiltinGraphBuilder_modules test is diff --git a/terraform/test-fixtures/graph-builder-orphan-deps/main.tf b/terraform/test-fixtures/graph-builder-orphan-deps/main.tf new file mode 100644 index 000000000..b21d3b6ab --- /dev/null +++ b/terraform/test-fixtures/graph-builder-orphan-deps/main.tf @@ -0,0 +1 @@ +provider "aws" {} diff --git a/terraform/transform_destroy.go b/terraform/transform_destroy.go index 9fb235107..8d5aeb4c9 100644 --- a/terraform/transform_destroy.go +++ b/terraform/transform_destroy.go @@ -1,6 +1,8 @@ package terraform -import "github.com/hashicorp/terraform/dag" +import ( + "github.com/hashicorp/terraform/dag" +) type GraphNodeDestroyMode byte @@ -103,6 +105,12 @@ func (t *DestroyTransformer) transform( nodeToCn[n] = cn nodeToDn[cn] = n + // If the creation node is equal to the destroy node, then + // don't do any of the edge jump rope below. + if n.(interface{}) == cn.(interface{}) { + continue + } + // Add it to the graph g.Add(n) diff --git a/terraform/transform_orphan.go b/terraform/transform_orphan.go index 448aae794..f0aceb3b9 100644 --- a/terraform/transform_orphan.go +++ b/terraform/transform_orphan.go @@ -298,6 +298,24 @@ func (n *graphNodeOrphanResource) dependableName() string { return n.ResourceName } +// GraphNodeDestroyable impl. +func (n *graphNodeOrphanResource) DestroyNode(mode GraphNodeDestroyMode) GraphNodeDestroy { + if mode != DestroyPrimary { + return nil + } + + return n +} + +// GraphNodeDestroy impl. +func (n *graphNodeOrphanResource) CreateBeforeDestroy() bool { + return false +} + +func (n *graphNodeOrphanResource) CreateNode() dag.Vertex { + return n +} + // Same as graphNodeOrphanResource, but for flattening type graphNodeOrphanResourceFlat struct { *graphNodeOrphanResource @@ -313,3 +331,21 @@ func (n *graphNodeOrphanResourceFlat) Name() string { func (n *graphNodeOrphanResourceFlat) Path() []string { return n.PathValue } + +// GraphNodeDestroyable impl. +func (n *graphNodeOrphanResourceFlat) DestroyNode(mode GraphNodeDestroyMode) GraphNodeDestroy { + if mode != DestroyPrimary { + return nil + } + + return n +} + +// GraphNodeDestroy impl. +func (n *graphNodeOrphanResourceFlat) CreateBeforeDestroy() bool { + return false +} + +func (n *graphNodeOrphanResourceFlat) CreateNode() dag.Vertex { + return n +}