terraformhcl

Terraform - Optional map(objects)


I want to use the optional parameter to pass optional parameters:

variable "clients" {
  type = map(object({
    description         = string
    initiated_login_uri = optional(string)
    allowed_clients     = optional(list(string), [])
  }))
}

resource "auth0_client" "this" {
  for_each           = var.clients
  description        = each.value.description
  initiate_login_uri = each.value.initiated_login_uri
  allowed_clients    = each.value.allowed_clients
}

For which, as I understood I should be able to send

clients = {
  client_0 = {
    description         = "Description"
    initiated_login_uri = "http://example.com"
    allowed_clients     = ["XXXXXX"]
  },
  
  client_1 = {
    description = "Description"
  }
}

But got

all map elements must have the same type

Any way to fix that? Meaning each element of a map with non-mandatory attributes?


Solution

  • The way you declared and set the variable clients is valid Terraform code.

    Consider the following code:

    variable "clients" {
      type = map(object({
        description        = string
        initiate_login_uri = optional(string)
        allowed_clients    = optional(list(string), [])
      }))
      default = {
        client_0 = {
          description        = "Description"
          initiate_login_uri = "http://example.com"
          allowed_clients    = ["XXXXXX"]
        },
        client_1 = {
          description = "Description"
        }
      }
    }
    
    output "clients" {
      value       = var.clients
      description = "Value of clients"
    }
    

    Running terraform plan using Terraform v1.9.4:

    Changes to Outputs:
      + clients = {
          + client_0 = {
              + allowed_clients    = [
                  + "XXXXXX",
                ]
              + description        = "Description"
              + initiate_login_uri = "http://example.com"
            }
          + client_1 = {
              + allowed_clients    = []
              + description        = "Description"
              + initiate_login_uri = null
            }
        }
    

    The problem is that you need to ensure that the default values for initiate_login_uri and allowed_clients are valid when setting the correspondent properties of auth0_client.

    For example, var.clients.initiated_login_uri default value is null but the value of auth0_client.initiate_login_uri must be an HTTPS URL or an empty string, according to auth0_client documentation.

    So, instead of:

    variable "clients" {
      type = map(object({
        description         = string
        initiated_login_uri = optional(string)
        allowed_clients     = optional(list(string), [])
      }))
    }
    

    Try:

    variable "clients" {
      type = map(object({
        description         = string
        initiated_login_uri = optional(string, "") // <-------- changed default value
        allowed_clients     = optional(list(string), [])
      }))
    }
    

    You might need to change the default value of allowed_clients as well. If an empty array ([]) is not valid, try changing the default value to null.