Are there optional attributes for map(object({ in variables.tf?

Hello, is there a way to set a map object in variables.tf to be optional? I have for_loop for my subnets , , only one subnet requires “delegation” parameter and the rest don’t. Is there a way that I can make this “delegation” optional for the rest of the ? My auto.tfvars file is complaining that the rest of the subnets don’t have this “delegation” attribute.

main.tf file code below:

resource "azurerm_subnet" "snets" {
  for_each             = var.snets
  name                 = each.value["name"]
  resource_group_name  = azurerm_resource_group.rgs[each.value["resource_group_name"]].name
  virtual_network_name = azurerm_virtual_network.vnets[each.value["virtual_network_name"]].name
  address_prefixes     = each.value["address_prefixes"]
  dynamic "delegation" {
    for_each = each.value["delegation"]
    content {
      name = each.value["name"]
      dynamic "service_delegation" {
        for_each = delegation.value["service_delegation "]
        content {
          name    = service_delegation.value["name"]
          actions = service_delegation.value["actions"]
        }
      }
    }
  }
}

Variables.tf file code below:

variable "snets" {
  description = "Map of Subnets"
  type = map(object({
    name                 = string
    resource_group_name  = string
    virtual_network_name = string
    address_prefixes     = list(string)

    delegation = map(object({
      name = string
      service_delegation = map(object({
        name    = string
        actions = list(string)
      }))
    }))

  }))
}

Auto.tfvars file code below:

snets = {  
ApplicationGatewaySubnet = {
    name                 = "ApplicationGatewaySubnet"
    resource_group_name  = "rg-spoke-prod-eus-01"
    virtual_network_name = "vnet-app-spoke-prod-eus-01"
    address_prefixes     = ["10.0.17.0/24"]
    #this subnet does not need delegation and gives error that attribute “delegation” is required
  }

  snet-app-integration-prod-eus-01 = {
    name                 = "snet-app-integration-prod-eus-01"
    resource_group_name  = "rg-spoke-prod-eus-01"
    virtual_network_name = "vnet-app-spoke-prod-eus-01"
    address_prefixes     = ["10.0.18.0/26"]
    id                   = "/subscriptions/xxxxxx/resourceGroups/rg-spoke-prod-eus-01/providers/Microsoft.Network/virtualNetworks/vnet-app-spoke-prod-eus-01/subnets/snet-app-integration-prod-eus-01"
    delegation = {
      deleg = {
        name = "ap-delegation"
        service_delegation = {
          serv_deleg = {
            name    = "Microsoft.Web/serverFarms"
            actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
          }
        }
      }
    }
  }

Hi @mmilan,

The idea of “optional attributes” relates only to object types, because object types are the only types that have attributes in Terraform.

The “delegation” attribute you are asking about is an attribute of an object type, so you can indeed make it optional. In this case I would suggest also setting the default to be an empty map, since then you can safely use it in your dynamic block for_each without needing to worry about the distinction between the attribute being omitted and the attribute being explicitly set to an empty map:

    delegation = optional(map(object({
      name = string
      service_delegation = map(object({
        name    = string
        actions = list(string)
      }))
    })), {})
1 Like

Thank you so much @apparentlymart , it worked! I appreciate your time and expertise!