diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index 9b26c24ff..bbe2b8434 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -24,6 +24,7 @@ func init() { "file": interpolationFuncFile(), "format": interpolationFuncFormat(), "formatlist": interpolationFuncFormatList(), + "index": interpolationFuncIndex(), "join": interpolationFuncJoin(), "length": interpolationFuncLength(), "replace": interpolationFuncReplace(), @@ -178,6 +179,25 @@ func interpolationFuncFormatList() ast.Function { } } +// interpolationFuncIndex implements the "index" function that allows one to +// find the index of a specific element in a list +func interpolationFuncIndex() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeString, ast.TypeString}, + ReturnType: ast.TypeInt, + Callback: func(args []interface{}) (interface{}, error) { + haystack := StringList(args[0].(string)).Slice() + needle := args[1].(string) + for index, element := range haystack { + if needle == element { + return index, nil + } + } + return nil, fmt.Errorf("Could not find '%s' in '%s'", needle, haystack) + }, + } +} + // 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 3258bda5c..05f84c201 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -206,6 +206,39 @@ func TestInterpolateFuncFormatList(t *testing.T) { }) } +func TestInterpolateFuncIndex(t *testing.T) { + testFunction(t, testFunctionConfig{ + Cases: []testFunctionCase{ + { + `${index("test", "")}`, + nil, + true, + }, + + { + fmt.Sprintf(`${index("%s", "foo")}`, + NewStringList([]string{"notfoo", "stillnotfoo", "bar"}).String()), + nil, + true, + }, + + { + fmt.Sprintf(`${index("%s", "foo")}`, + NewStringList([]string{"foo"}).String()), + "0", + false, + }, + + { + fmt.Sprintf(`${index("%s", "bar")}`, + NewStringList([]string{"foo", "spam", "bar", "eggs"}).String()), + "2", + false, + }, + }, + }) +} + func TestInterpolateFuncJoin(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 0d15cc9dd..f4730acd6 100644 --- a/website/source/docs/configuration/interpolation.html.md +++ b/website/source/docs/configuration/interpolation.html.md @@ -104,6 +104,9 @@ The supported built-in functions are: `formatlist("instance %v has private ip %v", aws_instance.foo.*.id, aws_instance.foo.*.private_ip)`. Passing lists with different lengths to formatlist results in an error. + * `index(list, elem)` - Finds the index of a given element in a list. Example: + `index(aws_instance.foo.*.tags.Name, "foo-test")` + * `join(delim, list)` - Joins the list with the delimiter. A list is only possible with splat variables from resources with a count greater than one. Example: `join(",", aws_instance.foo.*.id)`