CV and personal site of Andy Hunt
Posted: Thursday 04 March 2021 @ 12:12:55
Terraform allows you to define your inputs as arbitrarily complex objects and lists of objects. For example, consider the following:
variable "instances" {
type = list(object({
name = string
count = number
tags = map
}))
}
It describes an input which is a list of objects, which have name
, count
, and tags
fields. You probably have some validation you'd like to apply to each of those objects, for example:
name
must not be emptycount
must be a multiple of 3tags
must contain an business_unit
tagTerraform allows you to perform those validations using a validation
block in the variable's definition.
The Terraform documentation shows a reasonably trivial example of validating a string, but it's also possible to validate lists, and lists of objects. Enter the alltrue
function.
The alltrue
function takes an array, and asserts that every entry is the value true
. If you combine this with a Terraform for
expression, you can produce an input to alltrue
which is the result of applying a validation function to each element in the list.
You can start by writing a basic validation routine (for the above rules) for a single object. Assuming it's called instance
, it might look like:
( length(instance.name) > 0
&& (instance.count % 3) == 0
&& lookup(instance.tags, "business_unit", null) != null
)
You can then combine this with a for
expression to apply it to each object in a list, so that you're left with a list of boolean values:
[for instance in var.instances : (
length(instance.name) > 0
&& (instance.count % 3) == 0
&& lookup(instance.tags, "business_unit", null) != null
)]
Finally, you can wrap this in the alltrue
function to assert that every validation passed:
variable "instances" {
type = list(object({
name = string
count = number
tags = map
}))
validation {
condition = (
alltrue([for instance in var.instances : (
length(instance.name) > 0
&& (instance.count % 3) == 0
&& lookup(instance.tags, "business_unit", null) != null
)])
)
error_message = "Validation of an object failed"
}
}
Unfortunately, Terraform doesn't support multiple validation blocks for a single variable, so it isn't possible to provide a more useful error message.