Validating Terraform Resources Using Preconditions


During a project I was working on this weekend, one of the tasks was to validate a variable by comparing it to another variable, and ensuring the number of values in the one list was the same as the number of values in the other list. Terraform 0.13.0 and higher includes the ability to specify custom validation rules. A validation block can be added, which can include a condition and error message, similar to the following:

variable "image_id" {
  type        = string
  description = "The ID of the image."

  validation {
    condition     = length(var.image_id) > 4
    error_message = "The length of the image ID must be at least 4."

The Problem

In the above example, the validation check only references the variable itself var.image_id. In my case, I was trying to compare two variables. For example:

validation {
    condition     = length(var.image_id) == length(var.document_id)
    error_message = "The image_id size must match the document_id size"

When trying to use this kind of validation block inside the variable definition, I would get the following error:

The condition for variable "image_id" can only refer to the variable itself, using var.image_id.

Looking into this further, I found an open Terraform issue on Github: Allow variable validation conditions to refer to other variables #25609.

The Workaround

From reviewing this Github issue, one of the posts included a workaround that was only 4 days old. The ability to add preconditions and postconditions was made available in Terraform v1.2.0 and later. For more detail:

  • Terraform evaluates precondition blocks after evaluating existing count and for_each arguments. This lets Terraform evaluate the precondition separately for each instance and then make each.keycount.index, etc. available to those conditions. Terraform also evaluates preconditions before evaluating the resource’s configuration arguments. Preconditions can take precedence over argument evaluation errors.
  • Terraform evaluates postcondition blocks after planning and applying changes to a managed resource, or after reading from a data source. Postcondition failures prevent changes to other resources that depend on the failing resource.

For this use case, in the resource blocks being created, the following section was added:

  lifecycle {
    precondition {
      condition     = length(var.image_id) == length(var.document_id)
      error_message = "The image_id size must match the document_id size."

Testing by adjusting one of the variable lists to have a different number of items triggered a “Resource Precondition Failed” error, including details on the specific precondition that failed, so the validation via the resource block is now working.



Leave a Reply

Your email address will not be published. Required fields are marked *