Understand Conditional Statements in Terraform in 5 minutes
By
Brendan Thompson
Whilst the Terraform documentation states that there is only a single type of conditional expression -the ternary operator- there is technically an if expression available to us within the for_each meta-argument. Today we are going to dive into both of those scenarios and see how we can conditionally do things within Terraform.
First off, lets look at the ternary operator. The right hand side of the expression has three components to it:
The test expression — the conditions we are using to test truthfulness
The truthful expression — what is returned if the condition is true
The false expression — what is returned if the condition is false
This allows us to do a range of things as engineers from simply checking if something has a value to more complex logic such as if multiple things exist within a network or have permissions to another thing.
NOTE — Return TypesIt is very important to note that both sides of the ternary expression itself MUST be the same type.
We are now going to dive into an example where we will be using the conditional as a way to feature flag some Terraform resource.
variable "is_enabled" {
type = bool
description = <<-DESC
(Optional) Should feature be enabled
[Default: `false`]
DESC
default = false
}
resource "scratch_string" "first" {
in = "I am the first"
}
resource "scratch_string" "second" {
for_each = var.is_enabled ? { enabled = true } : {}
in = "I am the second"
}
```
First a variable is declared (is_enabled) which will be used to understand if the second string should be created or not. This is works because if is_enabled is true then { enabled = true } is returned to the for_each and a single resource will be created, however if it is false then an empty map ( {} ) will be returned which yields no resource creation. This same result can be achieved utilising the count meta-argument however this is less recommended.
These can be used absolutely anywhere within Terraform, another example might be as follows:
In this example we are going to create a virtual machine that is significantly more powerful for our production environment than any other. It is also possible to nest these expressions to allow for checking more and more conditions, ideally you wouldn't do this unless you had no other choice however.
It is obvious to see here that the more conditions we add the harder the code becomes to read and the more brittle it becomes too. But it certainly is possible.
Any part of the expression can also be wrapped within parentheses ( () ) which allows us to multiple checks or return values via complex expressions. For instance the test expression you may actually want to check multiple things and ensure they're all true with the alltrue() function.
The second conditional type to touch on is the if within the for expression, which we are going to look at now.
locals {
animals = {
mammal = {
feline = {
name = "cat"
sound = "meow"
}
canine = {
name = "dog"
sound = "woof"
}
}
reptile = {
serpentes = {
name = "snake"
sound = "hiss"
}
}
}
}
variable "class" {
type = string
default = "mammal"
}
resource "scratch_string" "first" {
for_each = {
for k, v in local.animals :
k => v
if k == var.class
}
in = each.key
}
In this example we are filtering animals by their class, this is provided to us via an input variable. We could do a lot more with the for expression especially in how we return information but that is not the scope of this article, instead we focus on the power of the if. It should be noted that you cannot use the if within the for to check for existence of a property/field on an object, that will return an error. The if is certainly not as powerful as the ternary operator but it is still incredibly powerful none the less.
In this article we looked at the ternary operator which allows us to return a true value or a false value based on the result of a condition. These are exceptionally powerful and allow us to create logic such as what size of a resource to provision in different environments, or if a resource should even be provisioned at all. We then took a dive into the if expression on the for expression which allows us to filter out data before returning it to the consumer. These are some fantastic concepts that you can apply to your Terraform code today!
Note: While this blog references Terraform, everything mentioned in here also applies to OpenTofu. New to OpenTofu? It is a fork of Terraform 1.5.7 as a result of the license change from MPL to BUSL by HashiCorp. OpenTofu is an open-source alternative to Terraform that is governed by the Linux Foundation. All features available in Terraform 1.5.7 or earlier are also available in OpenTofu. Find out the history of OpenTofu here.