Conditional nested configuration blocks for Terraform Resources

Rees Pozzi
3 min readFeb 3, 2023

Conditional expressions are used to add logic-based decision making with code. This usually follows a certain flow that is extensible and changes our code configuration based on certain conditions being met.

if (some condition is true) then
Do one thing!
else
Do a different thing!

Terraform is a little different to most programming languages though, a declarative IAC tool delivered by HashiCorp, which is written in HCL or JSON.

Does Terraform support conditional logic?

Yes, but it’s a little different to what you may be used to, or expect to be writing. Terraform uses conditional expressions, basically a ternary operator. You can read more about them here, but generally the form looks like this:

condition ? true_value : false_value

This is great for simple use cases, like deciding a value for an attribute, number of resources to create, etc. But what about when we want an entire nested block with complex values to either be included or omitted, based on a condition? Can we write all of this nicely within one line?

Recently, I’ve come across this interesting problem that goes beyond Terraform’s general use case for conditional expressions, and spent some time looking through solutions with colleagues. Let’s say you have a resource managed by Terraform, like below:

An image showing code for configuring a terraform resource

What if you only want to add the enabled_log configuration block, if a certain condition is met?

Terraform conditional expressions on their own don’t really work here. You could try to set enabled=false and have to switch between every time, or make another resource that doesn’t have that block, and use some conditional expression to set the number of each resource Terraform should create using count , or you could try and extract this into locals and add some logic this way. None of these methods are very clean to look at, and not all of them will work in all cases, if Terraform only expects one resource definition for instance. So how to get around this problem?

Dynamic Blocks with a condition

Dynamic Blocks in Terraform are typically used to adhere to D.R.Y principles, and avoid repeating nested blocks within a resource block. They have additional functionality in that they let you loop over a list of items, using the for_each meta argument. Do you see where we’re going with this?

The key here is that Terraform will iterate once for each element defined in the for_each argument.

So to remove the nested configuration block, we just provide an empty list to our dynamic block’s iterator.

This is how it looks in practice:

An image containing terraform code configuration for conditional nested block — https://gist.github.com/reespozzi/b8fbce5d5b0953aa6a761b4c1890c96e

If our condition is met, we supply a list which contains an element, therefore creating our nested block only once. If our condition is not met, we supply an empty list, so the nested block is not created.

This way, we can dynamically include entire nested configuration blocks for a Terraform resource, based on a given condition in a clean way!

--

--