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", {})
...
}
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" })
...
}
#!/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
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" ] })
...
}
#!/bin/bash
%{ for name in names }
echo "hello ${name}
%{ endfor ~}
The snippets above render the hello-world.tfpl
into a string that contains to echo
statements.
echo "hello world"
echo "hello planet"
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" })
...
}
#!/bin/bash
%{ for config_key, config_value in names }
echo "hello to ${config_key}: ${config_value}"
%{ endfor ~}
Results of this output
echo "hello to firstname Max"
echo "hello to lastname Fischer"
Top comments (0)