go.bigb.es/auxilia
Documentation
Index
Types
type Command struct { legatus.AlwaysApply Cmd string Args []string Sudo bool Stream bool }
Command runs a command unconditionally and captures its stdout. Unlike Exec it carries no idempotency guard (it embeds AlwaysApply), so it is the right tool for read-style commands whose output feeds later steps. Apply stores the trimmed stdout in Outcome.Data and in the FlowCtx param bag under Name().
When Stream is set, stdout/stderr also stream live to FlowCtx.Out() as the command runs (for deploy hooks like post_push), while stdout is still captured for Outcome.Data/the param bag via a tee.
func (c Command) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply runs the command, records its stdout, and exposes it as a param. With Stream set, output is teed live to FlowCtx.Out() while stdout is still captured.
type Compose struct { legatus.AlwaysApply Dir string Action ComposeAction Services []string Detach bool Stream bool }
Compose runs `docker compose <action>` in a stack's directory. It is a thin, opinion-free typed wrapper over a structural legatus.Cmd with Cmd.Dir set (PC2): it adds no stack/service policy of its own, only the `up -d` flag when Detach is set. It always applies (no idempotency guard); read-only actions report Changed:false so the engine's tally stays honest.
When Stream is set, stdout/stderr also stream live to FlowCtx.Out() as the command runs (for `up`/`logs` output), while stdout is still captured for Outcome.Data via a tee — mirroring Command's streaming contract.
func (c Compose) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply runs the compose command in Dir and reports whether it changed state. An empty Action fails loud rather than running `docker compose` with no subcommand.
type ComposeAction string
ComposeAction is a docker compose subcommand. Read-only actions (Ps, Logs) report Outcome.Changed:false; state-changing ones (Up, Down, Pull, Restart) report Changed:true.
const ( ComposeUp ComposeAction = "up" ComposeDown ComposeAction = "down" ComposePull ComposeAction = "pull" ComposePs ComposeAction = "ps" ComposeLogs ComposeAction = "logs" ComposeRestart ComposeAction = "restart" )
type Exec struct { Cmd string Args []string Creates string Unless string OnlyIf string // Sudo controls privilege-wrapping; the zero value (SudoDefault) is no sudo, // matching the previous bool zero value. Sudo SudoPolicy }
Exec runs a command with idempotency guards. Check evaluates the guards (PC4); Apply runs the command. Guards (highest precedence first):
- Creates: skip when the path already exists.
- Unless: skip when the shell command exits 0.
- OnlyIf: skip when the shell command exits non-zero.
With no guard, the command always runs.
func (e Exec) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply runs the command and reports it changed state.
func (e Exec) Check(fc *legatus.FlowCtx) (bool, error)
Check evaluates the guards and reports whether the command should run.
type File struct { Path string Content []byte Mode legatus.FileMode Owner string // Sudo controls privilege-wrapping of the upload (and the Normalize read); the // zero value (SudoDefault) is no sudo, matching the previous behavior. Sudo SudoPolicy // Normalize, when set, changes Check to compare the remote file and Content // AFTER applying it to both — so a byte-different but semantically-equal file // (e.g. reformatted) reports no change. nil ⇒ raw content+mode hash idempotency. Normalize func([]byte) []byte }
File ensures a remote file has the given content, mode, and owner. Check compares the remote SHA-256 hash and octal mode against the desired state; Apply uploads the content and applies mode/owner.
func (f File) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply uploads the content and reports the change.
func (f File) Check(fc *legatus.FlowCtx) (bool, error)
Check reports a change is needed unless the remote file already matches the desired state — by Normalize-equality when set, else content hash + mode.
type LocalMint struct { Path string Mode legatus.FileMode Stale func(existing []byte) bool Produce func(ctx context.Context, conn legatus.Conn, existing []byte) ([]byte, error) }
LocalMint mints a LOCAL file once from a remote command, then reuses it. Every other step in this package manages a REMOTE file; LocalMint is the inverse — its target lives on the machine running the Flow. It models "derive a local artifact from something only the remote host can produce" (a generated key, a fetched certificate, an exported config): expensive to produce, cheap to keep.
- Check is a local stat: apply is needed when Path is missing, or when a Stale predicate flags the existing bytes (e.g. an always-true predicate for an artifact that must be regenerated every run, or a content test for a back-fill).
- Apply reads any existing bytes, hands them to Produce (so a back-fill producer can preserve them), runs the producer over the Conn, and writes the result with an atomic temp+rename at Mode. A Produce error aborts with nothing written.
Path, Mode, Stale, and Produce are all caller-supplied; Mode must be set (a zero Mode writes a 0000 file). LocalMint itself is transport- and content-agnostic.
func (m LocalMint) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply reads any existing bytes, runs Produce over the Conn, and writes the result atomically at Mode.
func (m LocalMint) Check(*legatus.FlowCtx) (bool, error)
Check reports apply-needed when Path is missing or Stale flags the existing bytes. A read error other than not-exist is a hard failure (no regenerate over an unreadable file).
type Package struct { Pkg string State PkgState Manager PkgManager // Sudo controls privilege-wrapping of the install/remove; the zero value // (SudoDefault) sudo-wraps, preserving the previous always-sudo behavior. Sudo SudoPolicy }
Package manages an OS package. Check queries whether it is installed; Apply installs or removes it to converge State.
func (p Package) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply installs or removes the package.
func (p Package) Check(fc *legatus.FlowCtx) (bool, error)
Check reports a change is needed when the package's installed state differs from the desired State.
type PkgManager string
PkgManager identifies the host package manager. PC3: this battery carries apt/dnf/pacman opinions. An unknown manager is an error, never a silent default.
const ( // Apt is Debian/Ubuntu apt-get. Apt PkgManager = "apt" // Dnf is Fedora/RHEL dnf. Dnf PkgManager = "dnf" // Pacman is Arch Linux pacman. Pacman PkgManager = "pacman" )
type PkgState string
PkgState is the desired state of a package.
const ( // PkgPresent requires the package to be installed. PkgPresent PkgState = "present" // PkgAbsent requires the package to be removed. PkgAbsent PkgState = "absent" )
type Service struct { Unit string State ServiceState Enabled *bool // Sudo controls privilege-wrapping of the systemctl mutations; the zero value // (SudoDefault) sudo-wraps, preserving the previous always-sudo behavior. Sudo SudoPolicy }
Service manages a systemd unit (PC3: this battery is opinionated about systemd). State controls active/inactive; Enabled, when non-nil, controls the boot-time enablement. Check probes is-active/is-enabled; Apply converges.
func (s Service) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply converges run state and enablement.
func (s Service) Check(fc *legatus.FlowCtx) (bool, error)
Check reports a change is needed when the unit's active or enabled state differs from the desired state. ServiceRestarted always needs a change.
type ServiceState string
ServiceState is the desired run state of a systemd unit.
const ( // ServiceRunning requires the unit to be active. ServiceRunning ServiceState = "running" // ServiceStopped requires the unit to be inactive. ServiceStopped ServiceState = "stopped" // ServiceRestarted forces a restart on every apply (no skip). ServiceRestarted ServiceState = "restarted" )
type SudoPolicy uint8
SudoPolicy decides whether a step's privileged commands are sudo-wrapped. The zero value, SudoDefault, preserves each step's historical behavior — so adding the field to an existing step changes nothing — while the other values are explicit overrides. SudoIfNonRoot resolves against the host's login user: sudo only when connecting as a non-root user (root needs none and may lack the sudo binary), which is the common fleet shape of a non-root relay + root targets.
const ( // SudoDefault uses the step's built-in default (the dflt passed to resolve). SudoDefault SudoPolicy = iota // SudoAlways always sudo-wraps. SudoAlways // SudoNever never sudo-wraps. SudoNever // SudoIfNonRoot sudo-wraps only when the host login user is non-root. SudoIfNonRoot )
type Template struct { Path string Text string Mode legatus.FileMode Owner string }
Template renders a text/template into a remote file. The template data is the merge of Host.Vars and the FlowCtx param bag (params win on key collision). Once rendered, it follows File semantics for idempotency and upload.
func (t Template) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply renders the template and uploads it.
func (t Template) Check(fc *legatus.FlowCtx) (bool, error)
Check renders the template and reports a change is needed unless the remote file already matches the rendered content and mode.
type ValidatedFile struct { Path string Content []byte Mode legatus.FileMode Owner string Sudo bool // Validator returns the command that validates the staged file at the given // path; a non-zero exit aborts the write. It runs with Sudo when Sudo is set. Validator func(stagedPath string) legatus.Cmd // Normalize, when set, changes Check to compare the remote file and Content // AFTER applying it to both — so a byte-different but semantically-equal file // reports no change (and so no rewrite/validation). nil ⇒ content+mode hash. Normalize func([]byte) []byte }
ValidatedFile writes a file only after a validator command passes against the exact bytes to be installed. It stages the content beside the target, runs the validator on the staged path, and commits with an atomic same-directory move on success; on failure the staged file is removed and the live target is left untouched. Use it for configs that must pass a checker before a reload (sing-box check -c, haproxy -c -f). Unlike File, it supports sudo writes.
func (f ValidatedFile) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply stages the content beside the target, validates the staged path, and on success moves it into place; on validator failure it removes the staged file and errors, leaving the live target unchanged.
func (f ValidatedFile) Check(fc *legatus.FlowCtx) (bool, error)
Check reuses File's content+mode hash idempotency (or Normalize-equality when set): a remote file already matching needs no change, and so no validation.
type When struct { Cond func(*legatus.FlowCtx) bool Step legatus.Step }
When wraps a step with a precondition. Cond is evaluated in Check: when it is set and returns false the inner step is skipped (need=false); when it is nil or returns true, Check delegates to the inner step. Apply always delegates unchanged — When gates whether the step runs, never what it does.
func OnChanged(inner legatus.Step, watch ...string) When
OnChanged runs inner only if any of the watched earlier steps changed during this flow execution on this host — the restart-on-change pattern. Watch entries are step names, e.g. File{Path: p}.Name(). With no watch names it runs inner when any earlier step changed.
func (w When) Apply(fc *legatus.FlowCtx) (legatus.Outcome, error)
Apply delegates to the inner step unchanged.
func (w When) Check(fc *legatus.FlowCtx) (bool, error)
Check skips (need=false) when Cond is set and false; otherwise it delegates to the inner step's Check.
Package steps provides a battery of common legatus steps: file, validated-file, template, service, exec, package, command, and local-mint (the inverse of the others — derive a LOCAL artifact from a remote command), plus the When/OnChanged gating wrappers (run a step only when an earlier step changed). Each type satisfies legatus.Step and keeps its idempotency logic inside Check (PC4) so the engine never guesses.