Are there any examples of variable validation rules for more complex types? In particular, my use case is to ensure AWS resources have a set of required tags with correct case/spelling. Is it possible to validate each key in a map individually?
tags = {
Name = "foo"
Description = "foo bar baz"
Environment = "test"
}
example
variable "tags" {
default = {}
type = map(string)
}
Hi @mlehner616,
You can have as many validation
blocks for your variable as you want, and in this case I think I’d be inclined to write a separate one for each of the tag names, like this:
variable "tags" {
type = map(string)
validation {
condition = (
can(var.tags["Name"]) &&
var.tags["Name"] == lower(var.tags["Name"])
)
error_message = "A Name tag is required and it must be all-lowercase."
}
validation {
condition = can(var.tags["Description"])
error_message = "A Description tag is required."
}
validation {
condition = (
can(var.tags["Environment"]) &&
contains(["test", "production"], var.tags["Environment"])
)
error_message = "An Environment tag is required and it must be set to either \"test\" or \"production\"."
}
}
3 Likes
@apparentlymart
I greatly appreciate the hint. This was exactly what I needed and gets me a lot closer to what I need to do. The docs could use an example like this with something more than just “string.”
I’m not sure if I’m encountering a bug here or not but your example for “Name” generates the following vague error if the map doesn’t contain the key “Name” at all. Shouldn’t it return error_message
?
|----------------
| var.tags is map of string with 1 element
The given key does not identify an element in this collection value.
If I wrap the condition below in can() it fixes that problem but then it doesn’t properly validate the value and incorrectly succeeds even if the value has upper case characters. Am I missing something?
...
can(var.tags["Name"]) &&
can(var.tags["Name"] == lower(var.tags["Name"]))
...
Because the first condition would fail if the key “Name” were missing, why is the second condition even being evaluated at all?
I believe I fixed it with the following by wrapping the second condition in a try(), although it seems like I shouldn’t have to do this.
validation {
condition = (
can(var.tags["Name"]) &&
try(var.tags["Name"] == lower(var.tags["Name"]), false)
)
error_message = "A Name tag is required and it must be all-lowercase."
}
Hi @mlehner616,
I think what you ran into here is the behavior discussed in the following issue:
Indeed, right now you need to make sure both sides of &&
can evaluate without error, which is inconvenient. Hopefully we’ll improve on that in a future Terraform release.
1 Like