From df3e017f6cfe1aeba68a279e6fca379eaa7da4fa Mon Sep 17 00:00:00 2001 From: Jan Schumann Date: Fri, 10 Jun 2016 17:11:51 +0200 Subject: [PATCH] fix #7106 --- config/interpolate_funcs.go | 37 ++++++++++++++++++++++++++++++++ config/interpolate_funcs_test.go | 25 +++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index c48152648..4054e61f1 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -71,6 +71,7 @@ func Funcs() map[string]ast.Function { "lower": interpolationFuncLower(), "md5": interpolationFuncMd5(), "uuid": interpolationFuncUUID(), + "uniq": interpolationFuncUniq(), "replace": interpolationFuncReplace(), "sha1": interpolationFuncSha1(), "sha256": interpolationFuncSha256(), @@ -382,6 +383,42 @@ func interpolationFuncIndex() ast.Function { } } +// interpolationFuncUniq implements the "uniq" function that +// removes duplicate elements from a list. +func interpolationFuncUniq() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeList}, + ReturnType: ast.TypeList, + Variadic: true, + VariadicType: ast.TypeList, + Callback: func(args []interface{}) (interface{}, error) { + var list []string + + if len(args) != 1 { + return nil, fmt.Errorf("uniq() excepts only one argument.") + } + + if argument, ok := args[0].([]ast.Variable); ok { + for _, element := range argument { + list = appendIfMissing(list, element.Value.(string)) + } + } + + return stringSliceToVariableValue(list), nil + }, + } +} + +// helper function to add an element to a list, if it does not already exsit +func appendIfMissing(slice []string, element string) []string { + for _, ele := range slice { + if ele == element { + return slice + } + } + return append(slice, element) +} + // interpolationFuncJoin implements the "join" function that allows // multi-variable values to be joined by some character. func interpolationFuncJoin() ast.Function { diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index f4c527ebf..f6e05c82d 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -261,6 +261,31 @@ func TestInterpolationFuncConcatListOfMaps(t *testing.T) { } } +func TestInterpolateFuncUniq(t *testing.T) { + testFunction(t, testFunctionConfig{ + Cases: []testFunctionCase{ + // 3 duplicates + { + `${uniq(concat(split(",", "user1,user2,user3"), split(",", "user1,user2,user3")))}`, + []interface{}{"user1", "user2", "user3"}, + false, + }, + // 1 duplicate + { + `${uniq(concat(split(",", "user1,user2,user3"), split(",", "user1,user4")))}`, + []interface{}{"user1", "user2", "user3", "user4"}, + false, + }, + // too many args + { + `${uniq(concat(split(",", "user1,user2,user3"), split(",", "user1,user4")), "foo")}`, + nil, + true, + }, + }, + }) +} + func TestInterpolateFuncFile(t *testing.T) { tf, err := ioutil.TempFile("", "tf") if err != nil {