From 191124e9c9482bd99fbe229f7bc2fb67c3a6178a Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 14 Jan 2021 09:24:47 -0500 Subject: [PATCH] detect new outputs and plans as Create actions Rather than using a prior value of null to indicate create, which is imprecise because null is a valid output value, only plan values that didn't exist in the prior state as Create changes. --- terraform/context_plan_test.go | 26 ++++++++++++++++++++++++++ terraform/node_output.go | 10 ++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index f4dede18a..cab642b28 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -6714,3 +6714,29 @@ output "planned" { } } } + +func TestContext2Plan_createOutput(t *testing.T) { + // this should always plan a NoOp change for the output + m := testModuleInline(t, map[string]string{ + "main.tf": ` +output "planned" { + value = 1 +} +`, + }) + + ctx := testContext2(t, &ContextOpts{ + Config: m, + State: states.NewState(), + }) + plan, diags := ctx.Plan() + if diags.HasErrors() { + t.Fatal(diags.Err()) + } + + for _, c := range plan.Changes.Outputs { + if c.Action != plans.Create { + t.Fatalf("expected Create change, got %s for %q", c.Action, c.Addr) + } + } +} diff --git a/terraform/node_output.go b/terraform/node_output.go index d928a796b..c70c76e9c 100644 --- a/terraform/node_output.go +++ b/terraform/node_output.go @@ -432,12 +432,17 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C // the diff sensitiveBefore := false before := cty.NullVal(cty.DynamicPseudoType) + + // is this output new to our state? + newOutput := true + mod := state.Module(n.Addr.Module) if n.Addr.Module.IsRoot() && mod != nil { for name, o := range mod.OutputValues { if name == n.Addr.OutputValue.Name { before = o.Value sensitiveBefore = o.Sensitive + newOutput = false break } } @@ -455,10 +460,11 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C switch { case val.IsNull() && before.IsNull(): // This is separate from the NoOp case below, since we can ignore - // sensitivity here if there are only null values. + // sensitivity here when there are only null values. action = plans.NoOp - case before.IsNull(): + case newOutput: + // This output was just added to the configuration action = plans.Create case val.IsWhollyKnown() &&