mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Create product interpolation function
This creates the product interpolation function that returns the cartesian product of a list of lists.
This commit is contained in:
parent
2bca828e46
commit
acd17d9075
@ -47,6 +47,20 @@ func stringSliceToVariableValue(values []string) []ast.Variable {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// listVariableSliceToVariableValue converts a list of lists into the value
|
||||||
|
// required to be returned from interpolation functions which return TypeList.
|
||||||
|
func listVariableSliceToVariableValue(values [][]ast.Variable) []ast.Variable {
|
||||||
|
output := make([]ast.Variable, len(values))
|
||||||
|
|
||||||
|
for index, value := range values {
|
||||||
|
output[index] = ast.Variable{
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
func listVariableValueToStringSlice(values []ast.Variable) ([]string, error) {
|
func listVariableValueToStringSlice(values []ast.Variable) ([]string, error) {
|
||||||
output := make([]string, len(values))
|
output := make([]string, len(values))
|
||||||
for index, value := range values {
|
for index, value := range values {
|
||||||
@ -104,6 +118,7 @@ func Funcs() map[string]ast.Function {
|
|||||||
"min": interpolationFuncMin(),
|
"min": interpolationFuncMin(),
|
||||||
"pathexpand": interpolationFuncPathExpand(),
|
"pathexpand": interpolationFuncPathExpand(),
|
||||||
"pow": interpolationFuncPow(),
|
"pow": interpolationFuncPow(),
|
||||||
|
"product": interpolationFuncProduct(),
|
||||||
"uuid": interpolationFuncUUID(),
|
"uuid": interpolationFuncUUID(),
|
||||||
"replace": interpolationFuncReplace(),
|
"replace": interpolationFuncReplace(),
|
||||||
"rsadecrypt": interpolationFuncRsaDecrypt(),
|
"rsadecrypt": interpolationFuncRsaDecrypt(),
|
||||||
@ -1725,3 +1740,55 @@ func interpolationFuncRsaDecrypt() ast.Function {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// interpolationFuncProduct implements the "product" function
|
||||||
|
// that returns the cartesian product of two or more lists
|
||||||
|
func interpolationFuncProduct() ast.Function {
|
||||||
|
return ast.Function{
|
||||||
|
ArgTypes: []ast.Type{ast.TypeList},
|
||||||
|
ReturnType: ast.TypeList,
|
||||||
|
Variadic: true,
|
||||||
|
VariadicType: ast.TypeList,
|
||||||
|
Callback: func(args []interface{}) (interface{}, error) {
|
||||||
|
if len(args) < 2 {
|
||||||
|
return nil, fmt.Errorf("must provide at least two arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
total := 1
|
||||||
|
for _, arg := range args {
|
||||||
|
total *= len(arg.([]ast.Variable))
|
||||||
|
}
|
||||||
|
|
||||||
|
if total == 0 {
|
||||||
|
return nil, fmt.Errorf("empty list provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
product := make([][]ast.Variable, total)
|
||||||
|
|
||||||
|
b := make([]ast.Variable, total*len(args))
|
||||||
|
n := make([]int, len(args))
|
||||||
|
s := 0
|
||||||
|
|
||||||
|
for i := range product {
|
||||||
|
e := s + len(args)
|
||||||
|
pi := b[s:e]
|
||||||
|
product[i] = pi
|
||||||
|
s = e
|
||||||
|
|
||||||
|
for j, n := range n {
|
||||||
|
pi[j] = args[j].([]ast.Variable)[n]
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := len(n) - 1; j >= 0; j-- {
|
||||||
|
n[j]++
|
||||||
|
if n[j] < len(args[j].([]ast.Variable)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
n[j] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listVariableSliceToVariableValue(product), nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2960,3 +2960,55 @@ H7CurtMwALQ/n/6LUKFmjRZjqbKX9SO2QSaC3grd6sY9Tu+bZjLe
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInterpolateFuncProduct(t *testing.T) {
|
||||||
|
testFunction(t, testFunctionConfig{
|
||||||
|
Cases: []testFunctionCase{
|
||||||
|
{
|
||||||
|
`${product(list("dev", "qas", "prd"), list("applicationA", "applicationB", "applicationC"))}`,
|
||||||
|
[]interface{}{
|
||||||
|
[]interface{}{"dev", "applicationA"},
|
||||||
|
[]interface{}{"dev", "applicationB"},
|
||||||
|
[]interface{}{"dev", "applicationC"},
|
||||||
|
[]interface{}{"qas", "applicationA"},
|
||||||
|
[]interface{}{"qas", "applicationB"},
|
||||||
|
[]interface{}{"qas", "applicationC"},
|
||||||
|
[]interface{}{"prd", "applicationA"},
|
||||||
|
[]interface{}{"prd", "applicationB"},
|
||||||
|
[]interface{}{"prd", "applicationC"}},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`${product(list("A", "B"), list("C", "D"), list("E", "F"))}`,
|
||||||
|
[]interface{}{
|
||||||
|
[]interface{}{"A", "C", "E"},
|
||||||
|
[]interface{}{"A", "C", "F"},
|
||||||
|
[]interface{}{"A", "D", "E"},
|
||||||
|
[]interface{}{"A", "D", "F"},
|
||||||
|
[]interface{}{"B", "C", "E"},
|
||||||
|
[]interface{}{"B", "C", "F"},
|
||||||
|
[]interface{}{"B", "D", "E"},
|
||||||
|
[]interface{}{"B", "D", "F"},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`${product(list(), list(), list())}`,
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`${product(list("foo"),list("bar"))}`,
|
||||||
|
[]interface{}{
|
||||||
|
[]interface{}{"foo", "bar"},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`${product(list("foo"))}`,
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user