diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index 0160bef05f..f7fd057793 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -14,6 +14,7 @@ import ( "io/ioutil" "math" "net" + "net/url" "path/filepath" "regexp" "sort" @@ -111,6 +112,7 @@ func Funcs() map[string]ast.Function { "title": interpolationFuncTitle(), "trimspace": interpolationFuncTrimSpace(), "upper": interpolationFuncUpper(), + "urlencode": interpolationFuncURLEncode(), "zipmap": interpolationFuncZipMap(), } } @@ -1517,3 +1519,14 @@ func interpolationFuncFlatten() ast.Function { }, } } + +func interpolationFuncURLEncode() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeString}, + ReturnType: ast.TypeString, + Callback: func(args []interface{}) (interface{}, error) { + s := args[0].(string) + return url.QueryEscape(s), nil + }, + } +} diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index 2719f3fcae..603b49a2ac 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -2557,3 +2557,30 @@ func TestInterpolateFuncFlatten(t *testing.T) { }, }) } + +func TestInterpolateFuncURLEncode(t *testing.T) { + testFunction(t, testFunctionConfig{ + Cases: []testFunctionCase{ + { + `${urlencode("abc123-_")}`, + "abc123-_", + false, + }, + { + `${urlencode("foo:bar@localhost?foo=bar&bar=baz")}`, + "foo%3Abar%40localhost%3Ffoo%3Dbar%26bar%3Dbaz", + false, + }, + { + `${urlencode("mailto:email?subject=this+is+my+subject")}`, + "mailto%3Aemail%3Fsubject%3Dthis%2Bis%2Bmy%2Bsubject", + false, + }, + { + `${urlencode("foo/bar")}`, + "foo%2Fbar", + false, + }, + }, + }) +} diff --git a/website/docs/configuration/interpolation.html.md b/website/docs/configuration/interpolation.html.md index 12700b2d88..e092a4379d 100644 --- a/website/docs/configuration/interpolation.html.md +++ b/website/docs/configuration/interpolation.html.md @@ -386,6 +386,8 @@ The supported built-in functions are: * `upper(string)` - Returns a copy of the string with all Unicode letters mapped to their upper case. + * `urlencode(string)` - Returns an URL-safe copy of the string. + * `uuid()` - Returns a UUID string in RFC 4122 v4 format. This string will change with every invocation of the function, so in order to prevent diffs on every plan & apply, it must be used with the [`ignore_changes`](/docs/configuration/resources.html#ignore-changes) lifecycle attribute. * `values(map)` - Returns a list of the map values, in the order of the keys