feat(BCN01-LAB): sync manual Dashboard changes to Terraform

- Management VLAN switches → 109
- Puerto 47 stack: trunk, native VLAN 109
- SVI stack bcn01-lab-stack01: VLAN 109, 10.2.55.2/24, GW 10.2.55.1
- MX puerto 7: trunk, native VLAN 109
- Firewall: allow MANAGEMENT → internet (primera regla)
- Puerto 1 eqt-lab-st01-sw01: VLAN 110 (SERVERS)
This commit is contained in:
Jose Martinez
2026-03-25 18:24:47 +01:00
parent 88ae4a7574
commit c86569436b
7 changed files with 267 additions and 12 deletions
+84 -5
View File
@@ -21,6 +21,11 @@ data "meraki_switch_stacks" "stacks" {
network_id = local.network_id
}
# Dispositivos de la red (para resolución dinámica de serial por nombre de switch)
data "meraki_devices" "devices" {
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]
@@ -28,8 +33,8 @@ locals {
# 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}" => (
for config in concat(var.switch_port_configs, var.switch_stack_port_configs, var.switch_named_port_configs) :
"${try(config.serial, try(config.stack_name, config.switch_name))}:${config.port_range}" => (
length(split("-", config.port_range)) == 2
? [for i in range(
tonumber(split("-", config.port_range)[0]),
@@ -45,6 +50,19 @@ locals {
stack.name => stack.serials
}
# Mapa de nombre de stack -> ID del stack
stack_ids = {
for stack in data.meraki_switch_stacks.stacks.items :
stack.name => stack.id
}
# Mapa de nombre de dispositivo -> serial
device_serials = {
for d in data.meraki_devices.devices.items :
d.name => d.serial
if d.name != null && d.name != ""
}
# Expande switch_port_configs (serial explícito) en entradas individuales
switch_ports_expanded = flatten([
for config in var.switch_port_configs : [
@@ -55,6 +73,7 @@ locals {
name = config.name
type = config.type
vlan = config.vlan
allowed_vlans = config.allowed_vlans
access_policy_type = config.access_policy_type
access_policy_number = config.access_policy_number
}
@@ -73,6 +92,7 @@ locals {
name = config.name
type = config.type
vlan = config.vlan
allowed_vlans = config.allowed_vlans
access_policy_type = config.access_policy_type
access_policy_number = config.access_policy_number
}
@@ -80,10 +100,28 @@ locals {
]
])
# Unión de ambas listas para el resource meraki_switch_port
# Expande switch_named_port_configs (por nombre de switch) en entradas individuales
named_ports_expanded = flatten([
for config in var.switch_named_port_configs : [
for port_id in local._expand_range["${config.switch_name}:${config.port_range}"] : {
key = "${local.device_serials[config.switch_name]}:${port_id}"
serial = local.device_serials[config.switch_name]
port_id = port_id
name = config.name
type = config.type
vlan = config.vlan
allowed_vlans = config.allowed_vlans
access_policy_type = config.access_policy_type
access_policy_number = config.access_policy_number
}
]
])
# Unión de todas las 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 }
{ for p in local.stack_ports_expanded : p.key => p },
{ for p in local.named_ports_expanded : p.key => p }
)
}
@@ -175,8 +213,49 @@ resource "meraki_switch_port" "ports" {
name = each.value.name
type = each.value.type
vlan = each.value.vlan
vlan = each.value.vlan
allowed_vlans = each.value.type == "trunk" ? each.value.allowed_vlans : null
access_policy_type = each.value.access_policy_type
access_policy_number = each.value.access_policy_number
}
# 7. VLAN de gestión de los switches del site
resource "meraki_networks_switch_settings" "mgmt_vlan" {
count = var.switch_management_vlan != null ? 1 : 0
network_id = local.network_id
management_vlan = var.switch_management_vlan
}
# 8. Interfaces de enrutamiento L3 en stacks (SVIs para acceso de gestión al Dashboard)
resource "meraki_networks_switch_stacks_routing_interfaces" "stack_interfaces" {
for_each = {
for i in var.stack_routing_interfaces :
"${i.stack_name}:${i.vlan_id}" => i
}
network_id = local.network_id
switch_stack_id = local.stack_ids[each.value.stack_name]
name = each.value.name
vlan_id = each.value.vlan_id
ip_address = each.value.ip_address
subnet = each.value.subnet
default_gateway_ip = each.value.default_gateway
}
# 9. Puertos del firewall MX
resource "meraki_appliance_port" "ports" {
for_each = { for p in var.appliance_ports : p.port_id => p }
network_id = local.network_id
port_id = each.value.port_id
enabled = each.value.enabled
type = each.value.type
vlan = each.value.vlan
allowed_vlans = each.value.type == "trunk" ? each.value.allowed_vlans : null
drop_untagged_traffic = each.value.drop_untagged_traffic
}
+55
View File
@@ -112,6 +112,7 @@ variable "switch_port_configs" {
name = optional(string, "")
type = optional(string, "access")
vlan = optional(number, null)
allowed_vlans = optional(string, "all")
access_policy_type = optional(string, "Open")
access_policy_number = optional(number, null)
}))
@@ -127,6 +128,7 @@ variable "switch_stack_port_configs" {
name = optional(string, "")
type = optional(string, "access")
vlan = optional(number, null)
allowed_vlans = optional(string, "all")
access_policy_type = optional(string, "Open")
access_policy_number = optional(number, null)
}))
@@ -134,3 +136,56 @@ variable "switch_stack_port_configs" {
description = "Puertos de stack a configurar por nombre. Terraform resuelve los seriales de todos los miembros automáticamente."
}
# Configuración de puertos por nombre de switch (resolución dinámica de serial por nombre)
variable "switch_named_port_configs" {
type = list(object({
switch_name = string # nombre exacto del switch en Meraki Dashboard
port_range = string # puerto único "1" o rango "1-24"
name = optional(string, "")
type = optional(string, "access")
vlan = optional(number, null)
allowed_vlans = optional(string, "all")
access_policy_type = optional(string, "Open")
access_policy_number = optional(number, null)
}))
default = []
description = "Puertos de switch a configurar por nombre de dispositivo. Terraform resuelve el serial automáticamente."
}
# VLAN de gestión de los switches del site
variable "switch_management_vlan" {
type = number
default = null
description = "VLAN ID de gestión para los switches del site (Dashboard > Switch > Switch settings > Management VLAN)"
}
# Interfaces de enrutamiento L3 en stacks de switches
variable "stack_routing_interfaces" {
type = list(object({
stack_name = string # nombre exacto del stack en Meraki Dashboard
name = string # nombre descriptivo de la interfaz
vlan_id = number
ip_address = string # IP estática del stack en esta VLAN
subnet = string # subred en formato CIDR, ej: "10.2.55.0/24"
default_gateway = optional(string, null) # gateway para acceso a internet
dns1 = optional(string, null) # DNS primario
dns2 = optional(string, null) # DNS secundario
}))
default = []
description = "Interfaces L3 (SVIs) en stacks de switches para acceso de gestión al Dashboard de Meraki."
}
# Puertos del firewall MX
variable "appliance_ports" {
type = list(object({
port_id = string
enabled = optional(bool, true)
type = optional(string, "access") # "access" o "trunk"
vlan = optional(number, null) # VLAN nativa en trunk, o VLAN de acceso
allowed_vlans = optional(string, "all") # solo para trunk
drop_untagged_traffic = optional(bool, false)
}))
default = []
description = "Configuración de puertos del firewall MX (LAN ports)."
}