From b5d12791077db79da92f977923c7d26b14c449e6 Mon Sep 17 00:00:00 2001 From: David Adams Date: Wed, 25 May 2016 19:25:15 -0500 Subject: [PATCH 1/2] Allow specifying a default value to lookup() Fixes #4474, where lookup() calls fail out the entire interpolation when the provided key value is not found in the map. This will allow using coalesce() along with lookup() to greatly improve module flexibility. --- config/interpolate_funcs.go | 25 ++++++++++++++++++++----- config/interpolate_funcs_test.go | 23 ++++++++++++++++++++++- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index 532dd50d1..4859624f7 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -548,17 +548,32 @@ func interpolationFuncSplit() ast.Function { // dynamic lookups of map types within a Terraform configuration. func interpolationFuncLookup(vs map[string]ast.Variable) ast.Function { return ast.Function{ - ArgTypes: []ast.Type{ast.TypeMap, ast.TypeString}, - ReturnType: ast.TypeString, + ArgTypes: []ast.Type{ast.TypeMap, ast.TypeString}, + ReturnType: ast.TypeString, + Variadic: true, + VariadicType: ast.TypeString, Callback: func(args []interface{}) (interface{}, error) { + defaultValue := "" + defaultValueSet := false + if len(args) > 2 { + defaultValue = args[2].(string) + defaultValueSet = true + } + if len(args) > 3 { + return "", fmt.Errorf("lookup() takes no more than three arguments") + } index := args[1].(string) mapVar := args[0].(map[string]ast.Variable) v, ok := mapVar[index] if !ok { - return "", fmt.Errorf( - "lookup failed to find '%s'", - args[1].(string)) + if defaultValueSet { + return defaultValue, nil + } else { + return "", fmt.Errorf( + "lookup failed to find '%s'", + args[1].(string)) + } } if v.Type != ast.TypeString { return "", fmt.Errorf( diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index 5b99281f5..da12c22f5 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -713,12 +713,33 @@ func TestInterpolateFuncLookup(t *testing.T) { true, }, + // Supplied default with valid key + { + `${lookup(var.foo, "bar", "")}`, + "baz", + false, + }, + + // Supplied default with invalid key + { + `${lookup(var.foo, "zip", "")}`, + "", + false, + }, + // Too many args { - `${lookup(var.foo, "bar", "baz")}`, + `${lookup(var.foo, "bar", "", "abc")}`, nil, true, }, + + // Non-empty default + { + `${lookup(var.foo, "zap", "xyz")}`, + "xyz", + false, + }, }, }) } From 8a4fdc3dd5e7aeca658833eed69c72be7a8c394c Mon Sep 17 00:00:00 2001 From: David Adams Date: Wed, 25 May 2016 19:35:09 -0500 Subject: [PATCH 2/2] Update docs for lookup() interpolation function Add specifics about using the optional third argument for providing a default value. --- website/source/docs/configuration/interpolation.html.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/website/source/docs/configuration/interpolation.html.md b/website/source/docs/configuration/interpolation.html.md index 85d2708eb..3b414db7b 100644 --- a/website/source/docs/configuration/interpolation.html.md +++ b/website/source/docs/configuration/interpolation.html.md @@ -160,9 +160,11 @@ The supported built-in functions are: * `${length(split(",", "a,b,c"))}` = 3 * `${length("a,b,c")}` = 5 - * `lookup(map, key)` - Performs a dynamic lookup into a mapping + * `lookup(map, key [, default])` - Performs a dynamic lookup into a mapping variable. The `map` parameter should be another variable, such - as `var.amis`. + as `var.amis`. If `key` does not exist in `map`, the interpolation will + fail unless you specify a third argument, `default`, which should be a + string value to return if no `key` is found in `map. * `lower(string)` - Returns a copy of the string with all Unicode letters mapped to their lower case.