How to use `templatefile` when writing terraform files in JSON

I am looking to grammatically create terraform files, and am therefore using the JSON Configuration syntax (JSON Configuration Syntax - Configuration Language | Terraform | HashiCorp Developer)

I was wondering how to express

resource “local_file” “user_data_json” {
count = 2
content = templatefile(“metadata_template.json”, {
SYSTEM_NAME = var.system_name
NODE_NAME = var.node_names[count.index]
NODE_ID = local.node_ids[count.index]
DNS_SERVERS = “{jsonencode(var.dns_servers)}" NTP_SERVERS = "{jsonencode(var.ntp_servers)}”
TIMEZONE = var.timezone
}
)
filename = local.userdata_files[count.index]
}

In the JSON format?

This does not work?

“resource”: {
“local_file”: {
“user_data_json”: {
“content”: “{templatefile(\"metadata_template.json\", {'NODE_ID': '{local.node_ids[count.index]}', ‘NODE_NAME’: '{var.node_names[count.index]}', 'LICENSE_KEY': {var.license}, ‘DNS_SERVERS’: ‘{jsonencode(var.management_dns_servers)}', 'NTP_SERVERS': '{jsonencode(var.ntp_servers)}’, ‘DCM_SERVERS’: '{jsonencode(var.dcm_ips)}', 'TIMEZONE': {var.timezone})}”,
“count”: 2,
“filename”: “${local.userdata_files[count.index]}”
}
}

i.e. “content”: ("${templatefile("metadata_template.json", FOO), where FOO is a JSON array.

I’m using Terraform v0.12.3

More generally is there a way to do from HCL terraform file to its JSON equivalent? A command-line tool would be very useful here.

Hi @andrew-lee-metaswitc,

Unfortunately the forum has interpreted parts of your configuration as TeX math because the configuration wasn’t in ``` delimiters, so I can’t see exactly what you tried here, but it should work to wrap your expression in ${} when you place it inside the JSON string:

{
  "example": "${jsonencode(var.dns_servers)}"
}

The JSON syntax has a special rule where if the entire string is covered by a single interpolation sequence ("${ to start and }" to end) then the result of the expression inside is used directly as the result, without first converting it to a string. In this case that special case wouldn’t matter anyway, because the result of jsonencode is a string, but that’s a good rule to keep in mind when generating Terraform configuration in JSON format.

There is not currently any automatic way to convert from native syntax to JSON syntax.

Ahh yes, bad block comments. To close the loop on this, I have worked out how to express

resource "local_file" "user_data_json" {
  count = 2
  content = templatefile("metadata_template.json", {
    SYSTEM_NAME                  = var.system_name
    NODE_NAME                    = var.node_names[count.index]
    NODE_ID                      = local.node_ids[count.index]
    DNS_SERVERS                  = "${jsonencode(var.dns_servers)}"
    NTP_SERVERS                  = "${jsonencode(var.ntp_servers)}"
    }
  )
  filename = "${var.node_names[count.index]}_userdata.json"
}

in JSON, it just involves lots of back slashes:

  "resource": {
    "local_file": {
      "user_data_json": {
        "content": "${templatefile(\"metadata_template.json\", {\"NODE_ID\": \"${local.node_ids[count.index]}\", \"NODE_NAME\": \"${var.node_names[count.index]}\", \"LICENSE_KEY\": \"${var.license}\", \"DNS_SERVERS\": \"${jsonencode(var.management_dns_servers)}\", \"NTP_SERVERS\": \"${jsonencode(var.ntp_servers)}\"})}",
        "count": 2,
        "filename": "${var.node_names[count.index]}_userdata.json"
      }
    },

So I’ve got what I wanted.

2 Likes