Skip to content

Commit 6ed7151

Browse files
authored
Merge pull request #37923 from hashicorp/jbardin/nesting-group-schema-fixes
fix handling of NestingGroup in the configschema package
2 parents 87b3390 + 07a7d50 commit 6ed7151

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

internal/configs/configschema/coerce_value.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
7373
return cty.UnknownVal(impliedType), path.NewErrorf("attribute %q has none of required, optional, or computed set", name)
7474
}
7575

76+
// check for NestingGroup which cannot be null
77+
if attrS.NestedType != nil && attrS.NestedType.Nesting == NestingGroup && val.IsNull() {
78+
// we can cheat here and use EmptyValue to get a "zero" value
79+
// object, and expect the conversion to turn out the correct final
80+
// object type
81+
val = cty.EmptyObjectVal
82+
}
83+
7684
val, err := convert.Convert(val, attrConvType)
7785
if err != nil {
7886
return cty.UnknownVal(impliedType), append(path, cty.GetAttrStep{Name: name}).NewError(err)

internal/configs/configschema/coerce_value_test.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,54 @@ func TestCoerceValue(t *testing.T) {
616616
}),
617617
``,
618618
},
619+
"nested type nulls": {
620+
// handle NestedTypes with null
621+
&Block{
622+
Attributes: map[string]*Attribute{
623+
"foo": {
624+
NestedType: &Object{
625+
Nesting: NestingSingle,
626+
Attributes: map[string]*Attribute{
627+
"bar": {Type: cty.DynamicPseudoType, Optional: true},
628+
"baz": {Type: cty.DynamicPseudoType, Optional: true},
629+
},
630+
},
631+
Optional: true,
632+
},
633+
"fob": {
634+
NestedType: &Object{
635+
Nesting: NestingGroup,
636+
Attributes: map[string]*Attribute{
637+
"bar": {Type: cty.DynamicPseudoType, Optional: true},
638+
"baz": {Type: cty.DynamicPseudoType, Computed: true},
639+
},
640+
},
641+
Optional: true,
642+
},
643+
},
644+
},
645+
cty.ObjectVal(map[string]cty.Value{
646+
"foo": cty.ObjectVal(map[string]cty.Value{
647+
"bar": cty.StringVal("test"),
648+
"baz": cty.NullVal(cty.Number),
649+
}),
650+
"fob": cty.ObjectVal(map[string]cty.Value{
651+
"bar": cty.NullVal(cty.String),
652+
"baz": cty.NullVal(cty.Number),
653+
}),
654+
}),
655+
cty.ObjectVal(map[string]cty.Value{
656+
"foo": cty.ObjectVal(map[string]cty.Value{
657+
"bar": cty.StringVal("test"),
658+
"baz": cty.NullVal(cty.Number),
659+
}),
660+
"fob": cty.ObjectVal(map[string]cty.Value{
661+
"bar": cty.NullVal(cty.String),
662+
"baz": cty.NullVal(cty.Number),
663+
}),
664+
}),
665+
``,
666+
},
619667
}
620668

621669
for name, test := range tests {
@@ -633,7 +681,6 @@ func TestCoerceValue(t *testing.T) {
633681
}
634682
return
635683
}
636-
637684
if !gotValue.RawEquals(test.WantValue) {
638685
t.Errorf("wrong result\ninput: %#v\ngot: %#v\nwant: %#v", test.Input, gotValue, test.WantValue)
639686
}

internal/configs/configschema/implied_type.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,9 @@ func (o *Object) specType() cty.Type {
138138
} else {
139139
ret = cty.Object(attrTys)
140140
}
141+
141142
switch o.Nesting {
142-
case NestingSingle:
143+
case NestingSingle, NestingGroup:
143144
return ret
144145
case NestingList:
145146
return cty.List(ret)

internal/configs/configschema/implied_type_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,25 @@ func TestObjectImpliedType(t *testing.T) {
316316
},
317317
),
318318
},
319+
"nesting-group-attributes": {
320+
&Object{
321+
Nesting: NestingGroup,
322+
Attributes: map[string]*Attribute{
323+
"optional": {Type: cty.String, Optional: true},
324+
"required": {Type: cty.Number, Required: true},
325+
"computed": {Type: cty.List(cty.Bool), Computed: true},
326+
"optional_computed": {Type: cty.Map(cty.Bool), Optional: true, Computed: true},
327+
},
328+
},
329+
cty.Object(
330+
map[string]cty.Type{
331+
"optional": cty.String,
332+
"required": cty.Number,
333+
"computed": cty.List(cty.Bool),
334+
"optional_computed": cty.Map(cty.Bool),
335+
},
336+
),
337+
},
319338
"nested attributes": {
320339
&Object{
321340
Nesting: NestingSingle,

0 commit comments

Comments
 (0)