585d32b15c
Automate the PuppetDB reality import (issue #1) by querying pdbmux — the PuppetDB multiplexer whose HTTPS gateway is reachable from CI/workstations, unlike raw PuppetDB — instead of PuppetDB directly, and shaping the result to the NetBox reality side the devices module reconciles. - Add tools/backfill (Go): query pdbmux /pdb/query/v4/facts for the 13 existing physicals and emit per-host reality YAML — serial/model/UUID, every recordable interface (real NICs plus overlay/loopback/kube-lb) with MAC and CIDR IPs, and CPU/RAM/disk inventory. Filter ephemeral Calico veths and Ceph RBD volumes; take interface names from Facter, never assume them. - Emit deterministic, idempotent, yamllint-clean output into config/au/syd1/reality/<host>.yaml, generated for prodnxsr0001-0013. - Extend modules/infra with a reality variable and reality.tf creating netbox_device_interface/netbox_mac_address/netbox_ip_address/ netbox_inventory_item and device serial; wire reality only for hosts that also have an intent device. - Load reality/*.yaml in the terragrunt env; add `make backfill`; add a go vet/test woodpecker job; drop the in-cluster-only Python script. Closes #1 Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
126 lines
3.9 KiB
Terraform
126 lines
3.9 KiB
Terraform
variable "subnets" {
|
|
description = "Map of subnets keyed by name (config file basename)."
|
|
type = map(object({
|
|
prefix = string
|
|
description = optional(string, "")
|
|
site = optional(string)
|
|
router = optional(number)
|
|
dns = optional(list(string), [])
|
|
next_server = optional(string)
|
|
domain = optional(string)
|
|
dhcp = optional(object({
|
|
enabled = optional(bool, true)
|
|
start = number
|
|
stop = number
|
|
}))
|
|
}))
|
|
default = {}
|
|
}
|
|
|
|
variable "networks" {
|
|
description = <<-EOT
|
|
Named logical networks devices join, keyed by network name. `subnet` binds the
|
|
network to a subnet (its prefix is tagged net:<name> and used for device IP
|
|
allocation). gateway/dns/search are per-network provisioning constants (carried
|
|
for downstream consumers; not per-device).
|
|
EOT
|
|
type = map(object({
|
|
subnet = string
|
|
gateway = optional(string)
|
|
dns = optional(list(string), [])
|
|
search = optional(string)
|
|
}))
|
|
default = {}
|
|
}
|
|
|
|
variable "devices" {
|
|
description = <<-EOT
|
|
Intent-only device declarations keyed by device name. Reality (serial, real
|
|
interface names, MACs) is owned by discovery/PuppetDB, not this file.
|
|
`networks` maps a network name to a requested IP in CIDR form, or "" to
|
|
allocate the next-available from the network's prefix. `bootstrap_mac` is
|
|
transitional: it seeds a placeholder interface so bootapi can key the PXE boot
|
|
on MAC until the discovery image exists.
|
|
EOT
|
|
type = map(object({
|
|
site = string
|
|
role = string
|
|
model_hint = optional(string)
|
|
provision = optional(object({
|
|
profile = optional(string)
|
|
platform = optional(string)
|
|
}))
|
|
networks = optional(map(string), {})
|
|
pxe = optional(bool, false)
|
|
bootstrap_mac = optional(string)
|
|
}))
|
|
default = {}
|
|
}
|
|
|
|
variable "managed_ips" {
|
|
description = "Manually managed extra IP addresses (full CIDR form, e.g. 198.18.15.5/24)."
|
|
type = list(object({
|
|
ip = string
|
|
description = optional(string, "")
|
|
}))
|
|
default = []
|
|
}
|
|
|
|
variable "reality" {
|
|
description = <<-EOT
|
|
Per-host hardware reality keyed by device name, generated from pdbmux by
|
|
tools/backfill (see `make backfill`) — never hand-authored. It carries the
|
|
facts NetBox cannot learn from intent: serial/model/UUID, every recordable
|
|
interface (real NICs plus overlay/loopback/kube-lb) with MAC and CIDR IPs,
|
|
and CPU/RAM/disk inventory. Reality is wired into NetBox only for hosts that
|
|
also have an intent `devices/<host>.yaml`; until that intent lands, a host's
|
|
reality sits reviewed-but-inert.
|
|
EOT
|
|
type = map(object({
|
|
device = optional(string)
|
|
serial = optional(string)
|
|
model = optional(string)
|
|
uuid = optional(string)
|
|
interfaces = optional(list(object({
|
|
name = string
|
|
mac = optional(string)
|
|
mtu = optional(number)
|
|
physical = optional(bool, false)
|
|
ips = optional(list(string), [])
|
|
})), [])
|
|
inventory = optional(object({
|
|
cpu = optional(object({
|
|
model = optional(string)
|
|
cores = optional(number)
|
|
count = optional(number)
|
|
}))
|
|
memory_bytes = optional(number)
|
|
disks = optional(list(object({
|
|
name = string
|
|
model = optional(string)
|
|
serial = optional(string)
|
|
size_bytes = optional(number)
|
|
})), [])
|
|
}))
|
|
}))
|
|
default = {}
|
|
}
|
|
|
|
variable "vault_address" {
|
|
description = "Vault server address for the token data source."
|
|
type = string
|
|
default = "https://vault.service.consul:8200"
|
|
}
|
|
|
|
variable "netbox_server_url" {
|
|
description = "NetBox server base URL."
|
|
type = string
|
|
default = "https://netbox.k8s.syd1.au.unkin.net"
|
|
}
|
|
|
|
variable "kea_endpoint" {
|
|
description = "KeaAPI base URL (in-cluster ClusterIP service)."
|
|
type = string
|
|
default = "http://kea-api.dhcp-system.svc:8080"
|
|
}
|