config: Add "flatten" interpolation function

This function turns a list of lists or any arbitrary number of nested
lists into a flat list of primitive values.
This commit is contained in:
JWal31 2017-06-13 12:27:45 -07:00 committed by Martin Atkins
parent f1042a1338
commit 117f44bcda
3 changed files with 78 additions and 0 deletions

View File

@ -76,6 +76,7 @@ func Funcs() map[string]ast.Function {
"element": interpolationFuncElement(), "element": interpolationFuncElement(),
"file": interpolationFuncFile(), "file": interpolationFuncFile(),
"matchkeys": interpolationFuncMatchKeys(), "matchkeys": interpolationFuncMatchKeys(),
"flatten": interpolationFuncFlatten(),
"floor": interpolationFuncFloor(), "floor": interpolationFuncFloor(),
"format": interpolationFuncFormat(), "format": interpolationFuncFormat(),
"formatlist": interpolationFuncFormatList(), "formatlist": interpolationFuncFormatList(),
@ -1453,3 +1454,30 @@ func interpolationFuncSubstr() ast.Function {
}, },
} }
} }
// Flatten until it's not ast.TypeList
func flattener(finalList []ast.Variable, flattenList []ast.Variable) []ast.Variable {
for _, val := range flattenList {
if val.Type == ast.TypeList {
finalList = flattener(finalList, val.Value.([]ast.Variable))
} else {
finalList = append(finalList, val)
}
}
return finalList
}
// Flatten to single list
func interpolationFuncFlatten() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{ast.TypeList},
ReturnType: ast.TypeList,
Variadic: false,
Callback: func(args []interface{}) (interface{}, error) {
inputList := args[0].([]ast.Variable)
var outputList []ast.Variable
return flattener(outputList, inputList), nil
},
}
}

View File

@ -2503,3 +2503,49 @@ func TestInterpolateFuncBcrypt(t *testing.T) {
}, },
}) })
} }
func TestInterpolateFuncFlatten(t *testing.T) {
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
// empty string within array
{
`${flatten(split(",", "a,,b"))}`,
[]interface{}{"a", "", "b"},
false,
},
// typical array
{
`${flatten(split(",", "a,b,c"))}`,
[]interface{}{"a", "b", "c"},
false,
},
// empty array
{
`${flatten(split(",", ""))}`,
[]interface{}{""},
false,
},
// list of lists
{
`${flatten(list(list("a"), list("b")))}`,
[]interface{}{"a", "b"},
false,
},
// list of lists of lists
{
`${flatten(list(list("a"), list(list("b","c"))))}`,
[]interface{}{"a", "b", "c"},
false,
},
// list of strings
{
`${flatten(list("a", "b", "c"))}`,
[]interface{}{"a", "b", "c"},
false,
},
},
})
}

View File

@ -232,6 +232,10 @@ The supported built-in functions are:
* `floor(float)` - Returns the greatest integer value less than or equal to * `floor(float)` - Returns the greatest integer value less than or equal to
the argument. the argument.
* `flatten(list of lists)` - Flattens lists of lists down to a flat list of
primitive values, eliminating any nested lists recursively. Examples:
* `flatten(data.github_user.user.*.gpg_keys)`
* `format(format, args, ...)` - Formats a string according to the given * `format(format, args, ...)` - Formats a string according to the given
format. The syntax for the format is standard `sprintf` syntax. format. The syntax for the format is standard `sprintf` syntax.
Good documentation for the syntax can be [found here](https://golang.org/pkg/fmt/). Good documentation for the syntax can be [found here](https://golang.org/pkg/fmt/).