So I needed template executor for nginx configs that would go into production image.
I ended up writing this tool. It has zero dependencies. Output binary is around 2 MB.
Why not ...
envsubst- does simple substitution and does not support default values, conditions, or loopsgomplate- because it's too fat! Seriously, guys, 100 megs for a template renderer?!sed/awk- too much fuss
Tested with Go 1.10.7, 1.13, 1.16-1.19, 1.23.6
curl -L https://github.com/vegas503/temple/releases/latest/download/temple \
-o /usr/bin/temple && \
chmod +x /usr/bin/temple# Build with default flags (~3.8 MB):
go install github.com/vegas503/temple/cmd/temple@latest
# Build with flags to produce a smaller binary (~2.3 MB):
go install \
-trimpath \
-ldflags '-s -w' \
-gcflags=all='-B -l -wb=false' \
github.com/vegas503/temple/cmd/temple@latestAll the heavy lifting is done by Go's text/template package. Go see their docs first!
In addition to the built-ins, temple provides some additional functions for common scenarios.
Some functions (e. g. contains, split, join, and replace) have their arguments swapped.
This is done to make it easier to use function pipelines.
For instance, {{ $users := (split "," (env "USERS")) }} can be written as {{ $users := env "USERS" | split "," }}.
-
env(name: string) string- gets env var value, throws error if env var is not set$ echo '{{ env "USER" }}' | USER=skaarj temple skaarj
-
envdefault(name: string, def: string) string- gets env var value, returns default value if empty or unset$ echo '{{ envdefault "SOME_UNSET_VAR" "foo" }}' | temple foo
-
split(delim: string, s: string) []string- splits a string with a delimiter, trims whitespaces and returns array with all empty elements removed$ echo '{{ range $v := (split "," (env "ITEMS")) }}{{ $v }}{{ end }}' | ITEMS="A, B , C " temple ABC $ echo '{{ range $v := env "ITEMS" | split "," }}{{ $v }}{{ end }}' | ITEMS="A, B , C " temple ABC
-
contains(needle: string, s: string) bool- proxy for strings.Contains with arguments swapped -
join(glue: string, ss []string) string- proxy for strings.Join with arguments swapped -
coalesce(s string...) string- returns first non-empty string$ echo '{{ coalesce "" "two" "three" }}' | temple two
-
chain (ss ...[]string) []string- concatenates arrays$ cat temple.tpl {{- $colors := env "COLORS" | split "," }} {{- $numbers := env "NUMBERS" | split "," }} {{- range $item := (chain $colors $numbers) }} * {{ $item }} {{- end }} $ COLORS=red,green,blue NUMBERS=34,42 temple -i temple.tpl * red * green * blue * 34 * 42 -
uniq(ss []string) []string- returns array with all duplicate elements removed$ echo '{{ range $v := (uniq (split "," (env "COLORS"))) }}{{ $v }}{{ end }}' | COLORS=red,green,red temple redgreen $ echo '{{ range $v := env "COLORS" | split "," | uniq }}{{ $v }}{{ end }}' | COLORS=red,green,red temple redgreen
-
replace(from: string, to: string, s: string) string- proxy for strings.ReplaceAll but with source string as last argument -
upper(s: string) string- proxy for strings.ToUpper -
lower(s: string) string- proxy for strings.ToLower -
istrue(s: string) bool- returns true if string is non-empty and starts with "1", "t", "y" or "on".$ TPL='{{ if (istrue (env "FEATURE")) }}Enabled{{ else }}Disabled{{ end }}' $ echo "$TPL" | FEATURE=y temple Enabled $ echo "$TPL" | FEATURE=what temple Disabled
-
error(s: string)- prints error and exists with non-zero code$ echo '{{ error "Dafuq!" }}' | temple ERROR: Dafuq!