Search code examples
terraform

A Terraform variable validation rule works on an unexpected way


My problem

This is a Terraform script:

provider "azurerm" {
  skip_provider_registration = true

  features {
  }
}

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.74.0"
    }
  }
}

variable "configurations" {
  type = map(string)
  default = {
    audit_log_enabled = "ON"
  }

  validation {
    condition     = contains(keys(var.configurations), "foo") || contains(keys(var.configurations), "bar")
    error_message = "'foo' or 'bar' are not taken into account."
  }
}

When running, for instance I launch terraform console, I got this message:

│ Error: Invalid value for variable │ │ on test.tf line 17: │ 17: variable "configurations" { │ ├──────────────── │ │ var.configurations is map of string with 1 element │ │ 'foo' or 'bar' are not taken into account. │ │ This was checked by the validation rule at test.tf:28,3-13.

What is expected

As I am not using foo either bar, I should not have this message.

But if I default by:

  default = {
    audit_log_enabled = "ON"
    foo               = "123"
  }

I don't have the message.

What I need

  • What is happening?
  • How I can have the validation message only if configurations has foo or bar item defined?

Thank you


Solution

  • To expand on Marko E's correct answer above:

    I think your misunderstanding stems from what causes a validation condition to fail in Terraform. A validation condition must evaluate to true, and if it does not it will fail validation, show the error message, and exit early. The condition you enter is the 'happy path' state where the variables will meet the condition and pass validation. As @Marko E points out in his answer you want to check that your configurations variable does not contain the key foo and the configurations variable does not contain the key bar. You could express this many ways, but the most obvious is as Marko states above condition = !contains(keys(var.configurations), "foo") && !contains(keys(var.configurations), "bar").