From 26f5d6791453fbd06ca36f5b823d8ea1f987e45d Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Tue, 20 Oct 2015 09:06:52 -0400 Subject: [PATCH] Add uuid interpolation function --- config/interpolate_funcs.go | 24 +++++++++++ config/interpolate_funcs_test.go | 42 ++++++++++++++++++- .../docs/configuration/interpolation.html.md | 5 +++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index 5322e46c4f2b..9201f61a153b 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/hashicorp/terraform/config/lang/ast" + "github.com/hashicorp/terraform/helper/resource" "github.com/mitchellh/go-homedir" ) @@ -33,6 +34,7 @@ func init() { "split": interpolationFuncSplit(), "base64encode": interpolationFuncBase64Encode(), "base64decode": interpolationFuncBase64Decode(), + "uuid": interpolationFuncUuid(), } } @@ -442,3 +444,25 @@ func interpolationFuncBase64Decode() ast.Function { }, } } + +// interpolationFuncUuid implements an uuid v4 generator with an optional +// prefix string. Refer to pkg helper/resource/id for implementation details +// of the uuid generator. +func interpolationFuncUuid() ast.Function { + return ast.Function{ + Variadic: true, + VariadicType: ast.TypeString, + ReturnType: ast.TypeString, + Callback: func(args []interface{}) (interface{}, error) { + var prefix string + + if len(args) == 1 { + if v, ok := args[0].(string); ok { + prefix = v + } + } + + return resource.PrefixedUniqueId(prefix), nil + }, + } +} diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index cafdf05640d9..f4311b695c7e 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -6,7 +6,7 @@ import ( "os" "reflect" "testing" - + "strings" "github.com/hashicorp/terraform/config/lang" "github.com/hashicorp/terraform/config/lang/ast" ) @@ -644,6 +644,46 @@ func TestInterpolateFuncBase64Decode(t *testing.T) { }) } +func TestInterpolateUuid(t *testing.T) { + cases := []struct{ + Input string + Result int + Prefix string + Vars map[string]ast.Variable + }{ + {`${uuid()}`, 26, "", map[string]ast.Variable{}}, + {`${uuid("")}`, 26, "", map[string]ast.Variable{}}, + {`${uuid("lb-")}`, 29, "lb-", map[string]ast.Variable{}}, + } + + // defaults + for i, tc := range cases { + ast, err := lang.Parse(tc.Input) + if err != nil { + t.Fatalf("Case #%d: input: %#v\nerr: %s", i, tc.Input, err) + } + + out, _, err := lang.Eval(ast, langEvalConfig(tc.Vars)) + if err != nil { + t.Fatalf("Case #%d: input: %#v\nerr: %s", i, tc.Input, err) + } + + t.Logf("%s=%s", tc.Input, out) + + + if len(out.(string)) != tc.Result { + err = fmt.Errorf("expected input length (%d) to equal (%d)", len(out.(string)), tc.Result) + t.Fatalf("Case #%d: input: %#v\nerr: %s", i, tc.Input, err) + } + + if !strings.HasPrefix(out.(string), tc.Prefix) { + err = fmt.Errorf("expected prefix %s", tc.Prefix) + t.Fatalf("Case #%d: input: %#v\nerr: %s", i, tc.Input, err) + } + + } +} + type testFunctionConfig struct { Cases []testFunctionCase Vars map[string]ast.Variable diff --git a/website/source/docs/configuration/interpolation.html.md b/website/source/docs/configuration/interpolation.html.md index 28d03790d700..7b9f93d7704c 100644 --- a/website/source/docs/configuration/interpolation.html.md +++ b/website/source/docs/configuration/interpolation.html.md @@ -74,6 +74,11 @@ are documented below. The supported built-in functions are: + * `uuid(string)` - Returns a uuid string, with an optional prefix. This + uses a RFC 4122 v4 UUID with some basic cosmetic filters + applied (base32, remove padding, downcase) to make visually distinguishing + identifiers easier. This is the format used internally. + * `base64decode(string)` - Given a base64-encoded string, decodes it and returns the original string.