Differences with Ansible
Spage is compatible with Ansible's syntax, but there are some differences on both a syntax level but also runtime level.
New features
These features are available in Spage and have no equivalent in Ansible.
before
/after
These task before
/after
keywords are available in Spage and are used to enforce a certain order of execution
when running in parallel execution mode.
- name: task 1
command: echo "task 1"
after: task 3
- name: task 2
command: echo "task 2"
before: task 1
- name: task 3
command: echo "task 3"
$ SPAGE_EXECUTION_MODE=parallel spage run /tmp/spage_test.yaml
TASK [task 2] (localhost) ****************************************************
changed: [localhost] =>
cmd: "echo \"task 2\""
stdout: "task 2\n"
stderr: ""
TASK [task 3] (localhost) ****************************************************
changed: [localhost] =>
cmd: "echo \"task 3\""
stdout: "task 3\n"
stderr: ""
TASK [task 1] (localhost) ****************************************************
changed: [localhost] =>
cmd: "echo \"task 1\""
stdout: "task 1\n"
stderr: ""
PLAY RECAP ****************************************************
localhost : ok=0 changed=3 failed=0 skipped=0 ignored=0
run_as
The run_as
keyword is available in Spage and is used to run a task as a different user. This is equivalent to using both become
and become_user
together.
- name: Tell me the time
shell: echo "The time is $(date)"
run_as: root
Spage translates this to become: true
and become_user: root
.
Differences in behaviour
Not specifying hosts will assume localhost
If you're targeting a playbook without specifying the hosts
attribute on the play, Spage will assume localhost
as the target.
- name: Tell me the time
shell: echo "The time is $(date)"
register: time
$ spage run playbook.yaml
TASK [Tell me the time] (localhost) ****************************************************
changed: [localhost] =>
cmd: "echo \"The time is $(date)\""
Target localhost
will use connection: local
by default
If you're targeting localhost
in a playbook, Spage will use connection: local
by default.
all:
hosts:
localhost:
$ spage run playbook.yaml
TASK [Tell me the time] (localhost) ****************************************************
changed: [localhost] =>
cmd: "echo \"The time is $(date)\""
If you don't want to, you can specify spage_connection: local
in your inventory:
all:
hosts:
localhost:
spage_connection: ssh
Multiple plays in a single file are not supported
Spage does not support multiple plays in a single file.
- hosts: all
tasks:
- name: Tell me the time
shell: echo "The time is $(date)"
register: time
# Only one play is allowed in a file
- hosts: all
tasks:
- name: Tell me the time
shell: echo "The time is $(date)"
register: time
Detect variable usage and require input
Spage will detect variable usage and require input for those variables.
- name: Tell me the time
shell: echo "The time is {{ time }}"
$ spage generate playbook.yaml
$ cat generated_tasks.go
...
var GeneratedGraph = pkg.Graph{
RequiredInputs: []string{
"time",
},
...
$ go run generated_tasks.go
Execution failed: failed to check inventory for required inputs: required inputs [time] not found in host contexts
Error: failed to check inventory for required inputs: required inputs [time] not found in host contexts
2025-08-28T21:30:31.448+0200 ERROR Failed to run playbook {"error": "failed to check inventory for required inputs: required inputs [time] not found in host contexts"}
exit status 1