existing outputs can only be Updated
The planning logic here was inspired by resources, but unlike resources a null value is valid for an output and does not necessarily indicate it is being removed. If both before and after are null, the change should be NoOp. When an output is removed from the configuration, we have a separate node to create a Delete action to remove it from the state.
This commit is contained in:
parent
0a086030b1
commit
57f004e0ef
|
@ -6685,3 +6685,32 @@ func TestContext2Plan_variableCustomValidationsSensitive(t *testing.T) {
|
|||
t.Fatalf("wrong error:\ngot: %s\nwant: message containing %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext2Plan_nullOutputNoOp(t *testing.T) {
|
||||
// this should always plan a NoOp change for the output
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
output "planned" {
|
||||
value = false ? 1 : null
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Config: m,
|
||||
State: states.BuildState(func(s *states.SyncState) {
|
||||
r := s.Module(addrs.RootModuleInstance)
|
||||
r.SetOutputValue("planned", cty.NullVal(cty.DynamicPseudoType), false)
|
||||
}),
|
||||
})
|
||||
plan, diags := ctx.Plan()
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
for _, c := range plan.Changes.Outputs {
|
||||
if c.Action != plans.NoOp {
|
||||
t.Fatalf("expected no changes, got %s for %q", c.Action, c.Addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -451,10 +451,12 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C
|
|||
// strip any marks here just to be sure we don't panic on the True comparison
|
||||
val, _ = val.UnmarkDeep()
|
||||
|
||||
var action plans.Action
|
||||
action := plans.Update
|
||||
switch {
|
||||
case val.IsNull():
|
||||
action = plans.Delete
|
||||
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.
|
||||
action = plans.NoOp
|
||||
|
||||
case before.IsNull():
|
||||
action = plans.Create
|
||||
|
@ -467,9 +469,6 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C
|
|||
// only one we can act on, and the state will have been loaded
|
||||
// without any marks to consider.
|
||||
action = plans.NoOp
|
||||
|
||||
default:
|
||||
action = plans.Update
|
||||
}
|
||||
|
||||
change := &plans.OutputChange{
|
||||
|
|
Loading…
Reference in New Issue