Skip to content

Automax Technical Design

Goals

  • Python implementation.
  • External YAML definitions for jobs, inventories, variables and secrets.
  • Modular plugin architecture.
  • SSH-first execution model.
  • Three-level job structure: task, step, substep.
  • Step-scoped SSH connection reuse.
  • State store for resume and audit.
  • Serial, parallel and rolling execution strategies.
  • Tag-based selection and skip filters.
  • Declarative failure policy.
  • Canonical builtin plugin names with no public short aliases.

Execution model

A step opens one fresh SSH connection per target and reuses it for all its substeps. The runtime context is kept by Automax, not by a long-lived remote shell. Plugins that need step-local state can use the ExecutionContext.step_state mapping internally. Job authors should pass explicit plugin parameters such as cwd instead of relying on implicit cross-substep shell state.

Flow-control nodes are engine-level constructs, not plugins. They let job authors branch, switch, retry nested blocks, loop, group blocks, set values, echo messages, assert conditions, pause explicitly, record no-op branches, fail deliberately, recover with try/rescue/always, and use break/continue in loops while keeping nested plugin executions visible in the state store.

Targets can be scoped at job, task, step or substep level. When substeps in the same step resolve to different target sets, Automax keeps one execution group per step/target and runs only the matching substeps for that target.

External operational files

Automax does not require job, inventory, variable or secret files to live inside the Python source tree. The CLI receives them explicitly:

automax run \
  --job /srv/automax/jobs/deploy.yaml \
  --inventory /srv/automax/inventory/prod.yaml \
  --vars /srv/automax/vars/prod.yaml \
  --secrets /srv/automax/secrets/prod.yaml

Secrets

Secrets are resolved on the controller through env, file, command, vault, aws_secrets_manager, azure_key_vault, gcp_secret_manager and onepassword providers. External secret manager providers use vendor CLIs so the runner does not require cloud SDK dependencies.

Strategy

Strategy can be declared at job, task or step level. More specific scopes override less specific scopes.

strategy:
  mode: serial
strategy:
  mode: parallel
  max_parallel: 5
strategy:
  mode: rolling
  batch_size: 2
  pause_between_batches: 10

Tags

Tags can be declared at job, task, step or substep level and are inherited as an effective set for each substep.

automax run --job job.yaml --inventory inventory.yaml --tags deploy --skip-tags dangerous

Failure policy

Failure policy can be declared at job, task or step level. More specific scopes override less specific scopes.

failurePolicy:
  onFailure: stop_job
  onUnreachable: stop_host
  maxFailedHosts: 1

Supported actions:

stop_job
stop_task
stop_host
continue

Builtin plugin scope

Builtins are grouped into these public families:

commands:      command.local.run, command.remote.run
flow:          if/then/else, switch/case/default, retry/do, for/in/do, block, set/let, echo, assert, sleep, noop, fail, try/rescue/always, break/continue
filesystem:    fs.*
data:          data.archive.*, data.compression.*, data.download.*, data.transfer.*, data.backup.*, data.restore.*
database:      database.<engine>.check, database.<engine>.query
identity:      identity.user.*, identity.group.*
network:       network.connectivity.*, network.dns.*, network.firewall.*, network.http.*, network.link.*, network.route.*
os/packages:   os.*, os.package.*
security:      security.*
storage:       storage.*
system:        system.host.*, system.service.*, system.systemd.*, system.kernel.*, system.process.*, system.cron.*, system.journal.*, system.log.*
devices:       device.udev.*
notifications: notify.mail.send

Builtin plugin names are canonical only: no short or ambiguous aliases are exposed by default. External plugins can still define aliases, but automax plugins list shows canonical names unless --include-aliases is requested.

External plugins can be loaded with --plugin-path.

Remaining non-goals for this implementation

  • Central database state backend.
  • Deploy-release orchestration plugins with rollback semantics.
  • Full Ansible-equivalent module coverage.

Database design

SQLite is built in. PostgreSQL, MySQL and Oracle use optional Python extras. The shared database plugin base owns statement validation, transaction flow and output shaping so new database backends can be added as small driver-specific modules.