Salt Compatibility
Zester is designed so that most SaltStack state files (.sls) port to Zester
state files (.zy) with little or no change. This page summarizes the
Salt features Zester supports natively. Use zester-migrate
to convert .sls files and flag anything that needs manual review.
State language
Requisites
All Salt requisites are supported, including the inverse (_in) forms:
| Requisite | Inverse | Behavior |
|---|---|---|
require | require_in | Run after the target succeeds |
watch | watch_in | Like require; re-apply when the target changed |
onchanges | onchanges_in | Run only if the target changed |
onfail | onfail_in | Run only if the target failed |
prereq | prereq_in | Run before the target, but only if the target would change |
listen | listen_in | React to a change (aliased to watch) |
Requisite targets accept both Zester (pkg.installed:nginx) and Salt dict
(- pkg: nginx) forms.
Execution guards
onlyif: run only if every command exits0.unless: skipped if any command exits0(runs only when all exit non-zero).
A state whose guard is not met is a no-op (reports no change, with the diff
skipped: guard condition not met), not a failure.
run_migration:
cmd.run:
- command: /opt/app/bin/migrate
- unless: /opt/app/bin/is-migratedGeneric attributes
order: N(alsofirst/last) — ordering within a DAG level; requisite ordering always takes precedence.retry: Norretry: {attempts: N, interval: S}— retry on failure.intervalis in seconds (default 10). Retries apply in apply/revert runs, not in test mode.failhard: true— a failure aborts the remaining DAG levels (skipped withSkipReason: "failhard_abort").names: [...]— expand one declaration into one state per name.
module.run
Both the classic name: form and the newer dotted-key form are supported:
refresh:
module.run:
- name: cmd.run
- command: apt-get update
flag:
module.run:
- file.touch:
path: /var/run/flagSee Dependencies & Requisites for full details.
Dry run (test=True)
Preview changes without applying them:
zester 'web-*' state.highstate --test
zester 'web-01' state.apply webserver test=TrueSee Execution Model → Dry Run.
Modules
In addition to the core modules, Zester ships Salt-compatible modules for file
surgery (file.line, file.replace, file.comment/uncomment,
file.keyvalue, file.copy, file.touch), packages (pkg.latest,
pkg.purged, pkgrepo.managed), archives (archive.extracted), hosts
(host.present/absent), SSH keys (ssh_auth.present/absent),
git.latest, and the test.* helpers. See the module index.
Templates: the salt accessor
Templates can call execution modules during rendering, Salt-style:
{% set os = salt['grains.get']('os') %}
nginx_version: {{ salt['pkg.version']('nginx') }}
db_password: {{ salt['pillar.get']('db:password', 'changeme') }}grains.get/grains.item/grains.items resolve against facts,
pillar.get/pillar.items (and their settings.* equivalents) against
resolved settings, and other names dispatch to the
execution-module registry. The accessor is resolved by
scanning the template source for literal salt['...'] subscripts, so it only
works with literal module names in the template being rendered. For dynamic
module names (a variable subscript) or salt[...] uses inside included
template files, use the salt_call('mod.func', ...) fallback. The accessor
raises a render error if the engine has no module dispatcher configured.
Salt variable aliases are also honored: grains → facts, pillar →
settings. See Templating.
Remote execution
Ad-hoc, imperative execution modules (distinct from idempotent states) are available for operator commands:
zester 'web-*' pkg.version nginx
zester 'web-01' service.restart nginx
zester 'db-*' disk.usage
zester 'web-01' sys.list_functionsThe built-in set: test.echo, test.version, test.true, test.false,
pkg.version, pkg.list_pkgs, service.status, service.start,
service.stop, service.restart, disk.usage, cmd.run, grains.item,
grains.items, and sys.list_functions.
Backed by pkg/execmod. State modules take precedence when a name exists in
both, so state execution is unaffected.
What still needs manual review
zester-migrate flags constructs that don't map automatically. Known
divergences: custom Python execution modules must be rewritten as
Starlark modules; a few module arguments differ from
Salt (e.g. pkgrepo.managed uses baseurl rather than a full deb line, and
manages apt keys via key_url); and listen reacts inline rather than at the
end of the run.