Merge pull request #27979 from hashicorp/alisdair/defaults-fixes
functions: Fix panics in defaults
This commit is contained in:
commit
98899df514
|
@ -127,10 +127,12 @@ func defaultsApply(input, fallback cty.Value) cty.Value {
|
||||||
case wantTy.IsMapType():
|
case wantTy.IsMapType():
|
||||||
newVals := map[string]cty.Value{}
|
newVals := map[string]cty.Value{}
|
||||||
|
|
||||||
|
if !input.IsNull() {
|
||||||
for it := input.ElementIterator(); it.Next(); {
|
for it := input.ElementIterator(); it.Next(); {
|
||||||
k, v := it.Element()
|
k, v := it.Element()
|
||||||
newVals[k.AsString()] = defaultsApply(v, fallback)
|
newVals[k.AsString()] = defaultsApply(v, fallback)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(newVals) == 0 {
|
if len(newVals) == 0 {
|
||||||
return cty.MapValEmpty(ety)
|
return cty.MapValEmpty(ety)
|
||||||
|
@ -139,11 +141,13 @@ func defaultsApply(input, fallback cty.Value) cty.Value {
|
||||||
case wantTy.IsListType(), wantTy.IsSetType():
|
case wantTy.IsListType(), wantTy.IsSetType():
|
||||||
var newVals []cty.Value
|
var newVals []cty.Value
|
||||||
|
|
||||||
|
if !input.IsNull() {
|
||||||
for it := input.ElementIterator(); it.Next(); {
|
for it := input.ElementIterator(); it.Next(); {
|
||||||
_, v := it.Element()
|
_, v := it.Element()
|
||||||
newV := defaultsApply(v, fallback)
|
newV := defaultsApply(v, fallback)
|
||||||
newVals = append(newVals, newV)
|
newVals = append(newVals, newV)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(newVals) == 0 {
|
if len(newVals) == 0 {
|
||||||
if wantTy.IsSetType() {
|
if wantTy.IsSetType() {
|
||||||
|
@ -183,7 +187,7 @@ func defaultsAssertSuitableFallback(wantTy, fallbackTy cty.Type, fallbackPath ct
|
||||||
if fallbackTy.Equals(wantTy) {
|
if fallbackTy.Equals(wantTy) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
conversion := convert.GetConversionUnsafe(fallbackTy, wantTy)
|
conversion := convert.GetConversion(fallbackTy, wantTy)
|
||||||
if conversion == nil {
|
if conversion == nil {
|
||||||
msg := convert.MismatchMessage(fallbackTy, wantTy)
|
msg := convert.MismatchMessage(fallbackTy, wantTy)
|
||||||
return fallbackPath.NewErrorf("invalid default value for %s: %s", wantTy.FriendlyName(), msg)
|
return fallbackPath.NewErrorf("invalid default value for %s: %s", wantTy.FriendlyName(), msg)
|
||||||
|
|
|
@ -370,6 +370,57 @@ func TestDefaults(t *testing.T) {
|
||||||
Defaults: cty.StringVal("hello"),
|
Defaults: cty.StringVal("hello"),
|
||||||
WantErr: `only object types and collections of object types can have defaults applied`,
|
WantErr: `only object types and collections of object types can have defaults applied`,
|
||||||
},
|
},
|
||||||
|
// When applying default values to collection types, null collections in the
|
||||||
|
// input should result in empty collections in the output.
|
||||||
|
{
|
||||||
|
Input: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.NullVal(cty.List(cty.String)),
|
||||||
|
"b": cty.NullVal(cty.Map(cty.String)),
|
||||||
|
"c": cty.NullVal(cty.Set(cty.String)),
|
||||||
|
}),
|
||||||
|
Defaults: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.StringVal("hello"),
|
||||||
|
"b": cty.StringVal("hi"),
|
||||||
|
"c": cty.StringVal("greetings"),
|
||||||
|
}),
|
||||||
|
Want: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.ListValEmpty(cty.String),
|
||||||
|
"b": cty.MapValEmpty(cty.String),
|
||||||
|
"c": cty.SetValEmpty(cty.String),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
// When specifying fallbacks, we allow mismatched primitive attribute
|
||||||
|
// types so long as a safe conversion is possible. This means that we
|
||||||
|
// can accept number or boolean values for string attributes.
|
||||||
|
{
|
||||||
|
Input: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.NullVal(cty.String),
|
||||||
|
"b": cty.NullVal(cty.String),
|
||||||
|
"c": cty.NullVal(cty.String),
|
||||||
|
}),
|
||||||
|
Defaults: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.NumberIntVal(5),
|
||||||
|
"b": cty.True,
|
||||||
|
"c": cty.StringVal("greetings"),
|
||||||
|
}),
|
||||||
|
Want: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.StringVal("5"),
|
||||||
|
"b": cty.StringVal("true"),
|
||||||
|
"c": cty.StringVal("greetings"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
// Fallbacks with mismatched primitive attribute types which do not
|
||||||
|
// have safe conversions must not pass the suitable fallback check,
|
||||||
|
// even if unsafe conversion would be possible.
|
||||||
|
{
|
||||||
|
Input: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.NullVal(cty.Bool),
|
||||||
|
}),
|
||||||
|
Defaults: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.StringVal("5"),
|
||||||
|
}),
|
||||||
|
WantErr: ".a: invalid default value for bool: bool required",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
Loading…
Reference in New Issue