DEV Community

Cover image for How to use templates in Terraform
Dennis Groß (he/him)
Dennis Groß (he/him)

Posted on

How to use templates in Terraform

Terraform has a templatefile(path, vars) function that can be used to render the content of a file into a string with variable substitution.

Variable Substitution

The variable substitution has an interpolation syntax using ${..} . So you can reference variables that you passed into the second map argument of the templatefile function.

resource "aws_instance" "web_server" {
  ami           = data.aws_ami.amzn2.id
  instance_type = local.instance_type
  user_data     = templatefile("user-data.sh", {})
    ...
}
Enter fullscreen mode Exit fullscreen mode

The code above renders a shell script as a string without substituting any template variables.

The recommended file format is *.tftpl but the function does not enforce it.

We can pass additional variables from the terraform script to the user data example above.

resource "aws_instance" "web_server" {
  ami           = data.aws_ami.amzn2.id
  instance_type = local.instance_type
  user_data     = templatefile("user-data.sh", { log_group = "test-server" })
    ...
}
Enter fullscreen mode Exit fullscreen mode
#!/bin/bash
sudo chown $USER:$USER -R $cw_agent_config_folder
sudo mkdir -p $cw_agent_config_folder
sudo cat <<EOT >> $cw_agent_config_path
{
  "agent": {
    "metrics_collection_interval": $cw_agent_collection_interval,
    "run_as_user": "root"
  },
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "$http_access_logs",
            "log_group_name": "${log_group}",
            "log_stream_name": "{instance_id}-access-logs",
            "retention_in_days": $cw_agent_log_retention
          }
        ]
      }
    }
  },
  ...
}
EOT
sudo $cw_agent_ctl -a fetch-config -m ec2 -c file:$cw_agent_config_path -s
Enter fullscreen mode Exit fullscreen mode

The example above shows how you can work both with shell variables and template variables at the same time since the syntax that you use to reference them differs.

For Loop - Lists

Templates can also be used to dry up repeating sections.

This snippet prints “hello world” in 4 different variations.

resource "aws_instance" "web_server" {
  ...
  user_data     = templatefile("hello-world.tfpl", { names = [ "world", "planet" ] })
    ...
}
Enter fullscreen mode Exit fullscreen mode
#!/bin/bash
%{ for name in names }
echo "hello ${name}
%{ endfor ~}
Enter fullscreen mode Exit fullscreen mode

The snippets above render the hello-world.tfpl into a string that contains to echo statements.

echo "hello world"
echo "hello planet"
Enter fullscreen mode Exit fullscreen mode

It is important that we add a shebang into the shell script if we do not use the *.sh file ending (or comparable) but the *.tfpl file ending instead. The shebang instructs the script caller which binary must be invoked for the script execution.

For Loop - Maps

We can also loop through maps.

resource "aws_instance" "web_server" {
  ...
  user_data     = templatefile("hello-world.tfpl", { names = { "firstname": "Max", "lastname": "Fischer" })
    ...
}
Enter fullscreen mode Exit fullscreen mode
#!/bin/bash
%{ for config_key, config_value in names }
echo "hello to ${config_key}: ${config_value}"
%{ endfor ~}
Enter fullscreen mode Exit fullscreen mode

Results of this output

echo "hello to firstname Max"
echo "hello to lastname Fischer"
Enter fullscreen mode Exit fullscreen mode

Top comments (0)