go.bigb.es/auxilia

v0.6.1
Doc Versions Source

Index

Variables

var ErrNoPrompter = culpa.WithCode(culpa.New("legatus: no interactive prompter configured"), "LEGATUS_NO_PROMPTER")

ErrNoPrompter is returned by the non-interactive default prompter when a step requires a choice it cannot answer.

Functions

f func Output

src
func Output(ctx context.Context, conn Conn, cmd Cmd) (string, error)

Output runs cmd over conn, requires a clean run (exit 0), and returns the trimmed stdout. It is the "exec and capture" convenience over Conn.Exec: a non-zero exit is a hard error carrying the trimmed combined output, with no silent fallback to a partial result. For a probe where a non-zero exit is a signal rather than a failure (e.g. `test -e`), call Exec directly and inspect ExecResult.ExitCode.

f func Param

src
func Param[T any](fc *FlowCtx, key string) (T, bool)

Param reads a typed value from the per-flow param bag.

f func SetParam

src
func SetParam[T any](fc *FlowCtx, key string, v T)

SetParam stores a typed value in the per-flow param bag.

f func SetSharedParam

src
func SetSharedParam[T any](s *SharedStore, key string, v T)

SetSharedParam stores a typed value in a SharedStore.

f func SharedParam

src
func SharedParam[T any](s *SharedStore, key string) (T, bool)

SharedParam reads a typed value from a SharedStore.

Types

T type AlwaysApply

src
type AlwaysApply struct{}

AlwaysApply embeds into steps with no meaningful check; Check always reports a change is needed.

m func (AlwaysApply) Check

src
func (AlwaysApply) Check(*FlowCtx) (bool, error)

Check always reports need=true.

T type Cmd

src
type Cmd struct {
	Path  string
	Args  []string
	Env   map[string]string
	Sudo  bool
	Stdin io.Reader

	// Dir, when non-empty, is the working directory the command runs in. Empty
	// ⇒ the connection's default (login) directory, exactly as today. The
	// directory is quoted by the transport, so it never re-splits or re-evaluates
	// — the same guarantee Args carry.
	Dir string
}

Cmd is a remote command. Args are passed structurally: a transport must quote each element so the remote shell can never re-split or re-evaluate it.

T type Conn

src
type Conn interface {
	// Exec runs cmd to completion. A command that runs is not an error even on a
	// non-zero exit: the status is reported via ExecResult.ExitCode and err is
	// nil. err is reserved for failures to run the command at all (no session,
	// IO error, context cancellation). Callers decide whether a non-zero exit is
	// a failure (a step's Apply) or a signal (a probe like `test -e`).
	Exec(ctx context.Context, cmd Cmd) (ExecResult, error)
	// ExecStream runs cmd like Exec but streams output: a non-nil stdout/stderr
	// writer receives that stream live and the matching ExecResult field is left
	// nil; a nil writer buffers that stream into ExecResult exactly as Exec does,
	// so a caller can stream one stream while capturing the other. The exit-code
	// contract is identical to Exec — a clean run with a non-zero exit returns
	// err==nil with ExecResult.ExitCode set; ctx cancellation tears down the
	// process and returns ctx.Err() with bytes-so-far already written to the sink.
	ExecStream(ctx context.Context, cmd Cmd, stdout, stderr io.Writer) (ExecResult, error)
	Put(ctx context.Context, content io.Reader, remote string, mode FileMode, opts ...PutOption) error
	Get(ctx context.Context, remote string, w io.Writer) error
	Close() error
}

Conn is a live connection to one host. Transports implement it; the core engine depends only on this interface and never imports SSH (IV1, PC1).

T type DenyPrompter

src
type DenyPrompter struct{}

DenyPrompter is the non-interactive default: it declines confirmations and errors on selections.

m func (DenyPrompter) Confirm

src
func (DenyPrompter) Confirm(context.Context, string) (bool, error)

m func (DenyPrompter) Select

src
func (DenyPrompter) Select(context.Context, string, []string) (int, error)

T type Dialer

src
type Dialer interface {
	Dial(ctx context.Context, h *Host) (Conn, error)
}

Dialer opens a Conn to a host. transport provides the SSH implementation.

T type ErrorPolicy

src
type ErrorPolicy int

ErrorPolicy governs cross-host behavior. Within a single host's flow a failed step always stops that flow (IV7); ErrorPolicy decides what happens to the other hosts.

const (
	// ContinueOnError runs every host and collects all failures (default).
	ContinueOnError ErrorPolicy = iota
	// FailFast cancels remaining hosts after the first host failure (best-effort).
	FailFast
)

T type ExecResult

src
type ExecResult struct {
	Stdout   []byte
	Stderr   []byte
	ExitCode int
}

ExecResult is the outcome of a remote command.

m func (ExecResult) Combined

src
func (r ExecResult) Combined() []byte

Combined returns stdout followed by stderr.

T type FileMode

src

FileMode is the permission mode used when writing remote files.

T type Flow

src
type Flow struct {
	Name  string
	Steps []Step
}

Flow is an ordered, host-agnostic sequence of steps — a playbook. A Runner executes a Flow against each selected host, fanning out per host.

m func (Flow) Resolve

src
func (f Flow) Resolve() (Flow, error)

Resolve makes Flow its own FlowSource: a materialized Flow is already resolved, so it returns itself unchanged with a nil error.

T type FlowCtx

src
type FlowCtx struct {
	// contains filtered or unexported fields
}

FlowCtx threads through the steps of one flow execution on one host. Its param bag is private to this execution, so steps pass data forward without locking (IV3). Cross-host data goes through Shared.

f func NewFlowCtx

src
func NewFlowCtx(ctx context.Context, h *Host, c Conn, opts ...FlowCtxOption) *FlowCtx

NewFlowCtx builds a FlowCtx. The Runner uses it; step tests use it directly.

m func (*FlowCtx) AnyChanged

src
func (fc *FlowCtx) AnyChanged(names ...string) bool

AnyChanged reports whether any of the named earlier steps changed. With no names, it reports whether any earlier step in this flow changed. Visibility is limited to steps already executed on this host (never cross-host).

m func (*FlowCtx) Changed

src
func (fc *FlowCtx) Changed(name string) bool

Changed reports whether the named earlier step changed (or would change in dry-run) during this flow execution on this host. An unrun or unrecorded step reports false.

m func (*FlowCtx) Conn

src
func (fc *FlowCtx) Conn() Conn

Conn returns the live connection to the host.

m func (*FlowCtx) Ctx

src
func (fc *FlowCtx) Ctx() context.Context

Ctx returns the execution context.

m func (*FlowCtx) DryRun

src
func (fc *FlowCtx) DryRun() bool

DryRun reports whether this is a dry run.

m func (*FlowCtx) Get

src
func (fc *FlowCtx) Get(key string) (any, bool)

Get reads a value from the per-flow param bag.

m func (*FlowCtx) Host

src
func (fc *FlowCtx) Host() *Host

Host returns the target host.

m func (*FlowCtx) Log

src
func (fc *FlowCtx) Log() *slog.Logger

Log returns the per-flow logger, pre-tagged by the Runner with host and step.

m func (*FlowCtx) Out

src
func (fc *FlowCtx) Out() io.Writer

Out returns the human-facing output sink. The engine owns it; steps stream command output here (never os.Stdout) when asked. Never nil — io.Discard by default, so an unconfigured Runner silently discards.

m func (*FlowCtx) Prompter

src

Prompter returns the injected prompter (non-interactive by default).

m func (*FlowCtx) Set

src
func (fc *FlowCtx) Set(key string, v any)

Set stores a value in the per-flow param bag.

m func (*FlowCtx) Shared

src
func (fc *FlowCtx) Shared() *SharedStore

Shared returns the cross-host store.

T type FlowCtxOption

src

FlowCtxOption configures a FlowCtx.

f func WithFlowDryRun

src

WithFlowDryRun toggles dry-run.

f func WithFlowLogger

src

WithFlowLogger sets the per-flow logger.

f func WithFlowOutput

src

WithFlowOutput sets the human-facing output sink steps stream to (Out()).

f func WithFlowPrompter

src

WithFlowPrompter sets the prompter.

f func WithFlowShared

src

WithFlowShared sets the cross-host shared store.

T type FlowResult

src
type FlowResult struct {
	Flow   string
	Host   string
	Steps  []StepResult
	Status Status
	Params map[string]any
}

FlowResult is the record of one flow on one host, with a snapshot of the final param bag for pulling forward-passed data back out.

T type FlowSource

src
type FlowSource interface {
	Resolve() (Flow, error)
}

FlowSource is anything that lowers to a runnable Flow: a static Flow (the identity case) or a declarative spec that resolves to one (see legatus/flowspec). Runner.Run accepts a FlowSource, so callers pass either kind interchangeably. Resolve is host-independent — it yields the same Flow for every host, so the Runner resolves once before fanning out.

T type Host

src
type Host struct {
	Name   string
	Addr   string
	Port   int
	User   string
	Tags   []string
	Groups []string
	Vars   map[string]any
}

Host is a single SSH target the orchestrator can act on.

T type Inventory

src
type Inventory struct {
	// contains filtered or unexported fields
}

Inventory is the set of hosts an orchestration runs against.

f func NewInventory

src
func NewInventory(hosts ...*Host) *Inventory

NewInventory builds an inventory from the given hosts.

m func (*Inventory) Add

src
func (inv *Inventory) Add(h *Host)

Add appends a host to the inventory.

m func (*Inventory) Group

src
func (inv *Inventory) Group(name string) []*Host

Group returns the hosts that are members of the named group.

m func (*Inventory) Hosts

src
func (inv *Inventory) Hosts(sel ...Selector) []*Host

Hosts returns the hosts matching every selector (logical AND). With no selectors it returns all hosts.

T type NopReporter

src
type NopReporter struct{}

NopReporter discards all events. It is the default reporter.

m func (NopReporter) FlowDone

src
func (NopReporter) FlowDone(string, FlowResult)

m func (NopReporter) FlowStart

src
func (NopReporter) FlowStart(string, string)

m func (NopReporter) RunDone

src
func (NopReporter) RunDone(RunResult)

m func (NopReporter) StepDone

src
func (NopReporter) StepDone(string, StepResult)

m func (NopReporter) StepStart

src
func (NopReporter) StepStart(string, string)

T type Option

src
type Option func(*Runner)

Option configures a Runner.

f func WithConcurrency

src

WithConcurrency caps how many hosts run at once. Values < 1 are ignored.

f func WithDialer

src

WithDialer sets the dialer used to open per-host connections.

f func WithDryRun

src
func WithDryRun(d bool) Option

WithDryRun toggles dry-run: steps are Checked, never Applied.

f func WithErrorPolicy

src

WithErrorPolicy sets the cross-host error policy.

f func WithLogger

src

WithLogger sets the base structured logger.

f func WithOutput

src

WithOutput sets the human-facing output sink threaded into each flow's FlowCtx.Out(). Steps that stream (e.g. steps.Command{Stream}) write here.

f func WithPrompter

src

WithPrompter sets the prompter handed to each FlowCtx.

f func WithReporter

src

WithReporter sets the progress reporter.

T type Outcome

src
type Outcome struct {
	Changed bool
	Message string
	Data    any
}

Outcome is what a step reports about what it did. The engine wraps this in a StepResult with timing and a derived Status.

T type Prompter

src
type Prompter interface {
	Confirm(ctx context.Context, question string) (bool, error)
	Select(ctx context.Context, question string, options []string) (int, error)
}

Prompter answers interactive questions a step may ask. The core is non-interactive by default (PC2); a real prompter is injected by the caller.

T type PutOption

src
type PutOption func(*PutOptions)

PutOption mutates PutOptions.

f func WithPutOwner

src
func WithPutOwner(owner string) PutOption

WithPutOwner chowns the uploaded file to owner.

f func WithPutSudo

src

WithPutSudo stages the upload and moves it into place with sudo.

T type PutOptions

src
type PutOptions struct {
	Sudo  bool
	Owner string
}

PutOptions configures a file upload.

T type Reporter

src
type Reporter interface {
	FlowStart(host, flow string)
	StepStart(host, step string)
	StepDone(host string, r StepResult)
	FlowDone(host string, r FlowResult)
	RunDone(r RunResult)
}

Reporter receives engine-driven progress events for human-facing output. It is decoupled from structured logging; the engine drives both with no step involvement (PC5).

T type RunResult

src
type RunResult struct {
	Flows []FlowResult
}

RunResult aggregates one FlowResult per host.

m func (RunResult) Counts

src
func (r RunResult) Counts() (ok, changed, skipped, failed int)

Counts tallies step statuses across all hosts. WouldChange counts as changed.

m func (RunResult) Failed

src
func (r RunResult) Failed() bool

Failed reports whether any host's flow failed.

T type Runner

src
type Runner struct {
	// contains filtered or unexported fields
}

Runner executes flows across an inventory. It pools one Conn per host and carries a SharedStore so sequential Run calls can pass data between groups (e.g. exits → relay). The Runner reaches hosts only through the Dialer/Conn interfaces, never SSH directly (IV1, PC1).

f func NewRunner

src
func NewRunner(inv *Inventory, opts ...Option) *Runner

NewRunner builds a Runner. Defaults: concurrency 1, ContinueOnError, no-op reporter, non-interactive prompter, slog.Default logger.

m func (*Runner) Close

src
func (r *Runner) Close() error

Close closes all pooled connections. It also satisfies steward's Stopper.

m func (*Runner) Run

src
func (r *Runner) Run(ctx context.Context, src FlowSource, sel ...Selector) RunResult

Run executes flow against the hosts matching sel (all hosts if none), fanning out across an ordered worker pool capped at the configured concurrency. It always returns a result per host. Under FailFast, once a host fails the run context is cancelled and hosts not yet dispatched are recorded as cancelled without dialing — because jobs are fed in inventory order, with concurrency 1 this cancellation is deterministic.

m func (*Runner) Shared

src
func (r *Runner) Shared() *SharedStore

Shared returns the cross-host store, persistent across Run calls.

m func (*Runner) Stop

src
func (r *Runner) Stop(context.Context) error

Stop closes pooled connections (steward Stopper).

T type Selector

src
type Selector func(*Host) bool

Selector reports whether a host belongs to a selection. Selectors are pure predicates over a Host so they compose without reaching back into Inventory.

f func ByName

src
func ByName(names ...string) Selector

ByName selects hosts whose Name is in names.

f func ByTag

src
func ByTag(tags ...string) Selector

ByTag selects hosts carrying any of the given tags.

f func InGroup

src
func InGroup(group string) Selector

InGroup selects hosts that are members of the named group.

T type SharedStore

src
type SharedStore struct {
	// contains filtered or unexported fields
}

SharedStore is the cross-host, concurrency-safe param store carried by a Runner. Per-host flows publish here for later flows (e.g. exits → relay).

f func NewSharedStore

src

NewSharedStore returns an empty store.

m func (*SharedStore) Get

src
func (s *SharedStore) Get(key string) (any, bool)

Get reads a value.

m func (*SharedStore) Set

src
func (s *SharedStore) Set(key string, v any)

Set stores a value.

T type Status

src
type Status int

Status is the outcome of a step or the aggregate of a flow.

const (
	// StatusOK — applied, no change (or all steps skipped).
	StatusOK Status = iota
	// StatusChanged — applied and state changed.
	StatusChanged
	// StatusSkipped — Check reported no change needed.
	StatusSkipped
	// StatusWouldChange — dry-run: Check reported a change; Apply was not run.
	StatusWouldChange
	// StatusFailed — Check or Apply errored.
	StatusFailed
)

m func (Status) String

src
func (s Status) String() string

T type Step

src
type Step interface {
	Name() string
	Check(fc *FlowCtx) (need bool, err error)
	Apply(fc *FlowCtx) (Outcome, error)
}

Step is one unit of work. Check probes whether a change is needed (need=false reports Skipped and, in dry-run, ends the step). Apply performs the change and reports what it did.

f func StepFunc

src
func StepFunc(name string, fn func(*FlowCtx) (Outcome, error)) Step

StepFunc adapts a function into a Step that always applies.

T type StepResult

src
type StepResult struct {
	Step     string
	Status   Status
	Outcome  Outcome
	Err      error
	Started  time.Time
	Duration time.Duration
}

StepResult is the engine's record of one step on one host.