If/else and For in Terraform
Background
I by no means a programmer, but I have worked and dealt with Powershell, .Net, C++, C#, Java and similar code. So, for me, the way to work with conditionals and "For"-loops in Terraform is quite different to what I'm used to. For a more seasoned programmer this is probably quite simple and intuitive, but I've never worked with logic in the kind of structure that Terraform uses.
I'm going to explain in a bit more detail what I'm talking about.
If/else
In terraform, one way to deploy a resource multiple times is by using count. It can go from creating a resource zero times to hundreds, or thousands of times. It's important to note that for Terraform it's perfectly fine to deploy zero times. We can use this fact with ternary operators.
This is what a ternary looks like
condition ? caseTrue : caseFalse
This is the equivalent to an If-statement. If the condition is true the caseTrue is executed. If it is not true, the case False is executed. In terraform, this can be used to assign count conditionally in this way
count = var.server == "MicrosoftWindowsServer" ? 0 : 1
Everything efter count =
is the ternary statement, and the ternary will return an integer to count. In the case of this example, it will either be a 0 or a 1. This ternary checks if the variable var.server is set to "MicrosoftWindowsServer". If it is true, then count = 0
and will be deployed zero times. If it is set to something else count = 1
, and the resource will be deployed 1 time.
We can also use the ternary reversed. This means we can deploy a different version of the resource if the logical opposite occurs. In other words, like an else statement. Note that Terraform does not allow resources of the same type share the same name outside of lists, which have indexes to differentiate them. So each of these resources need a unique identifier and must be called differently in subsequent deployments. Even if only one resource is deployed. Even though ternaries now support short circuiting within the conditionals, it seems like short circuiting is not allowed between resources.
count = var.server == "MicrosoftWindowsServer" ? 1 : 0
OR
count = var.server != "MicrosoftWindowsServer" ? 0 : 1
Unfortunately, Terraform doesn't support if/else if/else statements. So more logically complex statements must be implemented manually. Terraform does support traditional logic operator such as AND &&, OR ||, NOT ! and so on. These operators can be chained together to make more complex conditionals. In theory, this can be an implementation of a full If else statement.
For
Terraform newer than version 0.12 supports expressions. This can be used to parse preexisting lists and maps rather than generating ones.
For example, we can convert all elements in a list of strings to upper case using this expression.
[for el in car.list : upper(el)]
The For iterates over each element of the list and returns the value of upper(el) for each element in form of a list. We can also use this expression to generate maps.
{for el in var.list : el => upper(el)}
In the example, the original element from list now correspond to their uppercase version.
We can also include an If statement as a filter in for expressions. However, we can't use If in logical operations like the ternary operators I showed in the beginning. The following will try to return a list of all non-empty elements in uppercase.
[for el in var.list : upper(el) if el != ""]
In plain English, loop through all elements in the variable list and return uppercase element if element isn't equal to empty.
The use of For expressions are a lot more limited compared to imperative programming languages. The For and If are exclusively used for lists rather than flow control of the program. This is because Terraform follows the declarative programming paradigm by describing the logic of the computation rather than the control flow. In other words, describing what the program must accomplish rather than how that is accomplished. For me, this often feel very restrictive. But hopefully this feeling will go away when I become more comfortable writing Terraform code.