From aa9f9486a8dd00b59fdc91a9f7ccfc762683ac5e Mon Sep 17 00:00:00 2001 From: nitrocode Date: Wed, 12 May 2021 11:27:21 -0400 Subject: [PATCH] Add templatestring function --- lang/funcs/filesystem.go | 16 +++++++++++----- lang/funcs/filesystem_test.go | 2 +- lang/functions.go | 7 ++++++- lang/functions_test.go | 7 +++++++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lang/funcs/filesystem.go b/lang/funcs/filesystem.go index 1f00b50868fe..3efa82f83e4a 100644 --- a/lang/funcs/filesystem.go +++ b/lang/funcs/filesystem.go @@ -63,7 +63,7 @@ func MakeFileFunc(baseDir string, encBase64 bool) function.Function { // As a special exception, a referenced template file may not recursively call // the templatefile function, since that would risk the same file being // included into itself indefinitely. -func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Function) function.Function { +func MakeTemplateFileFunc(baseDir string, templateFile bool, funcsCb func() map[string]function.Function) function.Function { params := []function.Parameter{ { @@ -79,9 +79,15 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Fun loadTmpl := func(fn string) (hcl.Expression, error) { // We re-use File here to ensure the same filename interpretation // as it does, along with its other safety checks. - tmplVal, err := File(baseDir, cty.StringVal(fn)) - if err != nil { - return nil, err + var tmplVal cty.Value + if templateFile { + var err error + tmplVal, err = File(baseDir, cty.StringVal(fn)) + if err != nil { + return nil, err + } + } else { + tmplVal = cty.StringVal(fn) } expr, diags := hclsyntax.ParseTemplate([]byte(tmplVal.AsString()), fn, hcl.Pos{Line: 1, Column: 1}) @@ -128,7 +134,7 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Fun givenFuncs := funcsCb() // this callback indirection is to avoid chicken/egg problems funcs := make(map[string]function.Function, len(givenFuncs)) for name, fn := range givenFuncs { - if name == "templatefile" { + if name == "templatefile" || name == "templatestring" { // We stub this one out to prevent recursive calls. funcs[name] = function.New(&function.Spec{ Params: params, diff --git a/lang/funcs/filesystem_test.go b/lang/funcs/filesystem_test.go index b91b52b1ed1a..8ffac0c63130 100644 --- a/lang/funcs/filesystem_test.go +++ b/lang/funcs/filesystem_test.go @@ -157,7 +157,7 @@ func TestTemplateFile(t *testing.T) { }, } - templateFileFn := MakeTemplateFileFunc(".", func() map[string]function.Function { + templateFileFn := MakeTemplateFileFunc(".", true, func() map[string]function.Function { return map[string]function.Function{ "join": stdlib.JoinFunc, "templatefile": MakeFileFunc(".", false), // just a placeholder, since templatefile itself overrides this diff --git a/lang/functions.go b/lang/functions.go index 21be9a7f1013..d5a918a8ccfc 100644 --- a/lang/functions.go +++ b/lang/functions.go @@ -146,11 +146,16 @@ func (s *Scope) Functions() map[string]function.Function { "zipmap": stdlib.ZipmapFunc, } - s.funcs["templatefile"] = funcs.MakeTemplateFileFunc(s.BaseDir, func() map[string]function.Function { + s.funcs["templatefile"] = funcs.MakeTemplateFileFunc(s.BaseDir, true, func() map[string]function.Function { // The templatefile function prevents recursive calls to itself // by copying this map and overwriting the "templatefile" entry. return s.funcs }) + s.funcs["templatestring"] = funcs.MakeTemplateFileFunc(s.BaseDir, false, func() map[string]function.Function { + // The templatestring function prevents recursive calls to itself + // by copying this map and overwriting the "templatestring" entry. + return s.funcs + }) if s.ConsoleMode { // The type function is only available in terraform console. diff --git a/lang/functions_test.go b/lang/functions_test.go index c33bc3672a10..b504459b365d 100644 --- a/lang/functions_test.go +++ b/lang/functions_test.go @@ -869,6 +869,13 @@ func TestFunctions(t *testing.T) { }, }, + "templatestring": { + { + `templatestring("Hello, $${name}!", {name = "Jodie"})`, + cty.StringVal("Hello, Jodie!"), + }, + }, + "timeadd": { { `timeadd("2017-11-22T00:00:00Z", "1s")`,