9a6f775300
Scope now spans devices and provisioning, not just IPAM. - rename module/consul-path/role ipam -> infra - networks config (subnet binding + gateway/dns/search constants); prefixes tagged net:<name> - intent-only devices module: netbox_device + device_type/role/manufacturer, static or next-available IPs (sticky via ignore_changes), transitional bootstrap_mac interface for bootapi PXE keying - seed 6 pending hosts prodnxsr0014-0019 (mgmt IPs .14-.19, optiplex-3070) - ci/puppetdb_backfill.py: emit NetBox reality (serial/model/uuid/interfaces) for existing hosts Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
94 lines
2.8 KiB
Terraform
94 lines
2.8 KiB
Terraform
locals {
|
|
# Netmask suffix per subnet, e.g. "24".
|
|
masks = { for k, v in var.subnets : k => split("/", v.prefix)[1] }
|
|
|
|
# Subnets that request a DHCP scope.
|
|
dhcp_subnets = { for k, v in var.subnets : k => v if try(v.dhcp.enabled, false) }
|
|
|
|
# Subnets that declare a gateway.
|
|
gateways = { for k, v in var.subnets : k => v if v.router != null }
|
|
|
|
# Distinct NetBox site slugs referenced by any subnet or device.
|
|
sites = toset(concat(
|
|
[for v in var.subnets : v.site if v.site != null],
|
|
[for d in var.devices : d.site],
|
|
))
|
|
|
|
# net:<name> tags to apply to each subnet's prefix (a prefix may back many networks).
|
|
prefix_net_tags = {
|
|
for sk in keys(var.subnets) : sk => [
|
|
for nname, n in var.networks : "net:${nname}" if n.subnet == sk
|
|
]
|
|
}
|
|
}
|
|
|
|
data "netbox_site" "this" {
|
|
for_each = local.sites
|
|
slug = each.value
|
|
}
|
|
|
|
# One tag per network so prefixes can be discovered by network membership.
|
|
resource "netbox_tag" "network" {
|
|
for_each = var.networks
|
|
|
|
name = "net:${each.key}"
|
|
slug = "net-${each.key}"
|
|
}
|
|
|
|
resource "netbox_prefix" "this" {
|
|
for_each = var.subnets
|
|
|
|
prefix = each.value.prefix
|
|
status = "active"
|
|
description = each.value.description
|
|
site_id = each.value.site != null ? tonumber(data.netbox_site.this[each.value.site].id) : null
|
|
tags = [for t in local.prefix_net_tags[each.key] : t]
|
|
|
|
depends_on = [netbox_tag.network]
|
|
}
|
|
|
|
# Role tagging a range as DHCP-managed; created once and shared by every range.
|
|
resource "netbox_ipam_role" "dhcp" {
|
|
name = "dhcp"
|
|
slug = "dhcp"
|
|
}
|
|
|
|
resource "netbox_ip_range" "dhcp" {
|
|
for_each = local.dhcp_subnets
|
|
|
|
start_address = "${cidrhost(each.value.prefix, each.value.dhcp.start)}/${local.masks[each.key]}"
|
|
end_address = "${cidrhost(each.value.prefix, each.value.dhcp.stop)}/${local.masks[each.key]}"
|
|
role_id = netbox_ipam_role.dhcp.id
|
|
status = "active"
|
|
description = "DHCP pool for ${each.key}"
|
|
}
|
|
|
|
resource "netbox_ip_address" "gateway" {
|
|
for_each = local.gateways
|
|
|
|
ip_address = "${cidrhost(each.value.prefix, each.value.router)}/${local.masks[each.key]}"
|
|
status = "active"
|
|
description = "gateway"
|
|
}
|
|
|
|
resource "netbox_ip_address" "managed" {
|
|
for_each = { for m in var.managed_ips : m.ip => m }
|
|
|
|
ip_address = each.value.ip
|
|
status = "active"
|
|
description = each.value.description
|
|
}
|
|
|
|
resource "kea_subnet" "this" {
|
|
for_each = local.dhcp_subnets
|
|
|
|
name = each.key
|
|
cluster_ref = "kea"
|
|
subnet = each.value.prefix
|
|
pools = ["${cidrhost(each.value.prefix, each.value.dhcp.start)}-${cidrhost(each.value.prefix, each.value.dhcp.stop)}"]
|
|
routers = each.value.router != null ? [cidrhost(each.value.prefix, each.value.router)] : null
|
|
dns_servers = each.value.dns
|
|
next_server = each.value.next_server
|
|
domain_name = each.value.domain
|
|
}
|