Merge pull request #9627 from hashicorp/f-format-map
core: Add zipmap interpolation function
This commit is contained in:
commit
9eb5c69849
|
@ -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