diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index ad543c308..d9a357a1d 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -60,6 +60,7 @@ func Funcs() map[string]ast.Function { "cidrnetmask": interpolationFuncCidrNetmask(), "cidrsubnet": interpolationFuncCidrSubnet(), "coalesce": interpolationFuncCoalesce(), + "coalescelist": interpolationFuncCoalesceList(), "compact": interpolationFuncCompact(), "concat": interpolationFuncConcat(), "distinct": interpolationFuncDistinct(), @@ -318,6 +319,30 @@ func interpolationFuncCoalesce() ast.Function { } } +// interpolationFuncCoalesceList implements the "coalescelist" function that +// returns the first non empty list from the provided input +func interpolationFuncCoalesceList() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeList}, + ReturnType: ast.TypeList, + Variadic: true, + VariadicType: ast.TypeList, + Callback: func(args []interface{}) (interface{}, error) { + if len(args) < 2 { + return nil, fmt.Errorf("must provide at least two arguments") + } + for _, arg := range args { + argument := arg.([]ast.Variable) + + if len(argument) > 0 { + return argument, nil + } + } + return make([]ast.Variable, 0), nil + }, + } +} + // interpolationFuncConcat implements the "concat" function that concatenates // multiple lists. func interpolationFuncConcat() ast.Function { diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index 193fcd147..4f1c3fa0a 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -615,6 +615,33 @@ func TestInterpolateFuncCoalesce(t *testing.T) { }) } +func TestInterpolateFuncCoalesceList(t *testing.T) { + testFunction(t, testFunctionConfig{ + Cases: []testFunctionCase{ + { + `${coalescelist(list("first"), list("second"), list("third"))}`, + []interface{}{"first"}, + false, + }, + { + `${coalescelist(list(), list("second"), list("third"))}`, + []interface{}{"second"}, + false, + }, + { + `${coalescelist(list(), list(), list())}`, + []interface{}{}, + false, + }, + { + `${coalescelist(list("foo"))}`, + nil, + true, + }, + }, + }) +} + func TestInterpolateFuncConcat(t *testing.T) { testFunction(t, testFunctionConfig{ Cases: []testFunctionCase{ diff --git a/website/source/docs/configuration/interpolation.html.md b/website/source/docs/configuration/interpolation.html.md index 2d1e3052b..cb7ad8cfe 100644 --- a/website/source/docs/configuration/interpolation.html.md +++ b/website/source/docs/configuration/interpolation.html.md @@ -169,6 +169,9 @@ The supported built-in functions are: * `coalesce(string1, string2, ...)` - Returns the first non-empty value from the given arguments. At least two arguments must be provided. + * `coalescelist(list1, list2, ...)` - Returns the first non-empty list from + the given arguments. At least two arguments must be provided. + * `compact(list)` - Removes empty string elements from a list. This can be useful in some cases, for example when passing joined lists as module variables or when parsing module outputs.