mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-20 11:48:24 -06:00
config: new "transpose" interpolation function
This function takes a map of lists of strings and inverts it so that the string values become keys and the keys become items within the corresponding lists.
This commit is contained in:
parent
a28b5d295e
commit
550ae05819
@ -112,6 +112,7 @@ func Funcs() map[string]ast.Function {
|
||||
"substr": interpolationFuncSubstr(),
|
||||
"timestamp": interpolationFuncTimestamp(),
|
||||
"title": interpolationFuncTitle(),
|
||||
"transpose": interpolationFuncTranspose(),
|
||||
"trimspace": interpolationFuncTrimSpace(),
|
||||
"upper": interpolationFuncUpper(),
|
||||
"urlencode": interpolationFuncURLEncode(),
|
||||
@ -1548,6 +1549,53 @@ func interpolationFuncURLEncode() ast.Function {
|
||||
}
|
||||
}
|
||||
|
||||
// interpolationFuncTranspose implements the "transpose" function
|
||||
// that converts a map (string,list) to a map (string,list) where
|
||||
// the unique values of the original lists become the keys of the
|
||||
// new map and the keys of the original map become values for the
|
||||
// corresponding new keys.
|
||||
func interpolationFuncTranspose() ast.Function {
|
||||
return ast.Function{
|
||||
ArgTypes: []ast.Type{ast.TypeMap},
|
||||
ReturnType: ast.TypeMap,
|
||||
Callback: func(args []interface{}) (interface{}, error) {
|
||||
|
||||
inputMap := args[0].(map[string]ast.Variable)
|
||||
outputMap := make(map[string]ast.Variable)
|
||||
tmpMap := make(map[string][]string)
|
||||
|
||||
for inKey, inVal := range inputMap {
|
||||
if inVal.Type != ast.TypeList {
|
||||
return nil, fmt.Errorf("transpose requires a map of lists of strings")
|
||||
}
|
||||
values := inVal.Value.([]ast.Variable)
|
||||
for _, listVal := range values {
|
||||
if listVal.Type != ast.TypeString {
|
||||
return nil, fmt.Errorf("transpose requires the given map values to be lists of strings")
|
||||
}
|
||||
outKey := listVal.Value.(string)
|
||||
if _, ok := tmpMap[outKey]; !ok {
|
||||
tmpMap[outKey] = make([]string, 0)
|
||||
}
|
||||
outVal := tmpMap[outKey]
|
||||
outVal = append(outVal, inKey)
|
||||
sort.Strings(outVal)
|
||||
tmpMap[outKey] = outVal
|
||||
}
|
||||
}
|
||||
|
||||
for outKey, outVal := range tmpMap {
|
||||
values := make([]ast.Variable, 0)
|
||||
for _, v := range outVal {
|
||||
values = append(values, ast.Variable{Type: ast.TypeString, Value: v})
|
||||
}
|
||||
outputMap[outKey] = ast.Variable{Type: ast.TypeList, Value: values}
|
||||
}
|
||||
return outputMap, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// interpolationFuncAbs returns the absolute value of a given float.
|
||||
func interpolationFuncAbs() ast.Function {
|
||||
return ast.Function{
|
||||
|
@ -2615,6 +2615,82 @@ func TestInterpolateFuncURLEncode(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestInterpolateFuncTranspose(t *testing.T) {
|
||||
testFunction(t, testFunctionConfig{
|
||||
Vars: map[string]ast.Variable{
|
||||
"var.map": ast.Variable{
|
||||
Type: ast.TypeMap,
|
||||
Value: map[string]ast.Variable{
|
||||
"key1": ast.Variable{
|
||||
Type: ast.TypeList,
|
||||
Value: []ast.Variable{
|
||||
{Type: ast.TypeString, Value: "a"},
|
||||
{Type: ast.TypeString, Value: "b"},
|
||||
},
|
||||
},
|
||||
"key2": ast.Variable{
|
||||
Type: ast.TypeList,
|
||||
Value: []ast.Variable{
|
||||
{Type: ast.TypeString, Value: "a"},
|
||||
{Type: ast.TypeString, Value: "b"},
|
||||
{Type: ast.TypeString, Value: "c"},
|
||||
},
|
||||
},
|
||||
"key3": ast.Variable{
|
||||
Type: ast.TypeList,
|
||||
Value: []ast.Variable{
|
||||
{Type: ast.TypeString, Value: "c"},
|
||||
},
|
||||
},
|
||||
"key4": ast.Variable{
|
||||
Type: ast.TypeList,
|
||||
Value: []ast.Variable{},
|
||||
},
|
||||
}},
|
||||
"var.badmap": ast.Variable{
|
||||
Type: ast.TypeMap,
|
||||
Value: map[string]ast.Variable{
|
||||
"key1": ast.Variable{
|
||||
Type: ast.TypeList,
|
||||
Value: []ast.Variable{
|
||||
{Type: ast.TypeList, Value: []ast.Variable{}},
|
||||
{Type: ast.TypeList, Value: []ast.Variable{}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
"var.worsemap": ast.Variable{
|
||||
Type: ast.TypeMap,
|
||||
Value: map[string]ast.Variable{
|
||||
"key1": ast.Variable{
|
||||
Type: ast.TypeString,
|
||||
Value: "not-a-list",
|
||||
},
|
||||
}},
|
||||
},
|
||||
Cases: []testFunctionCase{
|
||||
{
|
||||
`${transpose(var.map)}`,
|
||||
map[string]interface{}{
|
||||
"a": []interface{}{"key1", "key2"},
|
||||
"b": []interface{}{"key1", "key2"},
|
||||
"c": []interface{}{"key2", "key3"},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
`${transpose(var.badmap)}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
`${transpose(var.worsemap)}`,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestInterpolateFuncAbs(t *testing.T) {
|
||||
testFunction(t, testFunctionConfig{
|
||||
Cases: []testFunctionCase{
|
||||
|
@ -392,6 +392,8 @@ The supported built-in functions are:
|
||||
|
||||
* `title(string)` - Returns a copy of the string with the first characters of all the words capitalized.
|
||||
|
||||
* `transpose(map)` - Swaps the keys and list values in a map of lists of strings. For example, transpose(map("a", list("1", "2"), "b", list("2", "3")) produces a value equivalent to map("1", list("a"), "2", list("a", "b"), "3", list("b")).
|
||||
|
||||
* `trimspace(string)` - Returns a copy of the string with all leading and trailing white spaces removed.
|
||||
|
||||
* `upper(string)` - Returns a copy of the string with all Unicode letters mapped to their upper case.
|
||||
|
Loading…
Reference in New Issue
Block a user