Updating a non .tf file using terraform output values

Chinmay Dorlikar
3 min readMar 3, 2021

Passing output values or variables to .tf files is fairly easy, but can we do that for files with other extensions like .sh?

This article will help you pass the output values or variables generated in a tf file to a non .tf file using template_file resource and local-exec block.

Passing output or variable values to .tf files is pretty straightforward. Here’s a simple example:
variable bucket_name{
type = string
default = "my-bucket"
}
variable backend_name{
type = string
default = "my-website-backend"
}
resource google_storage_bucket static-site {
name = var.bucket_name
location = "EU"
force_destroy = true
}
resource google_compute_backend_bucket static-site {
bucket_name = google_storage_bucket.static-site.name
name = var.backend_name
enable_cdn = true
}
This shows how we can pass both a variable or an output value to a .tf file component. So how do we do this for a shell script which changes depending on maybe the name of a resource created?

The good thing about using Terraform is the multiple ways of approaching a problem. Even in this case, we have more than one way of achieving the solution. Let’s take a look at them!

If you are using a Linux machine to make all your Terraform operations, you can use a local-exec block and store the output/variable value in an environment variable and use it later in your bash script. Sounds easy right?resource google_storage_bucket bucket{
name = "my-bucket"
location = "EU"
}
resource null_resource export_value{
trigger = {
bucket_name = google_storage_bucket.bucket.name
}
provisioner local-exec {
command = "export bucket_name=${trigger.bucket_name}"
}
}
Here's what my shell script startup.sh looks like:
#!/bin/bash
gsutil cp -m gs://$bucket_name/ .

This is one way of doing which involves using the local-exec block which is not exactly the best way to do it. So here’s an interesting provision by Terraform registry that we will be actually using — template_file.

The template_file data source renders a template from a template string, which is usually loaded from an external file.

resource google_storage_bucket bucket {
name = "my-bucket"
location = "EU"
}
data template_file startup_script {
template = file(“startup.sh”)
vars = {
bucket_name = google_storage_bucket.bucket.name
}
}
Here’s what my shell script startup.sh looks like in this case:
#!/bin/bash
gsutil cp -m gs://${bucket_name}/ .

Here’s how the file will look after terraform apply for both the cases:
#!/bin/bash
gsutil cp -m gs://my-bucket/ .

And that’s it! Now you have changed a non .tf file using an output value and you can replace it with a variable value as well. And all this while keeping your code strictly in HCL!

This is particularly helpful when you need dynamic start-up script files for your EC2 or GCP VM instances spun up using Terraform.

Hope this helps you attain the ultimate goal — a single click deployment.

--

--