diff --git a/plans/objchange/objchange.go b/plans/objchange/objchange.go index 15565a4006..ed0f4ba5ee 100644 --- a/plans/objchange/objchange.go +++ b/plans/objchange/objchange.go @@ -25,6 +25,13 @@ import ( // produce strange results with more "extreme" cases, such as a nested set // block where _all_ attributes are computed. func ProposedNewObject(schema *configschema.Block, prior, config cty.Value) cty.Value { + // If the config and prior are both null, return early here before + // populating the prior block. The prevents non-null blocks from appearing + // the proposed state value. + if config.IsNull() && prior.IsNull() { + return prior + } + if prior.IsNull() { // In this case, we will construct a synthetic prior value that is // similar to the result of decoding an empty configuration block, diff --git a/plans/objchange/objchange_test.go b/plans/objchange/objchange_test.go index 91f9df1f21..97f749acae 100644 --- a/plans/objchange/objchange_test.go +++ b/plans/objchange/objchange_test.go @@ -83,6 +83,45 @@ func TestProposedNewObject(t *testing.T) { }), }), }, + "null block remains null": { + &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "foo": { + Type: cty.String, + Optional: true, + }, + }, + BlockTypes: map[string]*configschema.NestedBlock{ + "baz": { + Nesting: configschema.NestingSingle, + Block: configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "boz": { + Type: cty.String, + Optional: true, + Computed: true, + }, + }, + }, + }, + }, + }, + cty.NullVal(cty.DynamicPseudoType), + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.StringVal("bar"), + "baz": cty.NullVal(cty.Object(map[string]cty.Type{ + "boz": cty.String, + })), + }), + // The baz block does not exist in the config, and therefore + // shouldn't be planned. + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.StringVal("bar"), + "baz": cty.NullVal(cty.Object(map[string]cty.Type{ + "boz": cty.String, + })), + }), + }, "no prior with set": { // This one is here because our handling of sets is more complex // than others (due to the fuzzy correlation heuristic) and