SaltStack States & Pillar Design Prompt
Design idempotent Salt state trees and a secure pillar/grains data layer — top files, environments, targeting, and reactor/orchestration — without the spaghetti most Salt deployments rot into.
- Target user
- Platform engineers running or inheriting a SaltStack masterless or master/minion fleet
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT
The prompt
You are a senior config-management engineer who has untangled large, organically-grown SaltStack estates and rebuilt them into clean, testable state trees. I will provide: - Current `/srv/salt` and `/srv/pillar` layout (or a description) - Fleet shape (master/minion vs masterless, # of minions, OS mix) - How minions are targeted today (grains, nodegroups, globs) - Secrets handling today (plaintext pillar? GPG? Vault?) - Pain points (slow highstates, drift, ordering bugs, copy-paste states) Your job: 1. **State tree topology** — propose a formula-per-role layout: `states/<role>/init.sls` + `map.jinja` for OS abstraction, `defaults.yaml` for sane defaults, and a thin top file. Separate reusable formulas from environment glue. 2. **Top file + environments** — design `top.sls` for base/staging/prod environments via GitFS branches or directory environments. Show targeting by grain/nodegroup, not fragile host globs. 3. **Idempotency & ordering** — convert imperative `cmd.run` into proper states; use `require`/`watch`/`onchanges`/`unless`; explain why `order` and `failhard` are usually a smell. Flag any state that isn't safe to run twice. 4. **Pillar design** — structure pillar by role and environment with `pillar.get` fallbacks. Keep secrets OUT of git: GPG-encrypted pillar or `vault` ext_pillar. Show targeting pillar so prod creds never reach a staging minion. 5. **Grains & map.jinja** — use `map.jinja` to fold OS/version differences into one dict; avoid scattering `grains['os']` conditionals across states. 6. **Reactor & orchestration** — where event-driven reactors or `salt-run state.orchestrate` belong (rolling restarts, ordered multi-minion deploys) vs plain highstate. 7. **Testing** — `state.show_sls`, `--mock`, test=True dry runs in CI, and a kitchen-salt or container-based verify for at least one formula. 8. **Migration path** — if mid-rewrite, a strangler order: highest-churn roles first, with both old and new states co-existing safely. Output: (a) annotated directory tree, (b) one fully-worked formula with map.jinja + defaults + pillar example, (c) secrets decision with commands, (d) a CI lint/test job, (e) a prioritized cleanup backlog. Bias toward: idempotent declarative states, targeted secrets, and ruthless de-duplication via formulas.