lang/funcs: return default value if provided when object lookup fails to find attr

This commit is contained in:
Kristin Laemmert 2018-10-16 12:09:04 -07:00 committed by Martin Atkins
parent 93630cf95f
commit d1d0ede069
2 changed files with 31 additions and 12 deletions

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/hashicorp/hcl2/hcl"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert" "github.com/zclconf/go-cty/cty/convert"
"github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function"
@ -497,12 +496,21 @@ var LookupFunc = function.New(&function.Spec{
if len(args) < 1 || len(args) > 3 { if len(args) < 1 || len(args) > 3 {
return cty.NilType, fmt.Errorf("lookup() takes two or three arguments, got %d", len(args)) return cty.NilType, fmt.Errorf("lookup() takes two or three arguments, got %d", len(args))
} }
ty := args[0].Type() ty := args[0].Type()
key := args[1].AsString()
switch { switch {
case ty.IsObjectType(): case ty.IsObjectType():
if ty.HasAttribute(key) {
return args[0].GetAttr(key).Type(), nil
} else if len(args) == 3 {
// if the key isn't found but a default is provided,
// return the default type
return args[2].Type(), nil
}
return cty.DynamicPseudoType, nil return cty.DynamicPseudoType, nil
default: default:
return args[0].Type().ElementType(), nil return ty.ElementType(), nil
} }
}, },
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
@ -521,17 +529,11 @@ var LookupFunc = function.New(&function.Spec{
return cty.UnknownVal(retType), nil return cty.UnknownVal(retType), nil
} }
if retType == cty.DynamicPseudoType { if mapVar.Type().IsObjectType() {
// we're dealing with object-typed values if mapVar.Type().HasAttribute(lookupKey) {
traversal := hcl.TraverseAttr{Name: args[1].AsString()} return mapVar.GetAttr(lookupKey), nil
ret, diags := traversal.TraversalStep(args[0])
if diags.HasErrors() {
return cty.UnknownVal(retType), diags
} }
return ret, nil } else if mapVar.HasIndex(cty.StringVal(lookupKey)) == cty.True {
}
if mapVar.HasIndex(cty.StringVal(lookupKey)) == cty.True {
v := mapVar.Index(cty.StringVal(lookupKey)) v := mapVar.Index(cty.StringVal(lookupKey))
if ty := v.Type(); !ty.Equals(cty.NilType) { if ty := v.Type(); !ty.Equals(cty.NilType) {
switch { switch {

View File

@ -1165,6 +1165,14 @@ func TestLookup(t *testing.T) {
cty.NilVal, cty.NilVal,
true, true,
}, },
{ // Invalid key
[]cty.Value{
mapWithObjects,
cty.StringVal("bar"),
},
cty.NilVal,
true,
},
{ // Supplied default with valid key { // Supplied default with valid key
[]cty.Value{ []cty.Value{
simpleMap, simpleMap,
@ -1183,6 +1191,15 @@ func TestLookup(t *testing.T) {
cty.StringVal("bar"), cty.StringVal("bar"),
false, false,
}, },
{ // Supplied default with valid key
[]cty.Value{
mapWithObjects,
cty.StringVal("foobar"),
cty.StringVal(""),
},
cty.StringVal(""),
false,
},
{ // Supplied default with invalid key { // Supplied default with invalid key
[]cty.Value{ []cty.Value{
simpleMap, simpleMap,