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:

Leads to a failure:

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

About me
