Files
puppet-catalog-tools/AGENTS.md
T
unkin-agent 6551ab9f13
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ship every cmd binary in the release
Take the binary list from cmd/ in the Makefile, the RPM packaging and the
release pipeline so a new tool ships without a pipeline edit.
2026-09-12 16:46:51 +10:00

87 lines
4.0 KiB
Markdown

# 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>/`. The Makefile, `scripts/build-rpm.sh`,
`packaging/nfpm.yaml` and the release pipeline all take the shipped list from
`cmd/`, so nothing else needs editing.
## Transport
- Catalogs: `POST /puppet/v4/catalog` with `persistence` off,
`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 puppetserver `auth.conf`.
- Facts: `GET /pdb/query/v4/nodes/<certname>/facts` on 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, so `catalog-impact`
pulls 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 `environment` and 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. `--testonly` never returns 2.
- Normalisation carries a pile of false-positive fixes (classes and exported
resources skipped, `before`/`require` dropped, `notify`/`subscribe` sorted,
File titles keyed by `path`, 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::base`
declares `($hiera_include - $hiera_exclude).include`, and some modules — the
`jellyfin` one, for instance — are applied *only* by a `hiera_include` list in
a role yaml. A manifest-only search reports them as orphans.
- `hieradata/roles/<t1>/<t2>.yaml` is a **prefix** match on the role tiers, not
an exact one. `site/roles/manifests/.../<t3>.pp` is 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 `--repo` checkout, not from `--branch`. CI runs
on the branch checkout, so the two agree there.
## Testing
```bash
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`.