mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
fix CoerceValue to handle changing dynamic types
Objects with DynamicPseudoType attributes can't be coerced within a map if a concrete type is set. Change the Value type used to an Object when there is a type mismatch.
This commit is contained in:
parent
e3618f915b
commit
c20164ab31
@ -225,7 +225,29 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
||||
elems[key.AsString()] = val
|
||||
}
|
||||
}
|
||||
attrs[typeName] = cty.MapVal(elems)
|
||||
|
||||
// If the attribute values here contain any DynamicPseudoTypes,
|
||||
// the concrete type must be an object.
|
||||
useObject := false
|
||||
switch {
|
||||
case coll.Type().IsObjectType():
|
||||
useObject = true
|
||||
default:
|
||||
// It's possible that we were given a map, and need to coerce it to an object
|
||||
ety := coll.Type().ElementType()
|
||||
for _, v := range elems {
|
||||
if !v.Type().Equals(ety) {
|
||||
useObject = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if useObject {
|
||||
attrs[typeName] = cty.ObjectVal(elems)
|
||||
} else {
|
||||
attrs[typeName] = cty.MapVal(elems)
|
||||
}
|
||||
default:
|
||||
attrs[typeName] = cty.MapValEmpty(blockS.ImpliedType())
|
||||
}
|
||||
|
@ -436,6 +436,101 @@ func TestCoerceValue(t *testing.T) {
|
||||
}),
|
||||
``,
|
||||
},
|
||||
"dynamic value attributes": {
|
||||
&Block{
|
||||
BlockTypes: map[string]*NestedBlock{
|
||||
"foo": {
|
||||
Nesting: NestingMap,
|
||||
Block: Block{
|
||||
Attributes: map[string]*Attribute{
|
||||
"bar": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"baz": {
|
||||
Type: cty.DynamicPseudoType,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.ObjectVal(map[string]cty.Value{
|
||||
"a": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("beep"),
|
||||
}),
|
||||
"b": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("boop"),
|
||||
"baz": cty.NumberIntVal(8),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.ObjectVal(map[string]cty.Value{
|
||||
"a": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("beep"),
|
||||
"baz": cty.NullVal(cty.DynamicPseudoType),
|
||||
}),
|
||||
"b": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("boop"),
|
||||
"baz": cty.NumberIntVal(8),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
``,
|
||||
},
|
||||
"dynamic attributes in map": {
|
||||
// Convert a block represented as a map to an object if a
|
||||
// DynamicPseudoType causes the element types to mismatch.
|
||||
&Block{
|
||||
BlockTypes: map[string]*NestedBlock{
|
||||
"foo": {
|
||||
Nesting: NestingMap,
|
||||
Block: Block{
|
||||
Attributes: map[string]*Attribute{
|
||||
"bar": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"baz": {
|
||||
Type: cty.DynamicPseudoType,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.MapVal(map[string]cty.Value{
|
||||
"a": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("beep"),
|
||||
}),
|
||||
"b": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("boop"),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.ObjectVal(map[string]cty.Value{
|
||||
"a": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("beep"),
|
||||
"baz": cty.NullVal(cty.DynamicPseudoType),
|
||||
}),
|
||||
"b": cty.ObjectVal(map[string]cty.Value{
|
||||
"bar": cty.StringVal("boop"),
|
||||
"baz": cty.NullVal(cty.DynamicPseudoType),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
``,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
|
Loading…
Reference in New Issue
Block a user