diff --git a/modules/meraki-site/main.tf b/modules/meraki-site/main.tf index 794cbfc..85161b4 100755 --- a/modules/meraki-site/main.tf +++ b/modules/meraki-site/main.tf @@ -16,21 +16,39 @@ data "meraki_networks" "net" { organization_id = data.meraki_organization.org.id } +# Stacks de switches en la red (para resolución dinámica de seriales por nombre) +data "meraki_switch_stacks" "stacks" { + network_id = local.network_id +} + # Local para extraer el network_id exacto de la lista de redes locals { network_id = [for n in data.meraki_networks.net.items : n.id if n.name == var.network_name][0] - # Expande rangos de puertos: "1-24" -> ["1","2",...,"24"], "1" -> ["1"] + # Helper: expande un port_range en lista de port_ids + # "1-48" -> ["1","2",...,"48"] | "1" -> ["1"] + _expand_range = { + for config in concat(var.switch_port_configs, var.switch_stack_port_configs) : + "${try(config.serial, config.stack_name)}:${config.port_range}" => ( + length(split("-", config.port_range)) == 2 + ? [for i in range( + tonumber(split("-", config.port_range)[0]), + tonumber(split("-", config.port_range)[1]) + 1 + ) : tostring(i)] + : [config.port_range] + ) + } + + # Mapa de nombre de stack -> lista de seriales de sus miembros + stack_serials = { + for stack in data.meraki_switch_stacks.stacks.items : + stack.name => stack.serials + } + + # Expande switch_port_configs (serial explícito) en entradas individuales switch_ports_expanded = flatten([ for config in var.switch_port_configs : [ - for port_id in ( - length(split("-", config.port_range)) == 2 - ? [for i in range( - tonumber(split("-", config.port_range)[0]), - tonumber(split("-", config.port_range)[1]) + 1 - ) : tostring(i)] - : [config.port_range] - ) : { + for port_id in local._expand_range["${config.serial}:${config.port_range}"] : { key = "${config.serial}:${port_id}" serial = config.serial port_id = port_id @@ -42,6 +60,31 @@ locals { } ] ]) + + # Expande switch_stack_port_configs (por nombre de stack) en entradas individuales + # Aplica el mismo port_range a TODOS los miembros del stack + stack_ports_expanded = flatten([ + for config in var.switch_stack_port_configs : [ + for serial in local.stack_serials[config.stack_name] : [ + for port_id in local._expand_range["${config.stack_name}:${config.port_range}"] : { + key = "${serial}:${port_id}" + serial = serial + port_id = port_id + name = config.name + type = config.type + vlan = config.vlan + access_policy_type = config.access_policy_type + access_policy_number = config.access_policy_number + } + ] + ] + ]) + + # Unión de ambas listas para el resource meraki_switch_port + all_ports = merge( + { for p in local.switch_ports_expanded : p.key => p }, + { for p in local.stack_ports_expanded : p.key => p } + ) } # --- CONFIGURACIÓN GATEWAY (MX) --- @@ -122,9 +165,9 @@ resource "meraki_switch_access_policy" "dot1x" { } # 6. Configuración de puertos de switch -# port_range soporta rango "1-24" o puerto único "1" +# switch_port_configs: serial explícito | switch_stack_port_configs: por nombre de stack resource "meraki_switch_port" "ports" { - for_each = { for p in local.switch_ports_expanded : p.key => p } + for_each = local.all_ports depends_on = [meraki_switch_access_policy.dot1x] serial = each.value.serial diff --git a/modules/meraki-site/variables.tf b/modules/meraki-site/variables.tf index 239eecd..e2f0500 100755 --- a/modules/meraki-site/variables.tf +++ b/modules/meraki-site/variables.tf @@ -119,3 +119,18 @@ variable "switch_port_configs" { description = "Puertos de switch a configurar. access_policy_number referencia el número de la política creada en switch_access_policies." } +# Configuración de puertos por nombre de stack (resolución dinámica de seriales) +variable "switch_stack_port_configs" { + type = list(object({ + stack_name = string # nombre exacto del stack en Meraki Dashboard + port_range = string # puerto único "1" o rango "1-48" + name = optional(string, "") + type = optional(string, "access") + vlan = optional(number, null) + access_policy_type = optional(string, "Open") + access_policy_number = optional(number, null) + })) + default = [] + description = "Puertos de stack a configurar por nombre. Terraform resuelve los seriales de todos los miembros automáticamente." +} + diff --git a/sites/BCN01-LAB/main.tf b/sites/BCN01-LAB/main.tf index b460758..874047f 100755 --- a/sites/BCN01-LAB/main.tf +++ b/sites/BCN01-LAB/main.tf @@ -29,6 +29,7 @@ module "bcn01_lab" { firewall_rules = var.firewall_rules wireless_ssids = var.wireless_ssids radius_secret = var.radius_secret - switch_access_policies = var.switch_access_policies - switch_port_configs = var.switch_port_configs + switch_access_policies = var.switch_access_policies + switch_port_configs = var.switch_port_configs + switch_stack_port_configs = var.switch_stack_port_configs } diff --git a/sites/BCN01-LAB/switch.auto.tfvars b/sites/BCN01-LAB/switch.auto.tfvars index 2613f9c..380a185 100644 --- a/sites/BCN01-LAB/switch.auto.tfvars +++ b/sites/BCN01-LAB/switch.auto.tfvars @@ -73,3 +73,42 @@ switch_access_policies = [ # # ] switch_port_configs = [] + +# --- PUERTOS DE STACK --- +# Terraform resuelve automáticamente los seriales de todos los miembros del stack. +# El stack_name debe coincidir exactamente con el nombre en Dashboard > Switches > Stacks. +# Terraform aplicará el mismo port_range a CADA switch del stack (ambos de 48 puertos). +# +# Ejemplo para bcn01-lab-stack01 (2x 48 puertos): +# switch_stack_port_configs = [ +# +# # Puertos 1-44: acceso general con 802.1X (PCs, portátiles) +# { +# stack_name = "bcn01-lab-stack01" +# port_range = "1-44" +# type = "access" +# vlan = 100 # ACCESS - fallback si Okta no devuelve VLAN +# access_policy_type = "Custom access policy" +# access_policy_number = 1 # id de la política DOT1X-CORPO +# }, +# +# # Puertos 45-46: impresoras (VLAN fija, sin 802.1X) +# { +# stack_name = "bcn01-lab-stack01" +# port_range = "45-46" +# type = "access" +# vlan = 103 # PRINTERS +# access_policy_type = "Open" +# }, +# +# # Puertos 47-48: APs (VLAN fija, sin 802.1X) +# { +# stack_name = "bcn01-lab-stack01" +# port_range = "47-48" +# type = "access" +# vlan = 108 # APs +# access_policy_type = "Open" +# }, +# +# ] +switch_stack_port_configs = [] diff --git a/sites/BCN01-LAB/variables.tf b/sites/BCN01-LAB/variables.tf index ef19297..c60d991 100755 --- a/sites/BCN01-LAB/variables.tf +++ b/sites/BCN01-LAB/variables.tf @@ -110,3 +110,18 @@ variable "switch_port_configs" { default = [] description = "Puertos de switch a configurar con 802.1X. Requiere serial del switch." } + +# Configuración de puertos por nombre de stack +variable "switch_stack_port_configs" { + type = list(object({ + stack_name = string + port_range = string + name = optional(string, "") + type = optional(string, "access") + vlan = optional(number, null) + access_policy_type = optional(string, "Open") + access_policy_number = optional(number, null) + })) + default = [] + description = "Puertos de stack a configurar por nombre. Terraform resuelve los seriales automáticamente." +}