From bfbd00a23c9f4283a6945077bdd7bfc624796ca6 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Tue, 10 Dec 2019 14:40:12 -0800 Subject: [PATCH] website: Note about using jsonencode/yamlencode in templatefile It's a common source of errors to try to produce JSON or YAML syntax using string concatenation via our template language but to miss some details like correct string escaping, quoting, required commas, etc. The jsonencode and yamlencode functions are a better way to generate JSON and YAML, but it's not immediately obvious that both of these functions are available for use in external templates (via templatefile) too. Given that questions related to this come up a lot in our community forum and elsewhere, it seems worth having a documentation section to show the pattern of having a template that consists only of a single function call. --- .../functions/templatefile.html.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/website/docs/configuration/functions/templatefile.html.md b/website/docs/configuration/functions/templatefile.html.md index cfe5e347f..77cf80df8 100644 --- a/website/docs/configuration/functions/templatefile.html.md +++ b/website/docs/configuration/functions/templatefile.html.md @@ -64,6 +64,59 @@ backend 10.0.0.2:8080 ``` +### Generating JSON or YAML from a template + +If the string you want to generate will be in JSON or YAML syntax, it's +often tricky and tedious to write a template that will generate valid JSON or +YAML that will be interpreted correctly when using lots of individual +interpolation sequences and directives. + +Instead, you can write a template that consists only of a single interpolated +call to either [`jsonencode`](./jsonencode.html) or +[`yamlencode`](./yamlencode.html), specifying the value to encode using +[normal Terraform expression syntax](/docs/configuration/expressions.html) +as in the following examples: + +``` +${jsonencode({ + "backends": [for addr in ip_addrs : "${addr}:${port}"], +})} +``` + +``` +${yamlencode({ + "backends": [for addr in ip_addrs : "${addr}:${port}"], +})} +``` + +Given the same input as the `backends.tmpl` example in the previous section, +this will produce a valid JSON or YAML representation of the given data +structure, without the need to manually handle escaping or delimiters. +In the latest examples above, the repetition based on elements of `ip_addrs` is +achieved by using a +[`for` expression](/docs/configuration/expressions.html#for-expressions) +rather than by using +[template directives](/docs/configuration/expressions.html#directives). + +```json +{"backends":["10.0.0.1:8080","10.0.0.2:8080"]} +``` + +If the resulting template is small, you can choose instead to write +`jsonencode` or `yamlencode` calls inline in your main configuration files, and +avoid creating separate template files at all: + +```hcl +locals { + backend_config_json = jsonencode({ + "backends": [for addr in ip_addrs : "${addr}:${port}"], + }) +} +``` + +For more information, see the main documentation for +[`jsonencode`](./jsonencode.html) and [`yamlencode`](./yamlencode.html). + ## Related Functions * [`file`](./file.html) reads a file from disk and returns its literal contents