Search code examples
validationterraform

Terraform valdiate that one of N variables is set to "true"


I have 4 storage class variables that are set by default to false , then set one of them in inputs to "true" . Looking for a way to validate that only one of 4 storage classes variable is set to "true".

variable "sc1_default" { 
  default = "false"
}

variable "sc1_default" { 
  default = "false"
}

variable "sc3_default" { 
  default = "false"
}

variable "sc4_default" { 
  default = "false"
}


   
on terraform.tfvars  Inputs

sc3_default = "true"

Solution

  • Option #1

    We can do that with a lifecycle precondition in a null_resource

    A couple of things before we dive into the code:

    • Your code has two sc1_default variables I'm assuming that the second one was a typo and what you meant there is sc2_default
    • For additional validation use type in the variables, it's a good practice, makes the code more readable and if someone accidentally passes the wrong type the code fails gracefully.

    see sample code below

    variable "sc1_default" {
      type    = bool
      default = false
    }
    
    variable "sc2_default" {
      type    = bool
      default = false
    }
    
    variable "sc3_default" {
      type    = bool
      default = true
    }
    
    variable "sc4_default" {
      type    = bool
      default = true
    }
    
    resource "null_resource" "validation" {
      lifecycle {
        precondition {
          condition = (
            (var.sc1_default ? 1 : 0) +
            (var.sc2_default ? 1 : 0) +
            (var.sc3_default ? 1 : 0) +
            (var.sc4_default ? 1 : 0)
          ) < 2
          error_message = "Only one sc can be true"
        }
      }
    }
    

    You can see I set the sc3_default and sc4_default both to true just to trigger the error ...

    The condition is the core of this validation we are just adding all the true with the help of shorthand if syntax (var.sc_default ? 1 : 0) and the total should be less than two, I'm assuming that all false is OK, but if not you can change that logic to check that is precisely one.

    A terraform plan on that code will error out with the following message:

    Planning failed. Terraform encountered an error while generating this plan.
    
    ╷
    │ Error: Resource precondition failed
    │ 
    │   on main.tf line 24, in resource "null_resource" "validation":
    │   24:       condition = (
    │   25:         (var.sc1_default ? 1 : 0) +
    │   26:         (var.sc2_default ? 1 : 0) +
    │   27:         (var.sc3_default ? 1 : 0) +
    │   28:         (var.sc4_default ? 1 : 0)
    │   29:       ) < 2
    │     ├────────────────
    │     │ var.sc1_default is false
    │     │ var.sc2_default is false
    │     │ var.sc3_default is true
    │     │ var.sc4_default is true
    │ 
    │ Only one sc can be true
    

    Option #2

    If you can change the input variables we could reduce it to just one with a list(bool) the code will be smaller and the validation would be right on the variable

    variable "sc_default" {
      type        = list(bool)
      description = "list of sc default values"
      default     = [false, false, false, false]
    
    
      validation {
        condition     = length(var.sc_default) == 4
        error_message = "Four defaults expected"
      }
    
      validation {
        condition     = sum([for x in var.sc_default : x ? 1 : 0]) < 2
        error_message = "Only one sc can be true"
      }
    }