Conditionals and "For" in Terraform

Author by Leo Ling

Image result for terraform

Those who came from a programming background will find infrastructure as code solutions and other configuration languages to be pretty syntactically different from traditional imperative programming languages. Naturally, this is due to the different application of these languages- we would not want to accidentally get stuck in an infinite loop while deploying virtual machines. Nonetheless, there are ways of implementing some standard control flow statements.

If/else

To understand these, we have to first introduce how to deploy a resource multiple times. By including the count parameter with a resource, we are able to scale resource deployment from 0 up to the hundreds depending on the resource in question. Terraform is perfectly happy to deploy a resource 0 times, meaning that the resource is not actually deployed. Where this weird quirk comes in handy is in conjunction with ternary operators. 

For those of us unfamiliar with ternaries, they take the following form

cond ? caseTrue : caseFalse

If the condition is true the statement before the colon is executed (caseTrue), otherwise the statement after the colon is executed (caseFalse). In Terraform, this can be used to assign our count conditionally. For example...

count = var.image_publisher == "MicrosoftWindowsServer" ? 0 : 3

Everything to the right of count = is the ternary statement, and the ternary will return a single integer value to count. This ternary checks if the variable image_publisher is set to "MicrosoftWindowsServer". If that is true, the count = 0, and the resource is not deployed. Otherwise, count = 3 and the resource is deployed three times. 

We could also deploy another resource with the ternary reversed. This allows us to deploy a different version of the resource when the logical opposite occurs, an else. Note that terraform does not allow resources of the same type of share the same name outside of lists- which have indexes to differentiate them. Thus, each of these resources need an unique identifier, and must be called differently in subsequent deployments. Even though we would only be deploying one of resources at a time in this case. Although ternaries now support short circuiting within the conditionals, it seems like short circuiting is not allowed between resources.

count = var.image_publisher == "MicrosoftWindowsServer" ? 3 : 0

OR

count = var.image_publisher != "MicrosoftWindowsServer" ? 0 : 3

Unfortunately, Terraform does not support traditional if/else if/else statements. Thus, we have to implement more logically complex statements manually. Terraform does support traditional logic operators: AND &&, OR ||, NOT !, and so forth. We are able to chain these operators together to make more complex conditionals. In theory, this could be used to implement the full if else statements. 

For

In the newer versions of Terraform >= 0.12, Terraform now supports for expressions. This is mostly used for parsing preexisting lists and maps rather than generating ones. For example, we are able to convert all elements in a list of strings to upper case using this expression.

[for el in var.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 this case, the original element from list now correspond to their uppercase version.

Lastly, we can include an if statement as a filter in for expressions. Unfortunately, we are not able to use if in logical operations like the ternary operators we used before. The following state will try to return a list of all non-empty elements in their uppercase state.

[for el in var.list : upper(el) if el != ""]

All in all, the use of for expressions are much more limited compared to imperative programming languages. The two expressions introduced in this section, for and if are exclusively used for lists rather than flow control of the program. That is to be expected since Terraform follows the declarative programming paradigm by describing the logic of the computation rather than the control flow- describing what the program must accomplish rather than how that is accomplished.