Skip to content

Commit

Permalink
config: Add "flatten" interpolation function
Browse files Browse the repository at this point in the history
This function turns a list of lists or any arbitrary number of nested
lists into a flat list of primitive values.
  • Loading branch information
JWal31 authored and apparentlymart committed Aug 16, 2017
1 parent f1042a1 commit 117f44b
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
28 changes: 28 additions & 0 deletions config/interpolate_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func Funcs() map[string]ast.Function {
"element": interpolationFuncElement(),
"file": interpolationFuncFile(),
"matchkeys": interpolationFuncMatchKeys(),
"flatten": interpolationFuncFlatten(),
"floor": interpolationFuncFloor(),
"format": interpolationFuncFormat(),
"formatlist": interpolationFuncFormatList(),
Expand Down Expand Up @@ -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
},
}
}
46 changes: 46 additions & 0 deletions config/interpolate_funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
})
}
4 changes: 4 additions & 0 deletions website/docs/configuration/interpolation.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ The supported built-in functions are:
* `floor(float)` - Returns the greatest integer value less than or equal to
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. The syntax for the format is standard `sprintf` syntax.
Good documentation for the syntax can be [found here](https://golang.org/pkg/fmt/).
Expand Down

0 comments on commit 117f44b

Please sign in to comment.