Condition blocks and Terraform

Condition blocks and Terraform

You can apply precondition and postcondition blocks to your resources in Terraform if you want to assume some properties will be true/false before apply or if you want to guarantee some properties will be true/false after apply when supplying your modules to consumers.

Rules for evaluating conditions

When Terraform evaluates the conditions it will try and apply them as early as possible. However, some resource properties are only available after apply, those that say (Known after apply) in your terraform plan

The result of a precondition or postcondition must be structured in a way that it can return either true or false

The scope for conditions inside the Terraform module

preconditions and postconditions will apply to resources in-scope of the Terraform Module, not other resources in your cloud unless you specify them inside the module with a data block for instance. You can use the self object on resources to evaluate them with the postcondition block to guarantee certain configuration properties.

Declaring more than one condition or mixing them with count & for_each

If you declare more than one condition and one or more fails, Terraform returns error messages for all conditions

If you specify a resource with a count or for_each setting along with a precondition block the condition will be evaluated after the count/for_each. This is to ensure the condition has the value of each result returned from each.key and count.index

When the postcondition fails

postcondition blocks will evaluate after the apply step has ran on a resource or after the read step is done on a data block resource. If a postcondition fails it will ensure resources that are depending on this failed resource are not updated.

precondition blocks can be used elsewhere as well, for example in output blocks. If this is true Terraform will evaluate the result before its passed to the value of the output.

Be smart about your condition blocks

It is smart not to litter your modules with a lot of condition blocks. If you have one resource with many dependencies, see if you can't create one postcondition block for this resource instead of several precondition elsewhere in the configuration.

Demo

I have written the following configuration in a module:

resource "azurerm_resource_group" "this" {
  name     = "rg-${var.environment}-${var.location_short}-conditiondemo"
  location = var.location
}

resource "azurerm_storage_account" "this" {
  name                     = "st${var.environment}${var.location_short}demo1337"
  resource_group_name      = azurerm_resource_group.this.name
  location                 = azurerm_resource_group.this.location
  account_tier             = var.account_tier
  account_replication_type = var.account_replication_type

  lifecycle {
    precondition {
      condition     = contains(["westeurope", "swedencentral"], var.location)
      error_message = "Allowed resource locations are West Europe and Sweden Central."
    }
  }
}

The key here is the condition = contains(["westeurope", "swedencentral"], var.location) configuration inside the precondition block.

If I call my module using an incorrect location as such:

Location = East US

Leads to a failure:

If you want to mess around with this you can find all the code here:

GitHub - carlzxc71/azure-terraform-conditions
Contribute to carlzxc71/azure-terraform-conditions development by creating an account on GitHub.

Reference

Custom Conditions - Configuration Language | Terraform | HashiCorp Developer
Check custom requirements for variables, outputs, data sources, and resources and provide better error messages in context.

About me

About me
If you have landed on my page you will have already understood my passion for tech, but obviously there is more to life than that. Here I will try and outline a few of my other hobbies. Strength training I am a person who loves to move around and challenge