lang/funcs: update lookup() to accept object-typed values for "map" arg

This commit is contained in:
Kristin Laemmert 2018-10-16 11:04:19 -07:00 committed by Martin Atkins
parent 5303137b8c
commit 46e168a682
2 changed files with 31 additions and 3 deletions

View File

@ -4,6 +4,7 @@ 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"
@ -478,7 +479,7 @@ var LookupFunc = function.New(&function.Spec{
Params: []function.Parameter{ Params: []function.Parameter{
{ {
Name: "inputMap", Name: "inputMap",
Type: cty.Map(cty.DynamicPseudoType), Type: cty.DynamicPseudoType,
}, },
{ {
Name: "key", Name: "key",
@ -496,8 +497,13 @@ 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()
return args[0].Type().ElementType(), nil switch {
case ty.IsObjectType():
return cty.DynamicPseudoType, nil
default:
return args[0].Type().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) {
var defaultVal cty.Value var defaultVal cty.Value
@ -515,6 +521,16 @@ var LookupFunc = function.New(&function.Spec{
return cty.UnknownVal(retType), nil return cty.UnknownVal(retType), nil
} }
if retType == cty.DynamicPseudoType {
// we're dealing with object-typed values
traversal := hcl.TraverseAttr{Name: args[1].AsString()}
ret, diags := traversal.TraversalStep(args[0])
if diags.HasErrors() {
return cty.UnknownVal(retType), diags
}
return ret, nil
}
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) {

View File

@ -1123,6 +1123,10 @@ func TestLookup(t *testing.T) {
"foo": cty.StringVal("bar"), "foo": cty.StringVal("bar"),
"baz": cty.UnknownVal(cty.String), "baz": cty.UnknownVal(cty.String),
}) })
mapWithObjects := cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("bar"),
"baz": cty.NumberIntVal(42),
})
tests := []struct { tests := []struct {
Values []cty.Value Values []cty.Value
@ -1137,6 +1141,14 @@ func TestLookup(t *testing.T) {
cty.StringVal("bar"), cty.StringVal("bar"),
false, false,
}, },
{
[]cty.Value{
mapWithObjects,
cty.StringVal("foo"),
},
cty.StringVal("bar"),
false,
},
{ {
[]cty.Value{ []cty.Value{
intsMap, intsMap,