What are some commonly used built-in Terraform functions, and how do you discover/test them?

5 minintermediateterraformfunctionshcl

Quick Answer

Terraform ships a large standard library of pure functions, grouped roughly by purpose: string functions (`format`, `join`, `split`, `replace`, `lower`/`upper`), collection functions (`merge`, `concat`, `flatten`, `distinct`, `lookup`, `contains`), numeric functions (`min`, `max`, `ceil`), encoding functions (`jsonencode`/`jsondecode`, `base64encode`, `yamlencode`), and filesystem functions (`file`, `fileexists`, `templatefile`). Note that Terraform has **no way to define custom functions** in HCL itself — you compose the built-ins to get the behavior you need. `terraform console` is the standard way to interactively try a function against real values before committing it to configuration, e.g. running `merge({a=1}, {b=2})` directly to confirm the exact output shape before relying on it inside a resource block.

Detailed Answer

HCL is deliberately not a general-purpose programming language — there's no way to define your own function. Instead, Terraform ships a broad standard library of built-in functions, and real configurations lean on composing them.

The major categories

String functions

format("web-%02d", 3)          # "web-03"
join("-", ["a", "b", "c"])     # "a-b-c"
split(",", "a,b,c")            # ["a", "b", "c"]
replace("hello world", " ", "-")  # "hello-world"
lower("HELLO")                 # "hello"

Collection functions

merge({a = 1}, {b = 2})              # {a = 1, b = 2}
concat(["a"], ["b", "c"])            # ["a", "b", "c"]
flatten([["a", "b"], ["c"]])         # ["a", "b", "c"]
distinct(["a", "a", "b"])            # ["a", "b"]
lookup({env = "prod"}, "env", "dev") # "prod" (with a fallback default)
contains(["a", "b"], "a")            # true

Numeric functions

max(1, 5, 3)   # 5
min(1, 5, 3)   # 1
ceil(4.1)      # 5

Encoding functions

jsonencode({name = "web"})     # '{"name":"web"}'
jsondecode("{\"a\":1}")        # {a = 1}
base64encode("hello")
yamlencode({name = "web"})

Filesystem functions

file("${path.module}/policy.json")
fileexists("${path.module}/optional.json")
templatefile("${path.module}/script.sh.tpl", { name = "web" })

Discovering and testing functions

terraform console is the standard way to try a function before committing to it in configuration:

$ terraform console
> merge({a = 1}, {b = 2})
{
  "a" = 1
  "b" = 2
}
> cidrsubnet("10.0.0.0/16", 8, 2)
"10.0.2.0/24"

This lets you confirm the exact output shape/type of an unfamiliar function against real values, interactively, without wiring it into a resource and running a full plan.

The key constraint to remember

There is no way to write a custom function in HCL. If the built-in library doesn't have exactly what you need, the standard approaches are: compose several built-ins together (a for expression combined with format, say), fall back to a local-exec provisioner calling an external script (rarely ideal, per the earlier provisioners discussion), or use Terraform's external data source / a purpose-built provider to shell out to real code. This is one of the clearest trade-offs of choosing a purpose-built declarative language over a general-purpose one like Pulumi's approach.

Related Resources