Terraform 0.6.1
In a template variable section, I need to define a variable like this:
resource "template_file" "foo_template" {
filename = "foo.yaml"
vars = {
TF_FOO = "bar-${baz}"
}
}
That is - literally, where I have ${TF_FOO} in my foo.yaml, I want it replaced, literally with bar-${baz}
Now this obviously doesn't work, because terraform treats ${baz} as a variable and rightly says it doesn't exist.
So then I tried
TF_FOO="bar-$${baz}"
No luck - this gets written into the template as ... literally bar-$${baz}
So then I tried
TF_FOO="bar-\${baz}"
No luck - terraform treats this as a variable again.
There is no way to get terraform to write a literal ${baz} as a variable replacement in a terraform file.
Simple example:
dummy.tf
resource "template_file" "foo" {
filename = "./foo.yaml"
vars = {
bar = "bar-$${baz}"
}
}
bar.yaml
hello ${bar}
terraform apply
template_file.foo: Creating...
filename: "" => "./foo.yaml"
rendered: "" => "<computed>"
vars.#: "" => "1"
vars.bar: "" => "bar-$${baz}"
template_file.foo: Creation complete
vars.bar is incorrect as per documentation
terraform.tfstate
{
"version": 1,
"serial": 1,
...
"resources": {
"template_file.foo": {
...
"rendered": "hello bar-$${baz}\n\n",
...
}
rendered is incorrect
Horrible workaround for now:
bar = "bar-${replace("%{baz}", "%", "$")}"
Hi @gtmtech! I've just reproduced this on the master branch using the following files:
main.tf:
resource "template_file" "foo" {
filename = "./foo.yaml"
vars = {
bar = "bar-$${baz}"
}
}
output "out" {
value = "${template_file.foo.rendered}"
}
foo.yaml:
hello ${bar}
Applying then gives:
$ terraform apply
template_file.foo: Creating...
filename: "" => "./foo.yaml"
rendered: "" => "<computed>"
vars.#: "" => "1"
vars.bar: "" => "bar-$${baz}"
template_file.foo: Creation complete
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.
State path: terraform.tfstate
Outputs:
out = hello bar-$${baz}
I'll investigate further and try to get this fixed.
PR is open.
I had following scripts inside ‘neo4j\templates\user-data-slave.tpl”.
But this didn’t work because of ‘$’ character. It didn’t execute the code itself.
So I replaced with ‘$$’ as per terraform interpolation doc. But it copied as empty values.
# Neo4j backup scripts settings
echo 'Neo4j backup scripts settings'
mkdir -p /opt/neo4j-scripts
tee /opt/neo4j-scripts/neo4j_backup_to_s3.sh <<EOL
#Initialization the params
TODAY=$(date +%Y-%m-%d-%H-%M-%S)
NEO4J_SERVER=$1
NEO4J_BACKUP_BINARY=neo4j-backup
NEO4J_BACKUP_PORT=$2 # Default port 6362
NEO4J_HOSTNAME=$(hostname) #ip-10-0-2-1
NEO4j_BACKUP_DESTINATION_FOLDER=/tmp/neo4j-backup-tmp
BACKUP_TAR_FOLDER=/tmp
BACKUP_FILE_NAME=$NEO4J_HOSTNAME.tar
BACKUP_S3_FOLDER=daily/$TODAY
AWS_BUCKET=$3 #s3://bucket-us-east-1
<----- script for neo4j backup upload. This also contains $ linux variable--->
EOL
So finally fixed as below code. It may be dirty. But working. I am using 0.8.8. Still escaping of '$' with '$$' is not working.
# Neo4j backup scripts settings
echo 'Neo4j backup scripts settings'
mkdir -p /opt/neo4j-scripts
tee /opt/neo4j-scripts/neo4j_backup_to_s3.sh <<EOL
#Initialization the params
TODAY=<dollar>(date +%Y-%m-%d-%H-%M-%S)
NEO4J_SERVER=<dollar>1
NEO4J_BACKUP_BINARY=neo4j-backup
NEO4J_BACKUP_PORT=<dollar>2 # Default port 6362
NEO4J_HOSTNAME=<dollar>(hostname) #ip-10-0-2-1
NEO4j_BACKUP_DESTINATION_FOLDER=/tmp/neo4j-backup-tmp
BACKUP_TAR_FOLDER=/tmp
BACKUP_FILE_NAME=<dollar>NEO4J_HOSTNAME.tar
BACKUP_S3_FOLDER=daily/<dollar>TODAY
AWS_BUCKET=<dollar>3 #s3://bucket-us-east-1
<----- script for neo4j backup upload. This also contains <dollar> linux variable--->
EOL
sed -i 's/<dollar>/$$/g' /opt/neo4j-scripts/neo4j_backup_to_s3.sh
This is still not working properly in 0.11
resource "template_file" "init_file" {
template = "${file("${path.cwd}/templates/dsiprouter.tpl")}"
vars = {
giturl = "${var.giturl}"
gitbranch = "${var.gitbranch}"
}
}
resource "local_file" "foo" {
content = "${template_file.init_file.rendered}"
filename = "${path.module}/init.sh"
}
variable "giturl" {
default = "https://github.com/dOpensource/dsiprouter.git"
}
variable "gitbranch" {
default = "master"
}
output "template" {
value = "${template_file.init_file.rendered}"
}
#!/usr/bin/env bash
BUILD_VERSION="${gitbranch}"
BUILD_DIR="/opt/dsiprouter"
cmdExists() {
if command -v "$$1" > /dev/null 2>&1; then
return 0
else
return 1
fi
}
if cmdExists "yum"; then
yum install -y git curl
elif cmdExists "apt"; then
apt-get install -y git curl
if [ $$? -ne 0 ]; then
if ! grep -q -E '(ftp|deb)\.debian.org/debian' /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null; then
# add debian main repo
[ -e /etc/debian_version ] && CODENAME=$$(cat /etc/os-release | grep '^VERSION=' | cut -d '(' -f 2 | cut -d ')' -f 1)
echo "deb http://ftp.debian.org/debian $${CODENAME-stable} main contrib non-free" >>/etc/apt/sources.list
apt-get update -y
apt-get install -y debian-keyring debian-archive-keyring
fi
apt-get install -y git curl
fi
fi
git clone --depth 1 ${giturl} -b $${BUILD_VERSION} $${BUILD_DIR}
cd $${BUILD_DIR}
./dsiprouter.sh install -rtpengine -servernat
exit $$?
terraform apply -auto-approve ./run/
Escaped dollar sign literals are output as ONE dollar sign
Outputs:
template = #!/usr/bin/env bash
BUILD_VERSION="master"
BUILD_DIR="/opt/dsiprouter"
cmdExists() {
if command -v "$$1" > /dev/null 2>&1; then
return 0
else
return 1
fi
}
if cmdExists "yum"; then
yum install -y git curl
elif cmdExists "apt"; then
apt-get install -y git curl
if [ $$? -ne 0 ]; then
if ! grep -q -E '(ftp|deb)\.debian.org/debian' /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null; then
# add debian main repo
[ -e /etc/debian_version ] && CODENAME=$$(cat /etc/os-release | grep '^VERSION=' | cut -d '(' -f 2 | cut -d ')' -f 1)
echo "deb http://ftp.debian.org/debian ${CODENAME-stable} main contrib non-free" >>/etc/apt/sources.list
apt-get update -y
apt-get install -y debian-keyring debian-archive-keyring
fi
apt-get install -y git curl
fi
fi
git clone --depth 1 https://github.com/dOpensource/dsiprouter.git -b ${BUILD_VERSION} ${BUILD_DIR}
cd ${BUILD_DIR}
./dsiprouter.sh install -rtpengine -servernat
exit $$?
The parser seems to be grabbing a few but not all use cases in the template file.
Looking at my previous comment you can see that the following shell variables are correctly escaped:
While the rest of them are not correctly being escaped
It's still broken.^W^W^W My apologies it works well in my use case, i missed init call
$ terraform --version
Terraform v0.11.13
+ provider.google v2.2.0
+ provider.google-beta v2.2.0
+ provider.template v2.1.1
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.