Files
bootapi/docs/data-model.md
T
unkinben 8f356346eb
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Address PR review: PXE gate + callback, git-sync templates, distro catalog, k8s targets, http+https
Implements the six review comments on PR #1:

- Per-host PXE-enable gate: read NetBox pxe_enabled custom field; a known host
  with it false gets the safe local-boot script (Cobbler netboot_enabled). Add a
  token-guarded POST /provisioned/{ident} callback that clears pxe_enabled in
  NetBox, plus a %post snippet in the default kickstarts that calls it.
- Templates from a git repo: bootapi clones a templates repo and re-pulls every
  BOOTAPI_TEMPLATE_GIT_INTERVAL (default 3m), atomically swapping the template
  set (last-good kept on parse failure; embedded defaults are the startup
  fallback). Metrics for syncs/failures/generation.
- Distro catalog (catalog/*.yaml): NetBox host -> boot images/kickstart, so
  adding an OS is a YAML + template change. Ships almalinux + fedora entries
  (artifactapi remotes); debian/talos path documented.
- Boot images from the artifactapi almalinux/fedora remotes via the catalog.
- Bind resolvers, puppet server/CA and PUPPETCA_URL env file now target the k8s
  services (198.18.200.7; puppet(ca).k8s.syd1.au.unkin.net).
- Boot path served over plain HTTP (installers lack CA trust) with an optional
  parallel HTTPS listener; docs say do not 301 the boot endpoints.

New packages: internal/catalog, internal/gitsync. NetBox client gains a
pxe_enabled write (token needs that scope - noted in docs). `bootapi validate`
subcommand validates a template/catalog set for the templates-repo CI.

go build/vet clean, go test -race green, golangci-lint v2 clean, pre-commit clean.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-28 22:34:44 +10:00

5.5 KiB

Template data model

Every kickstart and iPXE template is rendered with Go text/template against a single flat value. This is the exact, stable contract template authors code against. It is assembled in internal/render.dataFor from a NetBox device (internal/netbox) plus render-time config (env/Vault).

Kickstart templates (*.ks.tmpl)

Field Type Source Notes
.Hostname string NetBox device name short name, e.g. web01
.Domain string NetBox CF domain, else BOOTAPI_DOMAIN
.FQDN string derived Hostname.Domain (or Hostname if no domain)
.Platform string NetBox platform slug e.g. almalinux9 — primary template-selection key
.OSFamily string derived from platform e.g. almalinux
.OSVersion string derived from platform e.g. 9
.Arch string fixed x86_64 (today)
.Role string NetBox device role slug e.g. kubernetes-worker
.Interfaces []Interface NetBox interfaces + IPs primary interface sorted first
.PrimaryInterface *Interface derived the NIC carrying the primary IP (or first)
.PrimaryIP string NetBox device primary_ip address only, no prefix
.Nameservers []string NetBox CF nameservers, else BOOTAPI_NAMESERVERS
.RootPasswordHash string render-time (BOOTAPI_ROOT_PASSWORD_HASH[_FILE]) crypt(3) hash; empty ⇒ lock root. Never from NetBox — see security.md
.SSHAuthorizedKeys []string render-time (BOOTAPI_SSH_AUTHORIZED_KEYS)
.PuppetServer string BOOTAPI_PUPPET_SERVER default puppet.k8s.syd1.au.unkin.net
.PuppetCAServer string BOOTAPI_PUPPET_CA_SERVER default puppetca.k8s.syd1.au.unkin.net
.PuppetCAURL string BOOTAPI_PUPPET_CA_URL written to /etc/sysconfig/puppet-initial as PUPPETCA_URL
.BaseURL string BOOTAPI_BASE_URL bootapi's own http URL
.KickstartURL string derived BaseURL/ks/Hostname
.CallbackURL string derived CallbackBaseURL/provisioned/Hostname
.ProvisionToken string render-time (BOOTAPI_PROVISION_TOKEN[_FILE]) bearer token the %post callback sends; empty ⇒ callback snippet omitted
.DistroVars map[string]string selected catalog entry's evaluated vars e.g. .DistroVars.mirror (install-tree base); empty when no catalog entry matched
.BootBaseURL string BOOTAPI_BOOT_BASE_URL legacy OS-tree base; empty when catalog-driven
.Custom map[string]any all NetBox custom fields, verbatim escape hatch for site-specific knobs without a code change

Interface

Field Type Notes
.Name string NetBox interface name, e.g. eth0
.MAC string normalized lower-case colon form
.IP string address only (empty ⇒ no IP; skip in the network stanza)
.PrefixLen int CIDR length, e.g. 24
.Netmask string dotted-quad, e.g. 255.255.255.0
.Gateway string per-IP CF gateway, else device CF gateway, else empty
.VLAN int untagged VLAN id, or 0
.Primary bool true for the NIC with the primary IP

iPXE templates (*.ipxe.tmpl)

Rendered with everything above plus:

Field Type Notes
.KernelURL string from the selected catalog entry's kernel_url (else legacy BootBaseURL/images/pxeboot/vmlinuz)
.InitrdURL string catalog initrd_url (else legacy path)
.RepoURL string OS install-tree root (KernelURL minus images/pxeboot/vmlinuz); passed as inst.repo=
.KernelArgs []string catalog entry's extra kernel args

The fallback templates (fallback-local, fallback-shell) are rendered with an empty value — they take no host data by design.

NetBox custom fields bootapi reads

Define these on the device (or, where noted, the IP address) in NetBox. All are optional; sensible fallbacks apply.

Custom field On Type Effect
domain device text DNS domain; overrides BOOTAPI_DOMAIN
gateway device / IP address text default gateway (IP-level wins)
nameservers device text comma-separated resolvers; overrides BOOTAPI_NAMESERVERS
provision_template device text force a specific catalog entry / template name
pxe_enabled device boolean gate network install (Cobbler's netboot_enabled). Unset ⇒ treated as enabled. Set false (or let the callback clear it) to boot local disk instead of re-installing.

Distro selection and the catalog

Host → distro is resolved through the distro catalog (catalog/*.yaml in the templates repo / embedded defaults). Each entry names a kickstart template, the kernel/initrd URL templates (artifactapi remotes) and extra kernel args. See template-authoring.md.

Selection precedence (both catalog Select and the kickstart-name fallback):

  1. provision_template custom field — exact catalog entry / template name.
  2. .Platform slug (e.g. almalinux9) matched against a catalog entry's match.platforms, else a template of that name.
  3. .OSFamily (e.g. fedora) matched against match.family, else a template of that name.
  4. BOOTAPI_DEFAULT_TEMPLATE (default almalinux9).

The version substituted into the catalog URLs is .OSVersion (the numeric suffix of the platform slug), falling back to the entry's version_default.