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
|
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:
|
default:
|
||||||
attrs[typeName] = cty.MapValEmpty(blockS.ImpliedType())
|
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 {
|
for name, test := range tests {
|
||||||
|
|
Loading…
Reference in New Issue