TrademarkTrademark
Features
Documentation
  1. Learning Center
  2. Terraform Expressions, Functions & Data Sources: A Comprehensive Guide

Article · part of a guide

The 4 Most Useful Terraform Functions

Learn about Brendan's favourite functions

The 4 Most Useful Terraform Functions

Key takeaways

  1. The format function builds strings from placeholders and is presented as a more readable alternative to string interpolation, especially for longer or multi-line formatting.
  2. The split function carves a string by a delimiter into a list, which is useful for parsing structured names like hyphen-delimited Azure resource names and indexing the result.
  3. The yamldecode function turns a YAML string into native Terraform objects you can iterate over, supporting a configuration-driven approach to Terraform.
  4. The file function reads a file into Terraform, and pairing it with fileexists guards against errors when the file may not exist by returning an empty object instead.

Why Use format Instead of String Interpolation?

This is one of the functions I reach for most. I tend to prefer it over string interpolation. String interpolation has gone out of fashion a bit since Terraform v0.12+, and that's part of what pushed me towards format in the first place. Now I love it because I can do more complex formatting and keep things readable by putting elements on their own lines.

locals {
  first = "FIRST   "
  second = "SECOND"
}
 
resource "scratch_string" "with_format" {
  in = format(
    "Something interesting from the %s and then from the %s",
    trimspace(local.first), # Remove whitespace
    lower(local.second)     # Return in lowercase
  )
}
 
resource "scratch_string" "with_string_interpolation" {
  in = "Something interesting from the ${trimspace(local.first)} and then from the ${lower(local.second)}"
}

In the first resource you can clearly see what's going on with format, even without the comments. The second example does the same thing with string interpolation. It's still readable here, but you can see how confusing it gets as the string and formatting requirements grow.

When you write Terraform, keep one question in mind: how easy will this be for other engineers to read and work on? Think back to the last time you were stuck in a codebase that was hard to read.

How Do You Split a Delimited String With split?

The split function is useful in a lot of situations, especially when you're dealing with strings that aren't comma delimited. A good example is a naming standard, like Azure resource names. Here we'll pull the region out of an Azure resource name.

locals {
  resourceGroupName = "rg-aus-prd-meow"
 
  regions = {
    aus = "Australia Southeast"
    aue = "Australia East"
  }
}

Our resourceGroupName property holds a hyphen-delimited (-) string. To grab the second element, which is the region, use split like this:

output "shortRegion" {
  value = split("-", local.resourceGroupName)[1]
}

We can go further and look up a value in local.regions based on the string that comes out of split:

output "fullRegion" {
  value = lookup(
    local.regions,
    split("-", local.resourceGroupName)[1]
  )
}

Being able to split strings comes in handy all the time when you work with named resources. I'd say I use split more than any other function!

How Does yamldecode Enable Config-Driven Terraform?

I'm a big proponent of config-driven Terraform, and my configuration format of choice is yaml. It reads well for both humans and machines, and it can be validated in a similar way to JSON. Terraform gives us an easy way to decode yaml into native objects. Here's a yaml string being decoded.

locals {
  yaml = 
  first: <<EOF
    name: FIRST
  second:
    name: SECOND
EOF
 
  decoded = yamldecode(local.yaml)
}

Above, local.yaml is a string containing some yaml. We need to decode it into Terraform objects so we can work with the data, which is what the yamldecode call on line 9 does. With the yaml decoded, here's one way to consume it:

resource "scratch_string" "yaml" {
  for_each = local.decoded
 
  in = format(
    "Property: %s, Name: %s",
    each.key,
    each.value.name
  )
}

This iterates over each key in local.decoded. That's the basic pattern for handling configuration in Terraform with yaml, and the next function takes it a step further.

How Do You Safely Read a File Into Terraform With file?

The last function here is file. It reads data in from a file (or several files, with fileset) so you can work with that data like anything else. In this example we are reading in a yaml file, since that's how we like to do configuration around here.

locals {
  yamlFile = file("./example.yaml")
}

That's the simplest form: reading a file into a local variable. It's also risky, because if the file doesn't exist Terraform errors out. Sometimes that's what you want, but there's an alternative:

locals {
  decodedFile = (
    fileexists("./example.yaml") ?
    yamldecode(file("./example.yaml")) :
    {}
  )
}

This checks whether the file exists first. If it does, we load it with file() and decode it into our variable with yamldecode(). If it doesn't, we return an empty object ({}).

Which of These Terraform Functions Should You Try Next?

These are the four I reach for most often and the ones that save me the most trouble. One caveat on file: just because you can read a file into Terraform doesn't mean you can use what's in it. If you have a favourite function that isn't on this list, I'd love to hear about it.

You can try all of these functions in your own runs by signing up for Scalr.

Frequently asked questions

Should I use format or string interpolation in Terraform?

format is often more readable, especially as strings and formatting requirements grow. It lets you put each element on its own line and add comments, where long interpolated strings get confusing. Interpolation is fine for short cases, but format holds up better as complexity increases.

How do you extract part of a string in Terraform with split?

split breaks a string into a list by a delimiter, so you can index the piece you want. For a hyphen-delimited Azure resource name like rg-aus-prd-meow, split("-", name)[1] returns the region segment. You can then feed that into lookup to map the short code to a full region name.

How do you use YAML configuration in Terraform?

The yamldecode function turns a YAML string into native Terraform objects. You can then iterate over the decoded data with for_each to drive resource creation from configuration. YAML reads well for both humans and machines, which makes it a good fit for config-driven Terraform.

How do you avoid errors when reading a file in Terraform?

Calling file() on a path that doesn't exist makes Terraform error out. Guard it with fileexists: if the file exists, read and decode it; otherwise return an empty object. That keeps the run working whether or not the file is present.

About the author

Brendan Thompson

solutions engineer at Scalr

Brendan Thompson is a solutions engineer at Scalr, specializing in Terraform and cloud infrastructure.

Part of this guide

2 sheets

Terraform Expressions, Functions & Data Sources: A Comprehensive Guide

1 article