core: New interpolation function "chunklist"
This turns a list into a list of lists with each element (apart from possibly the last) being the given length.
This commit is contained in:
parent
935890ec64
commit
ed9ba576e3
|
@ -79,6 +79,7 @@ func Funcs() map[string]ast.Function {
|
||||||
"dirname": interpolationFuncDirname(),
|
"dirname": interpolationFuncDirname(),
|
||||||
"distinct": interpolationFuncDistinct(),
|
"distinct": interpolationFuncDistinct(),
|
||||||
"element": interpolationFuncElement(),
|
"element": interpolationFuncElement(),
|
||||||
|
"chunklist": interpolationFuncChunklist(),
|
||||||
"file": interpolationFuncFile(),
|
"file": interpolationFuncFile(),
|
||||||
"matchkeys": interpolationFuncMatchKeys(),
|
"matchkeys": interpolationFuncMatchKeys(),
|
||||||
"flatten": interpolationFuncFlatten(),
|
"flatten": interpolationFuncFlatten(),
|
||||||
|
@ -1129,6 +1130,56 @@ func interpolationFuncElement() ast.Function {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns the `list` items chunked by `size`.
|
||||||
|
func interpolationFuncChunklist() ast.Function {
|
||||||
|
return ast.Function{
|
||||||
|
ArgTypes: []ast.Type{
|
||||||
|
ast.TypeList, // inputList
|
||||||
|
ast.TypeInt, // size
|
||||||
|
},
|
||||||
|
ReturnType: ast.TypeList,
|
||||||
|
Callback: func(args []interface{}) (interface{}, error) {
|
||||||
|
output := make([]ast.Variable, 0)
|
||||||
|
|
||||||
|
values, _ := args[0].([]ast.Variable)
|
||||||
|
size, _ := args[1].(int)
|
||||||
|
|
||||||
|
// errors if size is negative
|
||||||
|
if size < 0 {
|
||||||
|
return nil, fmt.Errorf("The size argument must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
// if size is 0, returns a list made of the initial list
|
||||||
|
if size == 0 {
|
||||||
|
output = append(output, ast.Variable{
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: values,
|
||||||
|
})
|
||||||
|
return output, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
variables := make([]ast.Variable, 0)
|
||||||
|
chunk := ast.Variable{
|
||||||
|
Type: ast.TypeList,
|
||||||
|
Value: variables,
|
||||||
|
}
|
||||||
|
l := len(values)
|
||||||
|
for i, v := range values {
|
||||||
|
variables = append(variables, v)
|
||||||
|
|
||||||
|
// Chunk when index isn't 0, or when reaching the values's length
|
||||||
|
if (i+1)%size == 0 || (i+1) == l {
|
||||||
|
chunk.Value = variables
|
||||||
|
output = append(output, chunk)
|
||||||
|
variables = make([]ast.Variable, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// interpolationFuncKeys implements the "keys" function that yields a list of
|
// interpolationFuncKeys implements the "keys" function that yields a list of
|
||||||
// keys of map types within a Terraform configuration.
|
// keys of map types within a Terraform configuration.
|
||||||
func interpolationFuncKeys(vs map[string]ast.Variable) ast.Function {
|
func interpolationFuncKeys(vs map[string]ast.Variable) ast.Function {
|
||||||
|
|
|
@ -2106,6 +2106,44 @@ func TestInterpolateFuncElement(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInterpolateFuncChunklist(t *testing.T) {
|
||||||
|
testFunction(t, testFunctionConfig{
|
||||||
|
Cases: []testFunctionCase{
|
||||||
|
// normal usage
|
||||||
|
{
|
||||||
|
`${chunklist(list("a", "b", "c"), 1)}`,
|
||||||
|
[]interface{}{
|
||||||
|
[]interface{}{"a"},
|
||||||
|
[]interface{}{"b"},
|
||||||
|
[]interface{}{"c"},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// `size` is pair and the list has an impair number of items
|
||||||
|
{
|
||||||
|
`${chunklist(list("a", "b", "c"), 2)}`,
|
||||||
|
[]interface{}{
|
||||||
|
[]interface{}{"a", "b"},
|
||||||
|
[]interface{}{"c"},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// list made of the same list, since size is 0
|
||||||
|
{
|
||||||
|
`${chunklist(list("a", "b", "c"), 0)}`,
|
||||||
|
[]interface{}{[]interface{}{"a", "b", "c"}},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// negative size of chunks
|
||||||
|
{
|
||||||
|
`${chunklist(list("a", "b", "c"), -1)}`,
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestInterpolateFuncBasename(t *testing.T) {
|
func TestInterpolateFuncBasename(t *testing.T) {
|
||||||
testFunction(t, testFunctionConfig{
|
testFunction(t, testFunctionConfig{
|
||||||
Cases: []testFunctionCase{
|
Cases: []testFunctionCase{
|
||||||
|
|
|
@ -230,6 +230,11 @@ The supported built-in functions are:
|
||||||
* `element(aws_subnet.foo.*.id, count.index)`
|
* `element(aws_subnet.foo.*.id, count.index)`
|
||||||
* `element(var.list_of_strings, 2)`
|
* `element(var.list_of_strings, 2)`
|
||||||
|
|
||||||
|
* `chunklist(list, size)` - Returns the `list` items chunked by `size`.
|
||||||
|
Examples:
|
||||||
|
* `list(aws_subnet.foo.*.id, 1)`: will outputs `[["id1"], ["id2"], ["id3"]]`
|
||||||
|
* `list(var.list_of_strings, 2)`: will outputs `[["id1", "id2"], ["id3", "id4"], ["id5"]`
|
||||||
|
|
||||||
* `file(path)` - Reads the contents of a file into the string. Variables
|
* `file(path)` - Reads the contents of a file into the string. Variables
|
||||||
in this file are _not_ interpolated. The contents of the file are
|
in this file are _not_ interpolated. The contents of the file are
|
||||||
read as-is. The `path` is interpreted relative to the working directory.
|
read as-is. The `path` is interpreted relative to the working directory.
|
||||||
|
|
Loading…
Reference in New Issue