
In Terraform, an expression refers to or computes values within a configuration. That can be something as simple as a literal value like "hello, world!", or as involved as conditionally returning exported attributes from a resource or data source.
This post looks at dynamic expressions: expressions whose result depends on the environment or on the inputs you pass in, so it can change from one run to the next.
We'll start with a simple example. The goal is to use a conditional expression to decide whether one or two instances of a resource get created.
In our examples we will be using the scratch provider to demonstrate the concepts.
variable "is_highly_available" {
type = bool
description = <<DESC
(Optional) if the solution is highly available
[Default: false]
DESC
default = false
}
resource "scratch_string" "primary" {
in = format("Primary Instance - var.is_highly_available = '%s'", var.is_highly_available)
}
resource "scratch_string" "secondary" {
for_each = var.is_highly_available ? { enabled = true } : {}
in = format("Secondary Instance - var.is_highly_available = '%s'", var.is_highly_available)
}In the above example we have a variable defined is_highly_available this is something that we would set when running our code to allow for our resources to be configured in a highly available fashion. The first (or primary) instance does not do any conditional checks as we can safely assume we always want the primary instance to be provisioned. The secondary instance as you can see has a conditional as the value for its for_each.
var.is_highly_available ? { enabled = true } : {}On the left-hand side we check whether var.is_highly_available is true. If it is, we create a single secondary instance; if it's false, we don't create one at all.
Now suppose we need to do something with the IDs our resources produce, and we don't want to care whether there are one, two, or a hundred instances. In the example below we want to act on a list of the id property. The try and compact functions give us a dynamic expression here. If only the primary instance is provisioned, the list returns a single value; if the secondary instance exists too, we get both IDs back.
resource "scratch_list" "dependent_resource" {
in = compact([
scratch_string.primary.id,
try(scratch_string.secondary.*.id, "")
])
}Let's look at another example, where we have the following local block:
locals {
instances = {
primary = {
enabled = true
region = "australiaeast"
}
secondary = {
enabled = true
region = "australiasoutheast"
}
tertiary = {
enabled = true
region = "australiacentral1"
}
}
}This describes our instances. We might pass it in via an input variable, or keep it static in local variables as we have above. We'll create the instances and use a dynamic expression to work out whether each one should be created. To start, we just check whether the instance is enabled.
resource "scratch_string" "this" {
for_each = {
for k, v in local.instances :
k => v
if v.enabled
}
in = each.key
}This produces three instances, since they're all marked as enabled. The dynamic part is the if check on the for_each, which runs a conditional (or a set of conditionals, as we'll see in a moment) against our input. What if we also had a restriction on where resources could be deployed?
locals {
allowed_regions = ["australiaeast", "australiasoutheast"]
}We'll use this list to further influence Terraform's decision on when a resource should be created. Here it is in action.
resource "scratch_string" "this" {
for_each = {
for k, v in local.instances :
k => v
if v.enabled && contains(local.allowed_regions, v.region)
}
in = each.key
}As you can see we now have the && operator in place and are checking to see if our region is on our allowed list! This is where the power of dynamic expressions starts to come to life for me.
Dynamic expressions let our Terraform code make some of these decisions for us. Instead of hard-coding how many instances of a resource exist, we turn them on or off with conditional expressions. We can also merge the results together without tracking how many instances ended up being created.
