Files
terraform-infra/modules/infra/variables.tf
unkinben 585d32b15c
ci/woodpecker/pr/plan Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/backfill-test Pipeline was successful
Backfill NetBox reality from pdbmux
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
2026-08-06 23:15:21 +10:00

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"
}