Expand list interpolation to lists and maps
Allow lists and maps within the list interpolation function via variable interpolation. Since this requires setting the variadic type to TypeAny, we check for non-heterogeneous lists in the callback.
This commit is contained in:
parent
58dd41f3b1
commit
2bd7cfd5fe
|
@ -91,15 +91,34 @@ func interpolationFuncList() ast.Function {
|
|||
ArgTypes: []ast.Type{},
|
||||
ReturnType: ast.TypeList,
|
||||
Variadic: true,
|
||||
VariadicType: ast.TypeString,
|
||||
VariadicType: ast.TypeAny,
|
||||
Callback: func(args []interface{}) (interface{}, error) {
|
||||
var outputList []string
|
||||
var outputList []ast.Variable
|
||||
|
||||
for _, val := range args {
|
||||
outputList = append(outputList, val.(string))
|
||||
for i, val := range args {
|
||||
switch v := val.(type) {
|
||||
case string:
|
||||
outputList = append(outputList, ast.Variable{Type: ast.TypeString, Value: v})
|
||||
case []ast.Variable:
|
||||
outputList = append(outputList, ast.Variable{Type: ast.TypeList, Value: v})
|
||||
case map[string]ast.Variable:
|
||||
outputList = append(outputList, ast.Variable{Type: ast.TypeMap, Value: v})
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected type %T for argument %d in list", v, i)
|
||||
}
|
||||
}
|
||||
|
||||
return stringSliceToVariableValue(outputList), nil
|
||||
// we don't support heterogeneous types, so make sure all types match the first
|
||||
if len(outputList) > 0 {
|
||||
firstType := outputList[0].Type
|
||||
for i, v := range outputList[1:] {
|
||||
if v.Type != firstType {
|
||||
return nil, fmt.Errorf("unexpected type %s for argument %d in list", v.Type, i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputList, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,28 @@ func TestInterpolateFuncList(t *testing.T) {
|
|||
|
||||
// not a string input gives error
|
||||
{
|
||||
`${list("hello", "${var.list}")}`,
|
||||
`${list("hello", 42)}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
||||
// list of lists
|
||||
{
|
||||
`${list("${var.list}", "${var.list2}")}`,
|
||||
[]interface{}{[]interface{}{"Hello", "World"}, []interface{}{"bar", "baz"}},
|
||||
false,
|
||||
},
|
||||
|
||||
// list of maps
|
||||
{
|
||||
`${list("${var.map}", "${var.map2}")}`,
|
||||
[]interface{}{map[string]interface{}{"key": "bar"}, map[string]interface{}{"key2": "baz"}},
|
||||
false,
|
||||
},
|
||||
|
||||
// error on a heterogeneous list
|
||||
{
|
||||
`${list("first", "${var.list}")}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
|
@ -57,6 +78,38 @@ func TestInterpolateFuncList(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"var.list2": {
|
||||
Type: ast.TypeList,
|
||||
Value: []ast.Variable{
|
||||
{
|
||||
Type: ast.TypeString,
|
||||
Value: "bar",
|
||||
},
|
||||
{
|
||||
Type: ast.TypeString,
|
||||
Value: "baz",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"var.map": {
|
||||
Type: ast.TypeMap,
|
||||
Value: map[string]ast.Variable{
|
||||
"key": {
|
||||
Type: ast.TypeString,
|
||||
Value: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
"var.map2": {
|
||||
Type: ast.TypeMap,
|
||||
Value: map[string]ast.Variable{
|
||||
"key2": {
|
||||
Type: ast.TypeString,
|
||||
Value: "baz",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ The supported built-in functions are:
|
|||
This function provides a way of representing list literals in interpolation.
|
||||
* `${list("a", "b", "c")}` returns a list of `"a", "b", "c"`.
|
||||
* `${list()}` returns an empty list.
|
||||
|
||||
|
||||
* `lookup(map, key [, default])` - Performs a dynamic lookup into a mapping
|
||||
variable. The `map` parameter should be another variable, such
|
||||
as `var.amis`. If `key` does not exist in `map`, the interpolation will
|
||||
|
|
Loading…
Reference in New Issue