Date: 2026-05-11
Time: 15:46
This is a Phase 2 example script for FTL2's automation context, demonstrating inventory integration — how to define hosts and groups, load them from YAML files or dictionaries, and execute modules across one or more hosts. It serves as a practical tutorial covering the progression from default localhost usage through multi-host remote execution.
Default localhost (simplest entry point):
async with automation() as ftl:
print(list(ftl.hosts)) # iterate host names
hosts = ftl.hosts["localhost"] # lookup returns list of Host objects
Inventory from a Python dict (dynamic inventories):
inventory = {
"webservers": {
"hosts": {
"web01": {"ansible_host": "192.168.1.10", "ansible_port": 22},
}
}
}
context = AutomationContext(inventory=inventory)
Inventory from a YAML file:
async with automation(inventory="/path/to/inventory.yml") as ftl:
for host in ftl.hosts["webservers"]:
print(host.name, host.ansible_host)
Remote execution with run_on:
# By group name or host name — returns list of results
results = await ftl.run_on("webservers", "file", path="/tmp/test", state="touch")
for result in results:
print(result.host, result.success, result.changed, result.output)
# By host object list
hosts = ftl.hosts["localhost"]
results = await ftl.run_on(hosts, "command", cmd="echo hello")
Local vs remote distinction:
# Local: direct module call
result = await ftl.file(path="/tmp/f", state="touch") # returns dict
# Remote: run_on — same module, but wrapped in remote execution
results = await ftl.run_on("localhost", "file", path="/tmp/f", state="touch") # returns list of result objects
| Parameter / Attribute | Description |
|---|---|
| automation(inventory=...) | Path to YAML inventory file (string) |
| AutomationContext(inventory=...) | Dict-based inventory; can also be used as async context manager |
| ftl.hosts | Host manager — iterable, supports len(), in, [] lookup, .groups, .all, .keys() |
| ftl.hosts["name"] | Lookup by host name or group name; returns list of Host objects |
| host.name | Host identifier |
| host.ansible_host | IP/hostname for connection |
| host.ansible_port | SSH port |
| host.ansible_user | SSH user |
| host.ansible_connection | Connection type (e.g. "local") |
| ftl.run_on(target, module, **params) | Target is a group name string, host name string, or list of Host objects |
Inventory YAML format follows Ansible-style structure with groups containing hosts and optional vars sections.
ftl.hosts["name"] always returns a list, even for a single host — consistent interface whether looking up a host name or group name.run_on returns a list of result objects with .host, .success, .changed, and .output attributes. This differs from direct module calls which return a dict.ftl.file(...)) are local-only; run_on is required for remote/multi-host execution.AutomationContext can be used both as a regular object and as an async context manager (async with AutomationContext(...) as ftl).automation() with no arguments provides a default inventory containing localhost.vars in YAML) are supported in inventory files.ftl2.automation (context manager factory) and ftl2.AutomationContext (class for direct instantiation).file (touch), command (shell commands) — called both locally and via run_on.docker-compose.yml for setting up remote SSH targets.automation() and direct ftl.module() calls; this phase adds ftl.hosts and ftl.run_on().