Object type variable definition syntax and variable validation

Is there a way to define as part of an object definition the variable validation.

Eg Say we have the following variable defined

  variable "VMSize" {
    type = string
    default = "Small"
    validation {
      condition = can(regex("^Small$|^Medium$|^Large$", var.VMSize))
      error_message = "Invalid VM Size."
    }
  }

How can one define it as part of an object?

The following doesn’t work (with v0.13-beta1).

variable "VMCluster" {
  type = object({
    "VMSize" = {
      type = string
    default = "Small"
    validation {
      condition = can(regex("^Small$|^Medium$|^Large$", var.VMSize))
      error_message = "Invalid VM Size."
    }
  }
})}

In general, will HCL be revising the object type definition to allow them to contain normally defined variables rather than the <KEY> = <TYPE> syntax?

The following would be great:

variable "VMCluster" {
  type = object({
    variable "VMSize"  {
      type = string
    default = "Small"
    validation {
      condition = can(regex("^Small$|^Medium$|^Large$", var.VMSize))
      error_message = "Invalid VM Size."
    }
  }
})}

Good question! You can define validations over the whole value of an object type. For example, like this:

variable "VMCluster" {
  type = object({ VMSize = string })
  validation {
    condition = can(regex("^Small$|^Medium$|^Large$", var.VMCluster.VMSize))
    error_message = "Invalid VM Size."
  }
}

(As a side note, it’s not possible to specify default values for single attributes of objects as you write in your last example: only complete values of objects are valid, and they must include key-value pairs for each attribute.)

Two other things that might be relevant here: an alternative way to write this specific validation condition, and using multiple validations.

Depending on how much you enjoy writing regexes, instead of using can(regex(…)), it might be simpler to use contains:

variable "VMCluster" {
  type = object({ VMSize = string })
  validation {
    condition = contains(["Small", "Medium", "Large"], var.VMCluster.VMSize)
    error_message = "Invalid VM Size."
  }
}

And as your object type gets more complex, you can add multiple validations. For example:

variable "VMCluster" {
  type = object({ VMSize = string, Count = number })
  validation {
    condition = contains(["Small", "Medium", "Large"], var.VMCluster.VMSize)
    error_message = "Invalid VM Size."
  }
  validation {
    condition = var.VMCluster.Count > 1
    error_message = "Count must be greater than 1."
  }
}

I hope this helps! Let me know if anything is unclear.

Thanks for the explanation.
Now, from a language coherency perspective this is pretty awful syntax. It would be MUCH better for objects to simply allow regular variable definition syntax. Is that already a planned enhancement? (I’ll open an request if not)

@wdec I don’t think we’ve heard that feedback before, no.

If you leave an enhancement request, it would be very helpful to have examples of what you’re trying to do that the current implementation doesn’t allow. Thanks in advance!

I added my proposal as comment to a somewhat related ongoing topic:


We’ll see how it goes. Maybe it should be a separate proposal