From 5a833fa1125ec8d18711fc911426f244a52adecd Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Mon, 22 Mar 2021 16:22:23 +0100 Subject: [PATCH] Add support for executing sub-templates Signed-off-by: Knut Ahlers --- README.md | 8 ++++++++ app.go | 8 +++++++- functions/func_test.go | 15 +++++++++++++++ functions/func_tplexec.go | 27 +++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 functions/func_tplexec.go diff --git a/README.md b/README.md index 160019f..1e766fd 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,14 @@ $ echo '{{ now "2006-01-02 15:04:05" }}' | korvike 2017-04-17 16:27:34 ``` +- `{{ tplexec (file "my.tpl") }}` + Execute the given template with the same function set and variables as the parent template. + ```console + $ export FOO=bar + $ echo '{{ env "FOO" }}' >my.tpl + $ echo '{{ tplexec (file "my.tpl") }}' | korvike + bar + ``` - `{{ vault [default value] }}` Read a key from Vault using `VAULT_ADDR` and `VAULT_TOKEN` environment variables (or `~/.vault-token` file) for authentication. ```console diff --git a/app.go b/app.go index 644ccec..c60368c 100644 --- a/app.go +++ b/app.go @@ -77,7 +77,13 @@ func main() { log.Fatalf("Unable to parse template: %s", err) } - if err := tpl.Execute(out, env.ListToMap(cfg.KeyPairs)); err != nil { + vars := map[string]interface{}{} + for k, v := range env.ListToMap(cfg.KeyPairs) { + vars[k] = v + } + + korvike.SetSubTemplateVariables(vars) + if err := tpl.Execute(out, vars); err != nil { log.Fatalf("Unable to execute template: %s", err) } } diff --git a/functions/func_test.go b/functions/func_test.go index 40ca439..fa722a0 100644 --- a/functions/func_test.go +++ b/functions/func_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "math/rand" "os" + "strings" "testing" "text/template" "time" @@ -17,6 +18,8 @@ func renderHelper(tpl string, ctx map[string]interface{}) string { panic(err) } + SetSubTemplateVariables(ctx) + buf := bytes.NewBufferString("") if err := t.Execute(buf, ctx); err != nil { panic(err) @@ -75,3 +78,15 @@ func Test_now(t *testing.T) { t.Errorf("[now] did not produce expected time format") } } + +func Test_tplexec(t *testing.T) { + result := randomString() + os.Setenv("KORVIKE_TESTING", result) + + if res := renderHelper(`{{ tplexec "{{ .var }}:{{ env \"KORVIKE_TESTING\" }}" }}`, map[string]interface{}{"var": "test"}); res != strings.Join([]string{ + "test", + result, + }, ":") { + t.Errorf("[template] did not produce expected result %q != test", res) + } +} diff --git a/functions/func_tplexec.go b/functions/func_tplexec.go new file mode 100644 index 0000000..b424307 --- /dev/null +++ b/functions/func_tplexec.go @@ -0,0 +1,27 @@ +package functions + +import ( + "bytes" + "fmt" + "text/template" +) + +var subTemplateVariables map[string]interface{} + +func SetSubTemplateVariables(m map[string]interface{}) { subTemplateVariables = m } + +func init() { + registerFunction("tplexec", func(rawTpl string) (string, error) { + tpl, err := template.New("in").Funcs(GetFunctionMap()).Parse(rawTpl) + if err != nil { + return "", fmt.Errorf("parse template: %w", err) + } + + out := new(bytes.Buffer) + if err := tpl.Execute(out, subTemplateVariables); err != nil { + return "", fmt.Errorf("execute template: %w", err) + } + + return out.String(), nil + }) +}