handle empty containers in ProposedNew NestedTypes

Empty containers of NestedTypes were not handled in ProposedNew, causing
plans to be submitted with null values where there was configuration
present.
This commit is contained in:
James Bardin 2021-09-14 16:36:45 -04:00
parent 9029870613
commit 331dc8b14c
2 changed files with 79 additions and 9 deletions

View File

@ -308,7 +308,9 @@ func proposedNewAttributes(attrs map[string]*configschema.Attribute, prior, conf
} }
func proposedNewNestedType(schema *configschema.Object, prior, config cty.Value) cty.Value { func proposedNewNestedType(schema *configschema.Object, prior, config cty.Value) cty.Value {
var newV cty.Value // If the config is null or empty, we will be using this default value.
newV := config
switch schema.Nesting { switch schema.Nesting {
case configschema.NestingSingle: case configschema.NestingSingle:
if !config.IsNull() { if !config.IsNull() {
@ -323,6 +325,7 @@ func proposedNewNestedType(schema *configschema.Object, prior, config cty.Value)
if config.IsKnown() && !config.IsNull() { if config.IsKnown() && !config.IsNull() {
configVLen = config.LengthInt() configVLen = config.LengthInt()
} }
if configVLen > 0 { if configVLen > 0 {
newVals := make([]cty.Value, 0, configVLen) newVals := make([]cty.Value, 0, configVLen)
for it := config.ElementIterator(); it.Next(); { for it := config.ElementIterator(); it.Next(); {
@ -345,8 +348,6 @@ func proposedNewNestedType(schema *configschema.Object, prior, config cty.Value)
} else { } else {
newV = cty.ListVal(newVals) newV = cty.ListVal(newVals)
} }
} else {
newV = cty.NullVal(schema.ImpliedType())
} }
case configschema.NestingMap: case configschema.NestingMap:
@ -378,8 +379,6 @@ func proposedNewNestedType(schema *configschema.Object, prior, config cty.Value)
// object values so that elements might have different types // object values so that elements might have different types
// in case of dynamically-typed attributes. // in case of dynamically-typed attributes.
newV = cty.ObjectVal(newVals) newV = cty.ObjectVal(newVals)
} else {
newV = cty.NullVal(schema.ImpliedType())
} }
} else { } else {
configVLen := 0 configVLen := 0
@ -403,8 +402,6 @@ func proposedNewNestedType(schema *configschema.Object, prior, config cty.Value)
newVals[k] = cty.ObjectVal(newEV) newVals[k] = cty.ObjectVal(newEV)
} }
newV = cty.MapVal(newVals) newV = cty.MapVal(newVals)
} else {
newV = cty.NullVal(schema.ImpliedType())
} }
} }
@ -446,8 +443,6 @@ func proposedNewNestedType(schema *configschema.Object, prior, config cty.Value)
} }
} }
newV = cty.SetVal(newVals) newV = cty.SetVal(newVals)
} else {
newV = cty.NullVal(schema.ImpliedType())
} }
} }

View File

@ -1461,6 +1461,81 @@ func TestProposedNew(t *testing.T) {
}))), }))),
}), }),
}, },
"expected empty NestedTypes": {
&configschema.Block{
Attributes: map[string]*configschema.Attribute{
"set": {
NestedType: &configschema.Object{
Nesting: configschema.NestingSet,
Attributes: map[string]*configschema.Attribute{
"bar": {Type: cty.String},
},
},
Optional: true,
},
"map": {
NestedType: &configschema.Object{
Nesting: configschema.NestingMap,
Attributes: map[string]*configschema.Attribute{
"bar": {Type: cty.String},
},
},
Optional: true,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"map": cty.MapValEmpty(cty.Object(map[string]cty.Type{"bar": cty.String})),
"set": cty.SetValEmpty(cty.Object(map[string]cty.Type{"bar": cty.String})),
}),
cty.ObjectVal(map[string]cty.Value{
"map": cty.MapValEmpty(cty.Object(map[string]cty.Type{"bar": cty.String})),
"set": cty.SetValEmpty(cty.Object(map[string]cty.Type{"bar": cty.String})),
}),
cty.ObjectVal(map[string]cty.Value{
"map": cty.MapValEmpty(cty.Object(map[string]cty.Type{"bar": cty.String})),
"set": cty.SetValEmpty(cty.Object(map[string]cty.Type{"bar": cty.String})),
}),
},
"optional types set replacement": {
&configschema.Block{
Attributes: map[string]*configschema.Attribute{
"set": {
NestedType: &configschema.Object{
Nesting: configschema.NestingSet,
Attributes: map[string]*configschema.Attribute{
"bar": {
Type: cty.String,
Required: true,
},
},
},
Optional: true,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"set": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("old"),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"set": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("new"),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"set": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("new"),
}),
}),
}),
},
} }
for name, test := range tests { for name, test := range tests {