7

First thanks for this post Adding a default field for type = map(object()) in variavles.tf, this answered the first part of the struggle that I had in getting default values to work with type map(object()). The last part that I am trying to get working is how to do validation of the input values.

terraform {
  experiments = [module_variable_optional_attrs]
}

variable "dns_server" {
  description = "Add DNS Servers for domain resolution.  You can configure a maximum of two servers.  Only one can be preferred 'true'."
  type = map(object({
    preferred = optional(bool)
    server    = optional(string)
  }))
  default = {
    default = {
      preferred = false
      server    = "198.18.1.1"
    }
  }
  validation {
    condition = (
      can(regexall("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$", var.dns_server["server"]))
    )
    error_message = "The DNS Server is not a valid IPv4 Address."
  }
}

locals {
  dns_server = {
    for k, v in var.dns_server : k => {
      preferred = coalesce(v.preferred, false)
      server = coalesce(v.server, "198.18.1.1")
    }
  }
}

The defaults value in the variable field I know isn't used but I am using it as a placeholder for the terraform docs output.

I also know what I have above for validation is not correct because if the user used the default server IPv4 that wouldn't be set until the locals definition. I just don't know of a way to do the validation because I my trusty google search hasn't pulled up any similar examples.

The code is located here if you need more details about how it is being used:

https://github.com/scotttyso/terraform-aci-fabric/tree/main/test

If I comment out the validation everything else is working fine. Thanks in advance.

1
  • In general, you can validate an object type but not a map type, because the object will have known keys you can parse in the validation block, and the map will not. Commented Feb 14, 2021 at 11:44

1 Answer 1

18

Is this what you are after?

variable "mapobject" {
  type = map(object({
    cidr_block       = string
    destination_type = string
    }
  ))

  validation {
    condition     = alltrue([for o in var.mapobject : contains(["CIDR_BLOCK", "NETWORK_SECURITY_GROUP", "SERVICE_CIDR_BLOCK"], o.destination_type)])
    error_message = "All destination_types must be one of CIDR_BLOCK, NETWORK_SECURITY_GROUP or SERVICE_CIDR_BLOCK!"
  }
}

With a variable assignment of:

mapobject = {
  "r0" = {
    cidr_block = "10.1.1.0/24",
    destination_type = "CIDR_BLOCK"
  }
}

The validation succeeds, whereas the following fails (as intended):

mapobject = {
  "r0" = {
    cidr_block = "10.1.1.0/24",
    destination_type = "**CIRD_BLOCK**"
  }
}

Associated error text with the previous usage:

Error: Invalid value for variable
  on main.tf line 86:
  86: variable "mapobject" {

All destination_types must be one of CIDR_BLOCK, NETWORK_SECURITY_GROUP or
SERVICE_CIDR_BLOCK!

This was checked by the validation rule at main.tf:93,2-12.

If it is, then kudos goes here: https://discuss.hashicorp.com/t/validate-list-object-variables/18291/2

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @Niel Davis

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.