Azure / terraform-azurerm-avm-ptn-virtualwan

MIT License
5 stars 11 forks source link

Bug: azurerm_vpn_site link block uses list rather than map object resulting in all blocks being recreated when adding and removing links #8

Closed OmnipotentOwl closed 10 months ago

OmnipotentOwl commented 10 months ago

Summary

When attempting to provision or update a link block inside an azurerm_vpn_site using the module the reordering or changing of the list will cause Terraform to attempt to reprovision all link blocks which changes the order for the index operation for subsequent azurerm_vpn_gateway_connection usage.

Remediation

Changing the variable and resource configuration for the vpn_sites links from a list to a map will provide stable identifiers for usage and prevent unnecessary churn and misconfiguration by index mismatch on the vpn_site_connections variable

variable "vpn_sites" {
  type = map(object({
    name = string
    # Name of the virtual hub
    virtual_hub_name = string
    links = map(object({  <--- changed to a map from a list
      name = string
      bgp = optional(object({
        asn             = number
        peering_address = string
      }))
      fqdn          = optional(string)
      ip_address    = optional(string)
      provider_name = optional(string)
      speed_in_mbps = optional(number)
      }
    ))
    address_cidrs = optional(list(string))
    device_model  = optional(string)
    device_vendor = optional(string)
    o365_policy = optional(object({
      traffic_category = object({
        allow_endpoint_enabled    = optional(bool)
        default_endpoint_enabled  = optional(bool)
        optimize_endpoint_enabled = optional(bool)
      })
    }))
    tags = optional(map(string))
  }))
  description = "S2S VPN Sites parameter"
  default     = {}
}
resource "azurerm_vpn_site" "vpn_site" {
  for_each = local.vpn_sites != null ? local.vpn_sites : {}

  name                = each.value.name
  location            = azurerm_virtual_hub.virtual_hub[each.value.virtual_hub_key].location
  resource_group_name = azurerm_virtual_hub.virtual_hub[each.value.virtual_hub_key].resource_group_name
  virtual_wan_id      = azurerm_virtual_wan.virtual_wan.id
  address_cidrs       = try(each.value.address_cidrs, null)
  dynamic "link" {
    for_each = each.value.links != null ? each.value.links : {}  <-- change this to a map

    content {
      name          = link.value.name
      ip_address    = try(link.value.ip_address, null)
      fqdn          = try(link.value.fqdn, null)
      speed_in_mbps = link.value.speed_in_mbps

      dynamic "bgp" {
        for_each = link.value.bgp != null ? [link.value.bgp] : []

        content {
          asn             = bgp.value.asn
          peering_address = bgp.value.peering_address
        }
      }
      provider_name = try(link.value.provider_name, null)
    }
  }
  device_model  = try(each.value.device_model, null)
  device_vendor = try(each.value.device_vendor, null)
  o365_policy {
    traffic_category {
      allow_endpoint_enabled    = try(each.value.o365_policy.traffic_category.allow_endpoint_enabled, null)
      default_endpoint_enabled  = try(each.value.o365_policy.traffic_category.default_endpoint_enabled, null)
      optimize_endpoint_enabled = try(each.value.o365_policy.traffic_category.optimize_endpoint_enabled, null)
    }
  }
  tags = try(each.value.tags, {})
}