Getting Started with Terraform Preconditions - The Legend of Hanuman

Getting Started with Terraform Preconditions


Terraform preconditions offer you a way to enforce conditions and even rules before creating, updating or destroying your Terraform resources. By adding preconditions you are adding another “level” of checks to ensure that the Terraform resources you deploy align with specific criteria, further adding reliability and reducing the risk of deployment issues

Table of Contents

Understanding Terraform’s Lifecycle Block and Preconditions

Preconditions are added to the Terraform lifecycle block. This allows you to manage specific behaviours for each Terraform resource. In this case, it involves the preconditions you want to use.

A Simple Precondition Example

Lets look at a simple example to start. The below resource group is only to be deployed in Azure regions uksouth or ukwest. Lets add a precondition to ensure the the resource group is only possible to be deployed to the two locations:

resource "azurerm_resource_group" "tamopsrg" {
  name     = "tamops-rg"
  location = var.location

  lifecycle {
    precondition {
      condition     = contains(["uksouth", "ukwest"], var.location)
      error_message = "Location must be either 'uksouth' or 'ukwest'."
    }
  }
}

I have highlighted the Terraform lifecycle block above, notice the use of precondition ? With the condition it must need along with the error_message when the condition is not met.

A quick test, with the below variable that is an invalid location:

variable "location" {
  description = "Location for the resources"
  type        = string
  default     = "West Europe"
}

We can see the Terraform precondition statement worked correctly, as the deployment has failed with the error_message: Location must be either 'uksouth' or 'ukwest'

% terraform plan

Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: Resource precondition failed
│ 
│   on main.tf line 7, in resource "azurerm_resource_group" "tamopsrg":
│    7:       condition     = contains(["uksouth", "ukwest"], var.location)
│     ├────────────────
│     │ var.location is "West Europe"
│ 
│ Location must be either 'uksouth' or 'ukwest'.

Benefits of Using Terraform Preconditions

Like any sort of precondition, there are benefits. I have summarised 5 benefits to explain why you may want to use Terraform preconditions in your configuration.

  1. Consistency: Another enabler tool to ensure consistency and set standards are enforced across your deployments
  2. Error Prevention: Catch any potential configuration errors early in your deployment
  3. Compliance: Helps to maintain compliance by enforcing specific standards and/or rules
  4. Cost Control: Another enabler for cost controlling, preventing the creation of over-sized resources
  5. Documentation: An interesting one, preconditions can also act as self-serving documentation

Best Practices for Preconditions in Azure

  1. Keep It Simple: Keep those preconditions as simple as possible! Create concise conditions that are easy to understand and maintain
  2. Use Variables: Use Terraform variables to make preconditions flexible and reusable
  3. Combine with Data Sources: Along with variables for flexibility configurations, also look at using Terraform data sources to create dynamic preconditions based on existing resources
  4. Test thoroughly: Ensure all preconditions work as expected
  5. Document those preconditions: You may want to document preconditions, within your documentation library

More advanced preconditions

What makes the likes of Terraform great, is that you can work with even more advanced preconditions, lets look at a few

Using Multiple Preconditions

Thats right, you can define multiple preconditions within the same lifecycle block:

resource "azurerm_resource_group" "tamopsrg" {
  name     = var.rg_name
  location = var.location

  lifecycle {
    precondition {
      condition     = contains(["uksouth", "ukwest"], var.location)
      error_message = "Location must be either 'uksouth' or 'ukwest'."
    }

    precondition {
      condition     = contains(["tamops-rg"], var.rg_name)
      error_message = "RG name must be tamops-rg'."
    }
  }
}

Using Terraform Functions in your Preconditions

Terraform functions can also be used as part of your precondition. Lets look at using cidrsubnet to ensure the subnet being used for Azure Virtual Network creation is at least /24

resource "azurerm_virtual_network" "tamopsvnet" {
  name                = "${var.rg_name}-vnet"
  address_space       = [var.vnet_address_space]
  location            = azurerm_resource_group.tamopsrg.location
  resource_group_name = azurerm_resource_group.tamopsrg.name

  lifecycle {
    precondition {
      condition     = cidrsubnet(var.vnet_address_space, 8, 0) != ""
      error_message = "The VNet address space must support at least 256 addresses."
    }
  }
}

Wrapping up

Integrating preconditions into your Terraform configurations for Azure resources adds valuable validation, preserving the integrity of your infrastructure. As your Terraform practices evolve, consider using preconditions for more complex validations and integrations across your resources. However, be mindful of overuse, as too many checks can complicate configurations, making them harder to manage.

GitHub repository containing example above


Share this content:

I am a passionate blogger with extensive experience in web design. As a seasoned YouTube SEO expert, I have helped numerous creators optimize their content for maximum visibility.

Leave a Comment