gomplate: Gomplate produce output file when parsing fails
Subject of the issue
gomplate
using an input template with reference to an environment variable that doesn’t exist, still writes an output file.
Your environment
- gomplate version 3.5.0
Steps to reproduce
$ gomplate -i 'fail: {{ .Env.BOGUS }}' -o fail.yml
template: <arg>:1:13: executing "<arg>" at <.Env.BOGUS>: map has no entry for key "BOGUS"
Expected behaviour
$ stat -f "%N" fail.yml
stat: fail.yml: stat: No such file or directory
$ test -f fail.yml || echo $?
1
Actual behaviour
$ stat -f "%N" fail.yml
fail.yml
$ test -f fail.yml && echo $?
0
About this issue
- Original URL
- State: open
- Created 5 years ago
- Comments: 16 (11 by maintainers)
I’m interested in this feature as well, for the same reasons others mentioned.
Buffering into memory is pretty common, even when piping. It all depends on the nature of the tool:
jq
will buffer in order to parse,sort
/uniq
/wc
must do the same (for obvious reasons), etc.gomplate
doing the same is fine, but I’m not so sure it should be the default behavior (an opt-in flag would be just as good, at least for me).Regarding the multiple input/output issue, I think the result should be consistent with multiple independent invocations of
gomplate
with a single input/output, as long as final exit status correctly reflects any intermediate failures.I was surprised by this behaviour. I’m using Gomplate to generate config files for services. If there is an error, Gomplate will clobber the (previously working) config file with an invalid one.
I expect instead - at least with a config option - that the content can be written to a temporary file and atomically renamed to the existing file to avoid such surprises.
I’d thought about that when I wrote that feature, and opted to ignore it at that point - but I’m definitely open to it! Can you open a separate issue for that? 🙂
Though I’m generally a fan of the Unix philosophy, I’ve never made any special effort to make gomplate with it… So any similarities are purely coincidental and unintentional 😉
What may be possible is a feature like the
GOMPLATE_SUPPRESS_EMPTY
one, where you could set an environment variable to change its behaviour to buffer rendering and not write to the output stream when errors are encountered. The challenge is what to do when outputting multiple files - I suppose it would have to output file-by-file…Or maybe the behaviour could be changed in the next major version of gomplate (v4) 🤔…
I’m going to re-open this since I’m now thinking this may be a good change in default behaviour, though until the next major release it would be opt-in. The tradeoff (slower time to any data being written) is probably worth it!
Hi @valepert, thanks for logging this, and sorry for the slow response - I’ve been on vacation 😉
This is the expected behaviour. Because the template is parsed and interpreted simultaneously, gomplate creates the output file before it starts to render the template.
Also, this is a useful behaviour when troubleshooting template errors, especially with larger templates, since the content that successfully rendered will all be present in the output.
One way to accomplish what you’re looking for is to delete the file on failure:
This way,
fail.yml
will never be present whengomplate
fails for any reason.A slightly different approach, without requiring a shell, would be to try to resolve environment variables up front, and then use the
GOMPLATE_SUPPRESS_EMPTY
environment variable to cause the output file to not be written on failures:This works because the template fails before any output has been rendered.
I’m going to close this issue now, since this is working as designed. Feel free to re-open though, if you feel strongly about this, or if the suggested workarounds don’t work 😉