core: respect roots in CBD transform

Because CBD now runs after a RootTransformer, it's now operating on a
graph that _may_ have had a graphNodeRoot added to it (a noop node whose
only purpose is to be a root).

CBD includes a step that tells the destroy node to depend on any parents
of the create node. When one of those parents was "root", this was
causing the destroy node to depend on "root", making it cease to be an
actual root node.

Because graphNodeRoot is a singleton, the follow-up RootTransformer was
not sufficient to slap another root on top - it wasn't being seen as a
fresh node, so edges were just accumulating, and we ended up in a state
with "no roots".

refs #1903 (not sure if this will fix all the "no root found" cases, or
just the one I bumped into)
This commit is contained in:
Paul Hinze 2015-05-13 17:19:26 -05:00
parent e1b4bf3ce0
commit 842d66183b
3 changed files with 59 additions and 3 deletions

View File

@ -40,6 +40,43 @@ func TestContext2Plan(t *testing.T) {
}
}
func TestContext2Plan_createBefore_maintainRoot(t *testing.T) {
m := testModule(t, "plan-cbd-maintain-root")
p := testProvider("aws")
p.DiffFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
Variables: map[string]string{
"in": "a,b,c",
},
})
plan, err := ctx.Plan()
if err != nil {
t.Fatalf("err: %s", err)
}
actual := strings.TrimSpace(plan.String())
expected := strings.TrimSpace(`
DIFF:
CREATE: aws_instance.bar.0
CREATE: aws_instance.bar.1
CREATE: aws_instance.foo.0
CREATE: aws_instance.foo.1
STATE:
<no state>
`)
if actual != expected {
t.Fatalf("expected:\n%s, got:\n%s", expected, actual)
}
}
func TestContext2Plan_emptyDiff(t *testing.T) {
m := testModule(t, "plan-empty")
p := testProvider("aws")

View File

@ -0,0 +1,13 @@
resource "aws_instance" "foo" {
count = "2"
lifecycle { create_before_destroy = true }
}
resource "aws_instance" "bar" {
count = "2"
lifecycle { create_before_destroy = true }
}
output "out" {
value = "${aws_instance.foo.0.id}"
}

View File

@ -1,8 +1,6 @@
package terraform
import (
"github.com/hashicorp/terraform/dag"
)
import "github.com/hashicorp/terraform/dag"
type GraphNodeDestroyMode byte
@ -193,6 +191,14 @@ func (t *CreateBeforeDestroyTransformer) Transform(g *Graph) error {
// This ensures that.
for _, sourceRaw := range g.UpEdges(cn).List() {
source := sourceRaw.(dag.Vertex)
// If the graph has a "root" node (one added by a RootTransformer and not
// just a resource that happens to have no ancestors), we don't want to
// add any edges to it, because then it ceases to be a root.
if _, ok := source.(graphNodeRoot); ok {
continue
}
connect = append(connect, dag.BasicEdge(dn, source))
}