From 4b6f258f1fe23e99d660cf652480314933d81626 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 16 Feb 2015 21:06:09 -0800 Subject: [PATCH] terraform: only depose state if we're doing the destroy side --- terraform/context_test.go | 54 +++++++++++++++++++ terraform/terraform_test.go | 7 +++ .../apply-good-create-before-update/main.tf | 7 +++ terraform/transform_resource.go | 16 ++++-- 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 terraform/test-fixtures/apply-good-create-before-update/main.tf diff --git a/terraform/context_test.go b/terraform/context_test.go index 58c5d050c..cb943c117 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -2787,6 +2787,60 @@ func TestContext2Apply_createBeforeDestroy(t *testing.T) { } } +func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) { + m := testModule(t, "apply-good-create-before-update") + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_instance.bar": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "foo": "bar", + }, + }, + }, + }, + }, + }, + } + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + State: state, + }) + + if p, err := ctx.Plan(nil); err != nil { + t.Fatalf("err: %s", err) + } else { + t.Logf(p.String()) + } + + state, err := ctx.Apply() + if err != nil { + t.Fatalf("err: %s", err) + } + + mod := state.RootModule() + if len(mod.Resources) != 1 { + t.Fatalf("bad: %s", state) + } + + actual := strings.TrimSpace(state.String()) + expected := strings.TrimSpace(testTerraformApplyCreateBeforeUpdateStr) + if actual != expected { + t.Fatalf("bad: \n%s", actual) + } +} + func TestContext2Apply_minimal(t *testing.T) { m := testModule(t, "apply-minimal") p := testProvider("aws") diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 2581b760d..d4b56967f 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -200,6 +200,13 @@ aws_instance.bar: type = aws_instance ` +const testTerraformApplyCreateBeforeUpdateStr = ` +aws_instance.bar: + ID = foo + foo = baz + type = aws_instance +` + const testTerraformApplyCancelStr = ` aws_instance.foo: ID = foo diff --git a/terraform/test-fixtures/apply-good-create-before-update/main.tf b/terraform/test-fixtures/apply-good-create-before-update/main.tf new file mode 100644 index 000000000..d0a2fc937 --- /dev/null +++ b/terraform/test-fixtures/apply-good-create-before-update/main.tf @@ -0,0 +1,7 @@ +resource "aws_instance" "bar" { + foo = "baz" + + lifecycle { + create_before_destroy = true + } +} diff --git a/terraform/transform_resource.go b/terraform/transform_resource.go index f7ef06c83..8c9c16a15 100644 --- a/terraform/transform_resource.go +++ b/terraform/transform_resource.go @@ -256,6 +256,7 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode { var diffApply *InstanceDiff var err error var createNew, tainted bool + var createBeforeDestroyEnabled bool seq.Nodes = append(seq.Nodes, &EvalOpFilter{ Ops: []walkOperation{walkApply}, Node: &EvalSequence{ @@ -285,7 +286,16 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode { &EvalIf{ If: func(ctx EvalContext) (bool, error) { - return n.Resource.Lifecycle.CreateBeforeDestroy, nil + destroy := false + if diffApply != nil { + destroy = diffApply.Destroy || diffApply.RequiresNew() + } + + createBeforeDestroyEnabled = + n.Resource.Lifecycle.CreateBeforeDestroy && + destroy + + return createBeforeDestroyEnabled, nil }, Node: &EvalDeposeState{ Name: n.stateId(), @@ -361,12 +371,12 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode { }, &EvalIf{ If: func(ctx EvalContext) (bool, error) { - if n.Resource.Lifecycle.CreateBeforeDestroy { + if createBeforeDestroyEnabled { tainted = err != nil } failure := tainted || err != nil - return n.Resource.Lifecycle.CreateBeforeDestroy && failure, nil + return createBeforeDestroyEnabled && failure, nil }, Node: &EvalUndeposeState{ Name: n.stateId(),