mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
handle NestedTypes in Block.CoerceValue
The CoerceValue code was not updated to handle NestedTypes, and while none of the new codepaths make use of this method, there are still some internal uses.
This commit is contained in:
parent
332ea1f233
commit
9029870613
@ -27,16 +27,19 @@ func (b *Block) CoerceValue(in cty.Value) (cty.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
||||||
|
convType := b.specType()
|
||||||
|
impliedType := convType.WithoutOptionalAttributesDeep()
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case in.IsNull():
|
case in.IsNull():
|
||||||
return cty.NullVal(b.ImpliedType()), nil
|
return cty.NullVal(impliedType), nil
|
||||||
case !in.IsKnown():
|
case !in.IsKnown():
|
||||||
return cty.UnknownVal(b.ImpliedType()), nil
|
return cty.UnknownVal(impliedType), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ty := in.Type()
|
ty := in.Type()
|
||||||
if !ty.IsObjectType() {
|
if !ty.IsObjectType() {
|
||||||
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("an object is required")
|
return cty.UnknownVal(impliedType), path.NewErrorf("an object is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
for name := range ty.AttributeTypes() {
|
for name := range ty.AttributeTypes() {
|
||||||
@ -46,29 +49,32 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
if _, defined := b.BlockTypes[name]; defined {
|
if _, defined := b.BlockTypes[name]; defined {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("unexpected attribute %q", name)
|
return cty.UnknownVal(impliedType), path.NewErrorf("unexpected attribute %q", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs := make(map[string]cty.Value)
|
attrs := make(map[string]cty.Value)
|
||||||
|
|
||||||
for name, attrS := range b.Attributes {
|
for name, attrS := range b.Attributes {
|
||||||
|
attrType := impliedType.AttributeType(name)
|
||||||
|
attrConvType := convType.AttributeType(name)
|
||||||
|
|
||||||
var val cty.Value
|
var val cty.Value
|
||||||
switch {
|
switch {
|
||||||
case ty.HasAttribute(name):
|
case ty.HasAttribute(name):
|
||||||
val = in.GetAttr(name)
|
val = in.GetAttr(name)
|
||||||
case attrS.Computed || attrS.Optional:
|
case attrS.Computed || attrS.Optional:
|
||||||
val = cty.NullVal(attrS.Type)
|
val = cty.NullVal(attrType)
|
||||||
default:
|
default:
|
||||||
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("attribute %q is required", name)
|
return cty.UnknownVal(impliedType), path.NewErrorf("attribute %q is required", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
val, err := attrS.coerceValue(val, append(path, cty.GetAttrStep{Name: name}))
|
val, err := convert.Convert(val, attrConvType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cty.UnknownVal(b.ImpliedType()), err
|
return cty.UnknownVal(impliedType), append(path, cty.GetAttrStep{Name: name}).NewError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs[name] = val
|
attrs[name] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
for typeName, blockS := range b.BlockTypes {
|
for typeName, blockS := range b.BlockTypes {
|
||||||
switch blockS.Nesting {
|
switch blockS.Nesting {
|
||||||
|
|
||||||
@ -79,7 +85,7 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
val := in.GetAttr(typeName)
|
val := in.GetAttr(typeName)
|
||||||
attrs[typeName], err = blockS.coerceValue(val, append(path, cty.GetAttrStep{Name: typeName}))
|
attrs[typeName], err = blockS.coerceValue(val, append(path, cty.GetAttrStep{Name: typeName}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cty.UnknownVal(b.ImpliedType()), err
|
return cty.UnknownVal(impliedType), err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
attrs[typeName] = blockS.EmptyValue()
|
attrs[typeName] = blockS.EmptyValue()
|
||||||
@ -100,7 +106,7 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !coll.CanIterateElements() {
|
if !coll.CanIterateElements() {
|
||||||
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("must be a list")
|
return cty.UnknownVal(impliedType), path.NewErrorf("must be a list")
|
||||||
}
|
}
|
||||||
l := coll.LengthInt()
|
l := coll.LengthInt()
|
||||||
|
|
||||||
@ -116,7 +122,7 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
idx, val := it.Element()
|
idx, val := it.Element()
|
||||||
val, err = blockS.coerceValue(val, append(path, cty.IndexStep{Key: idx}))
|
val, err = blockS.coerceValue(val, append(path, cty.IndexStep{Key: idx}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cty.UnknownVal(b.ImpliedType()), err
|
return cty.UnknownVal(impliedType), err
|
||||||
}
|
}
|
||||||
elems = append(elems, val)
|
elems = append(elems, val)
|
||||||
}
|
}
|
||||||
@ -141,7 +147,7 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !coll.CanIterateElements() {
|
if !coll.CanIterateElements() {
|
||||||
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("must be a set")
|
return cty.UnknownVal(impliedType), path.NewErrorf("must be a set")
|
||||||
}
|
}
|
||||||
l := coll.LengthInt()
|
l := coll.LengthInt()
|
||||||
|
|
||||||
@ -157,7 +163,7 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
idx, val := it.Element()
|
idx, val := it.Element()
|
||||||
val, err = blockS.coerceValue(val, append(path, cty.IndexStep{Key: idx}))
|
val, err = blockS.coerceValue(val, append(path, cty.IndexStep{Key: idx}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cty.UnknownVal(b.ImpliedType()), err
|
return cty.UnknownVal(impliedType), err
|
||||||
}
|
}
|
||||||
elems = append(elems, val)
|
elems = append(elems, val)
|
||||||
}
|
}
|
||||||
@ -182,7 +188,7 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !coll.CanIterateElements() {
|
if !coll.CanIterateElements() {
|
||||||
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("must be a map")
|
return cty.UnknownVal(impliedType), path.NewErrorf("must be a map")
|
||||||
}
|
}
|
||||||
l := coll.LengthInt()
|
l := coll.LengthInt()
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
@ -196,11 +202,11 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
var err error
|
var err error
|
||||||
key, val := it.Element()
|
key, val := it.Element()
|
||||||
if key.Type() != cty.String || key.IsNull() || !key.IsKnown() {
|
if key.Type() != cty.String || key.IsNull() || !key.IsKnown() {
|
||||||
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("must be a map")
|
return cty.UnknownVal(impliedType), path.NewErrorf("must be a map")
|
||||||
}
|
}
|
||||||
val, err = blockS.coerceValue(val, append(path, cty.IndexStep{Key: key}))
|
val, err = blockS.coerceValue(val, append(path, cty.IndexStep{Key: key}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cty.UnknownVal(b.ImpliedType()), err
|
return cty.UnknownVal(impliedType), err
|
||||||
}
|
}
|
||||||
elems[key.AsString()] = val
|
elems[key.AsString()] = val
|
||||||
}
|
}
|
||||||
@ -240,11 +246,3 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|||||||
|
|
||||||
return cty.ObjectVal(attrs), nil
|
return cty.ObjectVal(attrs), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Attribute) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
|
|
||||||
val, err := convert.Convert(in, a.Type)
|
|
||||||
if err != nil {
|
|
||||||
return cty.UnknownVal(a.Type), path.NewError(err)
|
|
||||||
}
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
@ -538,6 +538,67 @@ func TestCoerceValue(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
``,
|
``,
|
||||||
},
|
},
|
||||||
|
"nested types": {
|
||||||
|
// handle NestedTypes
|
||||||
|
&Block{
|
||||||
|
Attributes: map[string]*Attribute{
|
||||||
|
"foo": {
|
||||||
|
NestedType: &Object{
|
||||||
|
Nesting: NestingList,
|
||||||
|
Attributes: map[string]*Attribute{
|
||||||
|
"bar": {
|
||||||
|
Type: cty.String,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"baz": {
|
||||||
|
Type: cty.Map(cty.String),
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"fob": {
|
||||||
|
NestedType: &Object{
|
||||||
|
Nesting: NestingSet,
|
||||||
|
Attributes: map[string]*Attribute{
|
||||||
|
"bar": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.ListVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.StringVal("beep"),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.StringVal("boop"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.ListVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.StringVal("beep"),
|
||||||
|
"baz": cty.NullVal(cty.Map(cty.String)),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.StringVal("boop"),
|
||||||
|
"baz": cty.NullVal(cty.Map(cty.String)),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
"fob": cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{
|
||||||
|
"bar": cty.String,
|
||||||
|
}))),
|
||||||
|
}),
|
||||||
|
``,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, test := range tests {
|
for name, test := range tests {
|
||||||
|
Loading…
Reference in New Issue
Block a user