Skip to content

Commit 18d3542

Browse files
committed
objchange: fix ProposedNew from null objects
The codepath for AllAttributesNull was not correct for any nested object types with collections, and should create single null values for the correct NestingMode rather than a single object with null attributes. Since there is no reason to descend into nested object types to create nullv alues, we can drop the AllAttributesNull function altogether and create null values as needed during ProposedNew. The corresponding AllBlockAttributesNull was only called internally in 1 location, and simply delegated to schema.EmptyValue. We can reduce the package surface area by dropping that function too and calling EmptyValue directly.
1 parent 0062e71 commit 18d3542

File tree

3 files changed

+115
-38
lines changed

3 files changed

+115
-38
lines changed

internal/plans/objchange/all_null.go

Lines changed: 0 additions & 33 deletions
This file was deleted.

internal/plans/objchange/objchange.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ func ProposedNew(schema *configschema.Block, prior, config cty.Value) cty.Value
3737
// similar to the result of decoding an empty configuration block,
3838
// which simplifies our handling of the top-level attributes/blocks
3939
// below by giving us one non-null level of object to pull values from.
40-
prior = AllBlockAttributesNull(schema)
40+
//
41+
// "All attributes null" happens to be the definition of EmptyValue for
42+
// a Block, so we can just delegate to that
43+
prior = schema.EmptyValue()
4144
}
4245
return proposedNew(schema, prior, config)
4346
}
@@ -258,12 +261,15 @@ func proposedNewNestedBlock(schema *configschema.NestedBlock, prior, config cty.
258261
}
259262

260263
func proposedNewAttributes(attrs map[string]*configschema.Attribute, prior, config cty.Value) map[string]cty.Value {
261-
if prior.IsNull() {
262-
prior = AllAttributesNull(attrs)
263-
}
264264
newAttrs := make(map[string]cty.Value, len(attrs))
265265
for name, attr := range attrs {
266-
priorV := prior.GetAttr(name)
266+
var priorV cty.Value
267+
if prior.IsNull() {
268+
priorV = cty.NullVal(prior.Type().AttributeType(name))
269+
} else {
270+
priorV = prior.GetAttr(name)
271+
}
272+
267273
configV := config.GetAttr(name)
268274
var newV cty.Value
269275
switch {

internal/plans/objchange/objchange_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,110 @@ func TestProposedNew(t *testing.T) {
15361536
}),
15371537
}),
15381538
},
1539+
"prior null nested objects": {
1540+
&configschema.Block{
1541+
Attributes: map[string]*configschema.Attribute{
1542+
"single": {
1543+
NestedType: &configschema.Object{
1544+
Nesting: configschema.NestingSingle,
1545+
Attributes: map[string]*configschema.Attribute{
1546+
"list": {
1547+
NestedType: &configschema.Object{
1548+
Nesting: configschema.NestingList,
1549+
Attributes: map[string]*configschema.Attribute{
1550+
"foo": {
1551+
Type: cty.String,
1552+
},
1553+
},
1554+
},
1555+
Optional: true,
1556+
},
1557+
},
1558+
},
1559+
Optional: true,
1560+
},
1561+
"map": {
1562+
NestedType: &configschema.Object{
1563+
Nesting: configschema.NestingMap,
1564+
Attributes: map[string]*configschema.Attribute{
1565+
"map": {
1566+
NestedType: &configschema.Object{
1567+
Nesting: configschema.NestingList,
1568+
Attributes: map[string]*configschema.Attribute{
1569+
"foo": {
1570+
Type: cty.String,
1571+
},
1572+
},
1573+
},
1574+
Optional: true,
1575+
},
1576+
},
1577+
},
1578+
Optional: true,
1579+
},
1580+
},
1581+
},
1582+
cty.NullVal(cty.Object(map[string]cty.Type{
1583+
"single": cty.Object(map[string]cty.Type{
1584+
"list": cty.List(cty.Object(map[string]cty.Type{
1585+
"foo": cty.String,
1586+
})),
1587+
}),
1588+
"map": cty.Map(cty.Object(map[string]cty.Type{
1589+
"list": cty.List(cty.Object(map[string]cty.Type{
1590+
"foo": cty.String,
1591+
})),
1592+
})),
1593+
})),
1594+
cty.ObjectVal(map[string]cty.Value{
1595+
"single": cty.ObjectVal(map[string]cty.Value{
1596+
"list": cty.ListVal([]cty.Value{
1597+
cty.ObjectVal(map[string]cty.Value{
1598+
"foo": cty.StringVal("a"),
1599+
}),
1600+
cty.ObjectVal(map[string]cty.Value{
1601+
"foo": cty.StringVal("b"),
1602+
}),
1603+
}),
1604+
}),
1605+
"map": cty.MapVal(map[string]cty.Value{
1606+
"one": cty.ObjectVal(map[string]cty.Value{
1607+
"list": cty.ListVal([]cty.Value{
1608+
cty.ObjectVal(map[string]cty.Value{
1609+
"foo": cty.StringVal("a"),
1610+
}),
1611+
cty.ObjectVal(map[string]cty.Value{
1612+
"foo": cty.StringVal("b"),
1613+
}),
1614+
}),
1615+
}),
1616+
}),
1617+
}),
1618+
cty.ObjectVal(map[string]cty.Value{
1619+
"single": cty.ObjectVal(map[string]cty.Value{
1620+
"list": cty.ListVal([]cty.Value{
1621+
cty.ObjectVal(map[string]cty.Value{
1622+
"foo": cty.StringVal("a"),
1623+
}),
1624+
cty.ObjectVal(map[string]cty.Value{
1625+
"foo": cty.StringVal("b"),
1626+
}),
1627+
}),
1628+
}),
1629+
"map": cty.MapVal(map[string]cty.Value{
1630+
"one": cty.ObjectVal(map[string]cty.Value{
1631+
"list": cty.ListVal([]cty.Value{
1632+
cty.ObjectVal(map[string]cty.Value{
1633+
"foo": cty.StringVal("a"),
1634+
}),
1635+
cty.ObjectVal(map[string]cty.Value{
1636+
"foo": cty.StringVal("b"),
1637+
}),
1638+
}),
1639+
}),
1640+
}),
1641+
}),
1642+
},
15391643
}
15401644

15411645
for name, test := range tests {

0 commit comments

Comments
 (0)