Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ WORKDIR /app

RUN mkdir -p "${PLAYWRIGHT_BROWSERS_PATH}"
RUN playwright install chromium-headless-shell --with-deps

# Ansible is required by the built-in `ansible` component, which uses this
# container as the Ansible control node. Kept as a dedicated layer so it does
# not invalidate the cache for the expensive toolchain layers above.
# DEBIAN_FRONTEND=noninteractive avoids the tzdata install prompt.
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ansible && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*

RUN rm -rf /opt/install /opt/install-scripts /tmp/*

CMD [ "/bin/bash", "-c", "sleep infinity" ]
Expand Down
57 changes: 57 additions & 0 deletions docs/components/Core.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { CardGrid, LinkCard } from "@astrojs/starlight/components";

<CardGrid>
<LinkCard title="Add Memory" href="#add-memory" description="Add a namespaced JSON value to canvas memory" />
<LinkCard title="Ansible" href="#ansible" description="Run an Ansible playbook or ad-hoc command against an inventory." />
<LinkCard title="Approval" href="#approval" description="Collect approvals on events" />
<LinkCard title="Delete Memory" href="#delete-memory" description="Delete values from canvas memory by namespace and field matches" />
<LinkCard title="Display" href="#display" description="Display a debug message from the latest execution" />
Expand Down Expand Up @@ -267,6 +268,62 @@ A single `memory.added` event is emitted with all written rows and the total `co
}
```

<a id="ansible"></a>

## Ansible

**Component key:** `ansible`

Run Ansible from a SuperPlane workflow. The SuperPlane node acts as the Ansible control node and reaches managed hosts through the inventory you provide.

### Modes

- **Playbook**: Provide playbook YAML inline. It is run with `ansible-playbook` and the JSON output callback so the play recap (ok/changed/unreachable/failed per host) is captured.
- **Ad-hoc**: Run a single module against a host pattern, e.g. module `ping`, or module `shell` with arguments `uptime`.

### Configuration

- **Inventory**: Inline inventory (INI or YAML). Defaults to `localhost ansible_connection=local` so it works without any remote hosts.
- **Playbook** (playbook mode): The playbook YAML to run.
- **Host pattern / Module / Module arguments** (ad-hoc mode): The target pattern, module name, and module arguments.
- **Extra variables**: Optional `name=value` pairs passed via `-e`.
- **Limit**: Optional `--limit` host pattern.
- **Become**: Run with privilege escalation (`--become`).
- **Verbosity**: 0-4, mapped to `-v`..`-vvvv`.
- **Timeout (seconds)**: Maximum run time before the execution errors out.

### Output

- **success**: Ansible exited with status 0.
- **failed**: Ansible ran but exited non-zero (e.g. a task failed or a host was unreachable).

If Ansible cannot be run at all (binary missing, timeout, invalid working directory), the run finishes in the **error** state.

### Example Output

```json
{
"data": {
"exitCode": 0,
"recap": {
"localhost": {
"changed": 1,
"failures": 0,
"ignored": 0,
"ok": 2,
"rescued": 0,
"skipped": 0,
"unreachable": 0
}
},
"stderr": "",
"stdout": "{\"stats\": {\"localhost\": {\"ok\": 2, \"changed\": 1, \"unreachable\": 0, \"failures\": 0, \"skipped\": 0, \"rescued\": 0, \"ignored\": 0}}}"
},
"timestamp": "2026-01-19T12:00:00Z",
"type": "ansible.playbook.executed"
}
```

<a id="approval"></a>

## Approval
Expand Down
Loading