8093933500
Work out which hosts a puppet-prod change can affect, so a catalog test can
fan out over exactly those hosts instead of the whole estate.
- add cmd/catalog-impact and internal/impact
- map hieradata paths onto fact selectors from the hiera hierarchy
- trace manifest classes back to role classes through include, contain,
class {} and hiera_include, to a fixed point
- fetch the estate fact table from pdbmux in one query via FactsByName
- widen to all hosts, loudly, for any path that matches no rule
- ship the binary and its completions in the RPM
4.0 KiB
4.0 KiB
AGENTS.md
Project Overview
Go CLI tooling for the Puppet estate, shipped as one RPM
(puppet-catalog-tools). Every tool is a separate main package under cmd/;
shared code lives in internal/.
catalog-diff— compiles a host's catalog twice (base environment and the environment built from the branch under test) over the puppetserver API and diffs the result.catalog-impact— maps a control repo change onto the hosts it can affect, by reading hieradata paths as hierarchy positions and tracing manifest classes backwards to role classes.
Structure
cmd/catalog-diff/ # the CLI (flags, exit codes, orchestration)
cmd/catalog-impact/ # the CLI (flags, output modes)
internal/catalog/ # catalog types, normalisation, diff engine, renderers,
# branch.go (BranchToEnvironment)
internal/puppetserver/ # mTLS client for POST /puppet/v4/catalog + /status/v1/simple
internal/impact/ # path -> selector rules, repo index, reverse lookup,
# estate fact table, renderers
internal/pdbmux/ # unauthenticated fact client for pdbmux
internal/config/ # XDG config file + env var loading
packaging/nfpm.yaml # RPM spec (envsubst-templated)
scripts/build-rpm.sh # completions + nfpm packaging
.woodpecker/ # CI: build, test, pre-commit (PR) + release (tag)
Adding a binary: create cmd/<name>/, add the name to BINARIES in the
Makefile and to scripts/build-rpm.sh, and add its files to
packaging/nfpm.yaml.
Transport
- Catalogs:
POST /puppet/v4/catalogwithpersistenceoff,options.prefer_requested_environment: true, facts and synthesised trusted facts in the body. Auth is client mTLS against the estate Puppet CA; the certname must be allowed in the puppetserverauth.conf. - Facts:
GET /pdb/query/v4/nodes/<certname>/factson pdbmux, falling back to/pdb/query/v4/factsets/<certname>. No auth, no client cert. - Estate-wide facts: one AST query against
/pdb/query/v4/facts(pdbmux.Client.FactsByName). The estate is ~150 nodes, socatalog-impactpulls the whole table once and filters in Go rather than querying per host. - The two services have different auth models and stay separate clients.
Gotchas
- An ENC-supplied environment outranks the requested one. Every compile checks
the returned catalog's
environmentand hard-fails on a mismatch — never relax that check. - Branch names are converted the way g10k does it (
\W->_, case preserved). The rule lives in one function,catalog.BranchToEnvironment. - Exit codes are a contract: 0 same, 1 compile failed, 2 differences, 3
transport/auth/mismatch/usage.
--testonlynever returns 2. - Normalisation carries a pile of false-positive fixes (classes and exported
resources skipped,
before/requiredropped,notify/subscribesorted, File titles keyed bypath, datatype-only changes suppressed). Removing one floods the output with noise.
catalog-impact gotchas
- The reverse lookup must search hieradata as well as manifests.
profiles::basedeclares($hiera_include - $hiera_exclude).include, and some modules — thejellyfinone, for instance — are applied only by ahiera_includelist in a role yaml. A manifest-only search reports them as orphans. hieradata/roles/<t1>/<t2>.yamlis a prefix match on the role tiers, not an exact one.site/roles/manifests/.../<t3>.ppis exact.- The bias is to over-include: an unmapped path widens to the whole estate and says so on stderr. Never turn a widening into a silent empty result.
- The repo index comes from the
--repocheckout, not from--branch. CI runs on the branch checkout, so the two agree there.
Testing
make test # go test -v -race ./...
Everything is stubbed with httptest (a TLS server for puppetserver, a plain
one for pdbmux) — no live estate access is required. Renderer output is
covered by golden files under internal/catalog/testdata; regenerate with
go test ./internal/catalog -update.