I need to generate a shell script on a remote node that references terraform variables and shell variables within the script. I know that I can use $ to escape, however, when using a cat heredoc method in the inline, something like $$var1 will be empty.
I need to reference the instance local dns and ip address in the configuration. When the count > 1, I cannot reference the instance output (i.e. "${aws_instance.example.private_ip}").
0.6.15
resource "template_file" "example" {
template = "${file("${path.module}/example.sh.tpl")}"
vars {
name = "${var.name}"
}
}
resource "aws_instance" "test" {
provisioner "remote-exec" {
inline = [
"cat <<EOF > example.sh",
"${template_file.example.rendered}",
"EOF"
]
}
}
# example.sh.tpl
var1="$$(some linux command)"
cat <<TMP > somefile
$$var1
TMP
When example.sh is written to the remote instance, $$var1 should be $var1 however it is empty. I am generating two files because I need to reference the instance private ip in a file. When the file is generated, the first line will not show the command, but will show the output of the command.
I'm also doing this with a count > 1. The remote-exec provisioner does not allow me to reference the instance private_ip with a count > 1. I've tried:
"${aws_instance.example.private_ip}" # which works only on the first instance
"${element(aws_instance.example.*.private_ip, count.index)}" # which errors out before launching the instances.
EDIT: For the issue above, I totally missed the self attribute. However, I would still like to be able to do this with a template as it makes the .tf file look cleaner. I am trying to generate a json file and requires a lot of escaping for the quotes.
In generating the file from the remote-exec, $$var1 should output to $var1
# example.sh
var1="$(hostname)"
cat <<TMP > somefile
$var1
TMP
The file will contain a var that contains a linux command. The generated file shows the actual output instead of the command. And the referenced var that is using the $ escape is blank.
# example.sh
var1="ip-10-0-0-100.ec2.local" # showing the actual output and not the command
cat <<TMP > somefile
# is blank
TMP
Hi @nocode99 - thanks for taking the time to write up this nice bug report and repro case for us! I agree that template_file should respect the documented dollar-sign escaping behavior. One of us will get back to you when we have had a chance to take a look. 🔍
This is working on master, so I believe this was fixed at some point (and likely has a test to cover it since this is in HCL).
Why this closed? This still happens in v0.8
@akaspin I just ran the exact same example again (v0.8) to verify and got the expected result:

When implementing a cloudwatch agent config I had to use \$$ to escape a value of a template file:
"append_dimensions": {
"ImageId": "\$${aws:ImageId}",
"InstanceId": "\$${aws:InstanceId}",
"InstanceType": "\$${aws:InstanceType}",
"AutoScalingGroupName": "\$${aws:AutoScalingGroupName}"
}
When implementing a cloudwatch agent config I had to use
\$$to escape a value of a template file:"append_dimensions": { "ImageId": "\$${aws:ImageId}", "InstanceId": "\$${aws:InstanceId}", "InstanceType": "\$${aws:InstanceType}", "AutoScalingGroupName": "\$${aws:AutoScalingGroupName}" }
Just had this EXACT same problem, and went round in circles for ages before trying this. Then found this post :-)
Thanks
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
Just had this EXACT same problem, and went round in circles for ages before trying this. Then found this post :-)
Thanks