core: Add zipmap interpolation function
This commit adds a new interpolation function, zipmap, which produces a map given a list of string keys and a list of values of the same length as the list of keys. The name comes from the same operation in Clojure (and likely other functional langauges).
This commit is contained in:
parent
fbcd1cff3f
commit
47bce79b29
|
@ -84,6 +84,7 @@ func Funcs() map[string]ast.Function {
|
||||||
"title": interpolationFuncTitle(),
|
"title": interpolationFuncTitle(),
|
||||||
"trimspace": interpolationFuncTrimSpace(),
|
"trimspace": interpolationFuncTrimSpace(),
|
||||||
"upper": interpolationFuncUpper(),
|
"upper": interpolationFuncUpper(),
|
||||||
|
"zipmap": interpolationFuncZipMap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +387,39 @@ func interpolationFuncFormat() ast.Function {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func interpolationFuncZipMap() ast.Function {
|
||||||
|
return ast.Function{
|
||||||
|
ArgTypes: []ast.Type{
|
||||||
|
ast.TypeList, // Keys
|
||||||
|
ast.TypeList, // Values
|
||||||
|
},
|
||||||
|
ReturnType: ast.TypeMap,
|
||||||
|
Callback: func(args []interface{}) (interface{}, error) {
|
||||||
|
keys := args[0].([]ast.Variable)
|
||||||
|
values := args[1].([]ast.Variable)
|
||||||
|
|
||||||
|
if len(keys) != len(values) {
|
||||||
|
return nil, fmt.Errorf("count of keys (%d) does not match count of values (%d)",
|
||||||
|
len(keys), len(values))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, val := range keys {
|
||||||
|
if val.Type != ast.TypeString {
|
||||||
|
return nil, fmt.Errorf("keys must be strings. value at position %d is %s",
|
||||||
|
i, val.Type.Printable())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]ast.Variable{}
|
||||||
|
for i := 0; i < len(keys); i++ {
|
||||||
|
result[keys[i].Value.(string)] = values[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// interpolationFuncFormatList implements the "formatlist" function that does
|
// interpolationFuncFormatList implements the "formatlist" function that does
|
||||||
// string formatting on lists.
|
// string formatting on lists.
|
||||||
func interpolationFuncFormatList() ast.Function {
|
func interpolationFuncFormatList() ast.Function {
|
||||||
|
|
|
@ -11,6 +11,115 @@ import (
|
||||||
"github.com/hashicorp/hil/ast"
|
"github.com/hashicorp/hil/ast"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestInterpolateFuncZipMap(t *testing.T) {
|
||||||
|
testFunction(t, testFunctionConfig{
|
||||||
|
Cases: []testFunctionCase{
|
||||||
|
{
|
||||||
|
`${zipmap(var.list, var.list2)}`,
|
||||||
|
map[string]interface{}{
|
||||||
|
"Hello": "bar",
|
||||||
|
"World": "baz",
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`${zipmap(var.list, var.nonstrings)}`,
|
||||||
|
map[string]interface{}{
|
||||||
|
"Hello": []interface{}{"bar", "baz"},
|
||||||
|
"World": []interface{}{"boo", "foo"},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`${zipmap(var.nonstrings, var.list2)}`,
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`${zipmap(var.list, var.differentlengthlist)}`,
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Vars: map[string]ast.Variable{
|
||||||
|
"var.list": {
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: []ast.Variable{
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "Hello",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "World",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"var.list2": {
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: []ast.Variable{
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "bar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "baz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"var.differentlengthlist": {
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: []ast.Variable{
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "bar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "baz",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "boo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"var.nonstrings": {
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: []ast.Variable{
|
||||||
|
{
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: []ast.Variable{
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "bar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "baz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: []ast.Variable{
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "boo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: ast.TypeString,
|
||||||
|
Value: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestInterpolateFuncList(t *testing.T) {
|
func TestInterpolateFuncList(t *testing.T) {
|
||||||
testFunction(t, testFunctionConfig{
|
testFunction(t, testFunctionConfig{
|
||||||
Cases: []testFunctionCase{
|
Cases: []testFunctionCase{
|
||||||
|
|
|
@ -252,6 +252,13 @@ The supported built-in functions are:
|
||||||
returned by the `keys` function. This function only works on flat maps and
|
returned by the `keys` function. This function only works on flat maps and
|
||||||
will return an error for maps that include nested lists or maps.
|
will return an error for maps that include nested lists or maps.
|
||||||
|
|
||||||
|
* `zipmap(list, list)` - Creates a map from a list of keys and a list of
|
||||||
|
values. The keys must all be of type string, and the length of the lists
|
||||||
|
must be the same.
|
||||||
|
For example, to output a mapping of AWS IAM user names to the fingerprint
|
||||||
|
of the key used to encrypt their initial password, you might use:
|
||||||
|
`zipmap(aws_iam_user.users.*.name, aws_iam_user_login_profile.users.*.key_fingerprint)`.
|
||||||
|
|
||||||
<a id="templates"></a>
|
<a id="templates"></a>
|
||||||
## Templates
|
## Templates
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue