Add 'slice' interpolation function. (#9729)

This commit is contained in:
Kit Ewbank 2017-02-13 16:20:02 -05:00 committed by Paul Stack
parent 922eab8cfd
commit 549cff56d0
3 changed files with 101 additions and 1 deletions

View File

@ -85,6 +85,7 @@ func Funcs() map[string]ast.Function {
"sha1": interpolationFuncSha1(),
"sha256": interpolationFuncSha256(),
"signum": interpolationFuncSignum(),
"slice": interpolationFuncSlice(),
"sort": interpolationFuncSort(),
"split": interpolationFuncSplit(),
"timestamp": interpolationFuncTimestamp(),
@ -793,6 +794,42 @@ func interpolationFuncSignum() ast.Function {
}
}
// interpolationFuncSlice returns a portion of the input list between from, inclusive and to, exclusive.
func interpolationFuncSlice() ast.Function {
return ast.Function{
ArgTypes: []ast.Type{
ast.TypeList, // inputList
ast.TypeInt, // from
ast.TypeInt, // to
},
ReturnType: ast.TypeList,
Variadic: false,
Callback: func(args []interface{}) (interface{}, error) {
inputList := args[0].([]ast.Variable)
from := args[1].(int)
to := args[2].(int)
if from < 0 {
return nil, fmt.Errorf("from index must be >= 0")
}
if to > len(inputList) {
return nil, fmt.Errorf("to index must be <= length of the input list")
}
if from > to {
return nil, fmt.Errorf("from index must be <= to index")
}
var outputList []ast.Variable
for i, val := range inputList {
if i >= from && i < to {
outputList = append(outputList, val)
}
}
return outputList, nil
},
}
}
// interpolationFuncSort sorts a list of a strings lexographically
func interpolationFuncSort() ast.Function {
return ast.Function{

View File

@ -1330,6 +1330,66 @@ func TestInterpolateFuncSignum(t *testing.T) {
})
}
func TestInterpolateFuncSlice(t *testing.T) {
testFunction(t, testFunctionConfig{
Cases: []testFunctionCase{
// Negative from index
{
`${slice(list("a"), -1, 0)}`,
nil,
true,
},
// From index > to index
{
`${slice(list("a", "b", "c"), 2, 1)}`,
nil,
true,
},
// To index too large
{
`${slice(var.list_of_strings, 1, 4)}`,
nil,
true,
},
// Empty slice
{
`${slice(var.list_of_strings, 1, 1)}`,
[]interface{}{},
false,
},
{
`${slice(var.list_of_strings, 1, 2)}`,
[]interface{}{"b"},
false,
},
{
`${slice(var.list_of_strings, 0, length(var.list_of_strings) - 1)}`,
[]interface{}{"a", "b"},
false,
},
},
Vars: map[string]ast.Variable{
"var.list_of_strings": {
Type: ast.TypeList,
Value: []ast.Variable{
{
Type: ast.TypeString,
Value: "a",
},
{
Type: ast.TypeString,
Value: "b",
},
{
Type: ast.TypeString,
Value: "c",
},
},
},
},
})
}
func TestInterpolateFuncSort(t *testing.T) {
testFunction(t, testFunctionConfig{
Vars: map[string]ast.Variable{

View File

@ -296,7 +296,10 @@ The supported built-in functions are:
Example: `element(split(",", var.r53_failover_policy), signum(count.index))`
where the 0th index points to `PRIMARY` and 1st to `FAILOVER`
* `sort(list)` - Returns a lexicographically sorted list of the strings contained in
* `slice(list, from, to)` - Returns the portion of `list` between `from` (inclusive) and `to` (exclusive).
Example: `slice(var.list_of_strings, 0, length(var.list_of_strings) - 1)`
* `sort(list)` - Returns a lexographically sorted list of the strings contained in
the list passed as an argument. Sort may only be used with lists which contain only
strings.
Examples: `sort(aws_instance.foo.*.id)`, `sort(var.list_of_strings)`