Skip to main content

A thin Python wrapper over Ansible's executor: typed AnsibleHost / AnsibleHosts classes that let you run Ansible modules from Python without pytest-ansible or ansible-runner.

Project description

ansible-host

CI License: Apache 2.0 Ruff

A thin Python wrapper over Ansible's executor. Lets you run Ansible modules from Python with structured results, batch execution, and a host-object-first API — without going through pytest-ansible or ansible-runner.

Status: alpha (0.1.0a0). Built from a working internal implementation; API is stable in shape but may shift in details before 1.0.

Why this exists

Ansible has a great executor and a huge module ecosystem, but the existing Python access paths are awkward for in-test or in-tool use:

pytest-ansible ansible-runner ansible-host
Use case Pytest fixtures AWX-style managed jobs In-process programmatic
API surface ~20% of Ansible's runtime Subprocess + event stream Typed Python objects
Forking, custom callbacks Limited Yes (in subprocess) Yes (native)
Per-call overhead Low High (subprocess + JSON parsing) Low (in-process)
Returns Strings Event stream Structured Python dicts

ansible-host sits where the other two don't: in-process, low-overhead, structured-result execution that you can drop into any Python codebase that wants Ansible underneath.

Install

pip install ansible-host

Requires Python 3.10+ and ansible-core>=2.16,<2.22. Like Ansible itself, the library runs on POSIX systems (Linux, macOS, WSL) — it is not supported on native Windows.

Development

The recommended dev workflow uses uv — it manages the virtualenv directly, sidestepping the python3-venv split on Ubuntu and installing dependencies an order of magnitude faster than pip.

# One-time: install uv (https://docs.astral.sh/uv/getting-started/installation/)
curl -LsSf https://astral.sh/uv/install.sh | sh

# In the repo
uv venv                        # creates .venv with the default Python
uv pip install -e ".[dev]"     # editable install + dev extras
uv run pytest                  # run the test suite
uv run ruff check src tests    # lint

To target a specific Python or ansible-core version (matches the CI matrix):

uv venv --python 3.12
uv pip install -e ".[dev]"
uv pip install "ansible-core==2.19.*"
uv run pytest

pip and a manually-managed venv still work — uv is just the convenience.

Quickstart

30-second try — no SSH, no inventory

AnsibleLocalhost runs modules in-process on the current machine via Ansible's local connection plugin. No inventory file, no SSH, no setup.

from ansible_host import AnsibleLocalhost

host = AnsibleLocalhost()
result = host.ping()
assert result["ping"] == "pong"

result = host.command("uname -a")
print(result["stdout"])

Running against a real host

Drop an inventory file alongside your script:

# inventory.ini
[switches]
sw-01 ansible_host=10.0.0.1 ansible_user=admin
from ansible_host import AnsibleHost

host = AnsibleHost(inventory="inventory.ini", pattern="sw-01")
result = host.shell("show version")
print(result["stdout"])

Multi-host fanout

from ansible_host import AnsibleHosts

hosts = AnsibleHosts(inventory="inventory.ini", pattern="switches")
results = hosts.ping()                       # parallelism via forks=
for hostname, r in results.items():
    print(hostname, r["ping"])

# Container API: index, iterate, len
print(len(hosts), hosts.hostnames)
first = hosts[0]                             # -> AnsibleHost
by_name = hosts["sw-01"]                     # -> AnsibleHost
for h in hosts:
    print(h.hostname)

Dynamic dispatch and task directives

Any Ansible module is callable as a method via __getattr__ (host.<module_name>(...)):

host.copy(src="/etc/hosts", dest="/tmp/hosts.bak")
host.command("rm /tmp/maybe-missing", task_directives={"ignore_errors": True})
host.shell("echo $TOKEN", task_directives={"no_log": True})

Common task_directives: ignore_errors, no_log, when, failed_when, changed_when, become.

Batch mode — queue tasks, run them in a single play

with host:
    host.shell("uptime")
    host.shell("df -h")
    host.shell("free -m")
results = host.results

Building a queue across functions

with host: is lexically scoped. If you need to assemble a batch across multiple functions, use the explicit form — same machinery, no scope limit:

host.load_module("ansible.builtin.command", args=["uptime"])
host.load_module("ansible.builtin.command", args=["df -h"])
results = host.run_loaded_modules()

Result shapes

single task batch (with block)
single host dict list[dict]
multi host {hostname: dict} {hostname: list[dict]}

Failures

A failing module raises AnsibleModuleFailed:

from ansible_host import AnsibleModuleFailed

try:
    host.command("false")
except AnsibleModuleFailed as e:
    print("module failed:", e)

# Or suppress and inspect the result:
result = host.command("false", task_directives={"ignore_errors": True})
assert result["failed"] is True

More examples

See tests/test_local_integration.py for 30 runnable examples covering ping, command, shell, batch mode, dynamic dispatch, no_log, forks, multi-host fanout, per-host failure aggregation, and the container protocol.

Compatibility

This library uses Ansible's internal Python API (TaskQueueManager, InventoryManager, VariableManager, Play, DataLoader). Those APIs are not officially stable across ansible-core releases — expect occasional updates when ansible-core introduces breaking internal changes. The current support range is declared in pyproject.toml and in the matrix CI.

Concurrency

ansible-host is designed for sequential use at the instance level. For parallelism within a single call, use Ansible's native forking via the forks= option. Running multiple AnsibleHost / AnsibleHosts instances concurrently in different threads will race on ansible.context's process-global state.

Reference implementation

A real-world use of this pattern lives in sonic-mgmt's tbng branchansible-host is the cleaned-up, packaged version of that code.

License

Apache License 2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ansible_host-0.1.0a0.tar.gz (25.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ansible_host-0.1.0a0-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

Details for the file ansible_host-0.1.0a0.tar.gz.

File metadata

  • Download URL: ansible_host-0.1.0a0.tar.gz
  • Upload date:
  • Size: 25.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ansible_host-0.1.0a0.tar.gz
Algorithm Hash digest
SHA256 e3eb46cc8cbb068dd1eab6462584aa4cef06ae4ac863d6246874dd31af731d0b
MD5 ff91c86bf328f494e4fd60895eb94b42
BLAKE2b-256 3611805750a007ccc09d3ec8ab08fbde8b2fcf7a35b23d903e76ccc6c3b61938

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_host-0.1.0a0.tar.gz:

Publisher: publish.yml on wangxin/ansible-host

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ansible_host-0.1.0a0-py3-none-any.whl.

File metadata

  • Download URL: ansible_host-0.1.0a0-py3-none-any.whl
  • Upload date:
  • Size: 22.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ansible_host-0.1.0a0-py3-none-any.whl
Algorithm Hash digest
SHA256 0fb70a4871d4f730b6b6bfd7d4c659c0ef1ca2661345855392ad0a569a7bb5fe
MD5 132a13588f31d7dff58c19304ac03043
BLAKE2b-256 6ec0b1c9cb4bc1fdf21a649e17552f27f253270a2184a74b8940cf6f0eeb8148

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_host-0.1.0a0-py3-none-any.whl:

Publisher: publish.yml on wangxin/ansible-host

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page