diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index faa077ee3..6a2050c91 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -120,6 +120,7 @@ func Funcs() map[string]ast.Function { "pow": interpolationFuncPow(), "uuid": interpolationFuncUUID(), "replace": interpolationFuncReplace(), + "reverse": interpolationFuncReverse(), "rsadecrypt": interpolationFuncRsaDecrypt(), "sha1": interpolationFuncSha1(), "sha256": interpolationFuncSha256(), @@ -955,6 +956,25 @@ func interpolationFuncReplace() ast.Function { } } +// interpolationFuncReverse implements the "reverse" function that does list reversal +func interpolationFuncReverse() 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) + + reversedList := make([]ast.Variable, len(inputList)) + for idx := range inputList { + reversedList[len(inputList)-1-idx] = inputList[idx] + } + + return reversedList, nil + }, + } +} + func interpolationFuncLength() ast.Function { return ast.Function{ ArgTypes: []ast.Type{ast.TypeAny}, diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index f63d81c30..e883429e9 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -1546,6 +1546,39 @@ func TestInterpolateFuncReplace(t *testing.T) { }) } +func TestInterpolateFuncReverse(t *testing.T) { + testFunction(t, testFunctionConfig{ + Vars: map[string]ast.Variable{ + "var.inputlist": { + Type: ast.TypeList, + Value: []ast.Variable{ + {Type: ast.TypeString, Value: "a"}, + {Type: ast.TypeString, Value: "b"}, + {Type: ast.TypeString, Value: "1"}, + {Type: ast.TypeString, Value: "d"}, + }, + }, + "var.emptylist": { + Type: ast.TypeList, + // Intentionally 0-lengthed list + Value: []ast.Variable{}, + }, + }, + Cases: []testFunctionCase{ + { + `${reverse(var.inputlist)}`, + []interface{}{"d", "1", "b", "a"}, + false, + }, + { + `${reverse(var.emptylist)}`, + []interface{}{}, + false, + }, + }, + }) +} + func TestInterpolateFuncLength(t *testing.T) { testFunction(t, testFunctionConfig{ Cases: []testFunctionCase{