Postgres-backed External Node Classifier for Puppet, replacing Cobbler. - encapi HTTP server (chi + pgx): read/write API + two ENC document shapes (reshaped for the exec terminus; cobbler-wire for enc_direct_facts.rb) - encapi-cli: classify/node/role/status CRUD + import-cobbler seeder - pkg/client Go SDK; unit tests across all packages (DB via testcontainers) - Dockerfile (distroless), Makefile, nfpm RPM (encapi-cli + encapi-enc wrapper), Woodpecker CI, docs/cutover.md
3.2 KiB
Cutover: Cobbler ENC → encapi
Today Cobbler is Puppet's ENC. Two consumers hit
http://cobbler.main.unkin.net/cblr/svc/op/puppet/hostname/<host>:
-
The exec ENC —
puppet-prodsets, insite/profiles/manifests/puppet/server.pp:node_terminus = exec external_nodes = /opt/cobbler-enc/cobbler-enc/opt/cobbler-enc/cobbler-enc(templated fromsite/profiles/templates/puppet/server/cobbler-enc.erb) fetches Cobbler and reshapes it (list-form classes, dropsenvironmentwhentesting, addsenc_role/enc_env). -
The
enc_role/enc_envfacts —modules/libs/lib/facter/enc_direct_facts.rb, a fact on every node, fetches the same Cobbler endpoint (cached 7d at/var/cache/puppet_enc.yaml) and derivesenc_role = classes.keys.first,enc_env = environment. Those facts driveenc_role_tier1/2/3+enc_role_path, i.e. the whole Hiera hierarchy.
encapi serves drop-in replacements for both.
1. Seed encapi from the current estate
export ENCAPI_URL=https://encapi.k8s.syd1.au.unkin.net
export ENCAPI_WRITE_TOKEN=…
encapi-cli import-cobbler --dry-run # review
encapi-cli import-cobbler # writes statuses, roles, nodes
import-cobbler lists hosts from PuppetDB
(http://puppetdbapi.service.consul:8080), reads each host's Cobbler ENC, and
creates the derived status, role, and node.
2. Repoint the exec ENC (profiles::puppet::cobbler_enc)
Install the CLI RPM on the puppet masters (it ships encapi-cli,
/usr/local/bin/encapi-enc, and /etc/encapi/enc.conf), set
ENCAPI_URL in /etc/encapi/enc.conf, and point Puppet at the wrapper:
node_terminus = exec
external_nodes = /usr/local/bin/encapi-enc
encapi-enc <certname> runs encapi-cli classify <certname>, which returns the
identical reshaped document (GET /api/v1/nodes/<certname>/enc).
3. Repoint the enc_direct_facts.rb fact
Change only the base URL in enc_direct_facts.rb:
uri = URI("https://encapi.k8s.syd1.au.unkin.net/cblr/svc/op/puppet/hostname/#{...}")
encapi's /cblr/svc/op/puppet/hostname/<host> returns the cobbler-wire shape
(classes as a map, environment always present), so classes.keys.first and
environment still resolve. No other fact logic changes.
4. Verify before flipping
For a sample of hosts, diff the old and new output:
diff <(curl -s "http://cobbler.main.unkin.net/cblr/svc/op/puppet/hostname/$H") \
<(curl -s "https://encapi.k8s.syd1.au.unkin.net/cblr/svc/op/puppet/hostname/$H")
diff <(/opt/cobbler-enc/cobbler-enc "$H") \
<(encapi-cli classify "$H")
The classes/environment/enc_role/enc_env fields must match. (Cobbler's
provisioning params — epel, tree, from_cobbler, operatingsystemrelease —
are intentionally dropped: they are unused by the Puppet manifests. If a future
need arises, wire ENCAPI_DISTRO_API_URL to the kickstart-replacement API and
they reappear under parameters.)
5. Decommission
Once masters and agents are repointed and a Puppet run is clean, retire
profiles::puppet::cobbler_enc and Cobbler's ENC role. Cobbler can keep doing
provisioning/kickstart; only its ENC duty moves to encapi.