Skip to main content

ansible_shed

Simple Ansible tower to run playbooks via ansible-playbook + export prometheus metrics about success.

Example Run + Stats

Playbook(s) will be run on host(s) and then the output parsed to generated statistics

Log example:

[2021-03-09 15:59:36,239] DEBUG: Starting /usr/local/bin/ansible-shed (main.py:71)
[2021-03-09 15:59:36,239] DEBUG: Using selector: EpollSelector (selector_events.py:59)
[2021-03-09 15:59:36,241] DEBUG: Prometheus metrics server starting on :::12345/metrics (service.py:133)
[2021-03-09 15:59:36,243] INFO: Rebasing /tmp/ansible_shed/repo from git@github.com:cooperlees/clc_ansible.git (shed.py:36)
[2021-03-09 15:59:36,246] DEBUG: Prometheus metrics server started on http://[::]:12345/metrics (service.py:160)
[2021-03-09 15:59:36,246] INFO: Serving prometheus metrics on: http://[::]:12345/metrics (shed.py:150)
Already up to date.
Current branch master is up to date.
[2021-03-09 15:59:37,480] INFO: Running ansible-playbook: '/home/cooper/venvs/a/bin/ansible-playbook --inventory hosts site.yaml --limit home2.cooperlees.com --tags chrony --skip-tags php_static_files,zfs' (shed.py:70)
[2021-03-09 15:59:38,906] DEBUG: negotiating {'*/*'} resulted in choosing TextFormatter (negotiator.py:32)
[2021-03-09 15:59:38,908] INFO: ::1 [09/Mar/2021:15:59:38 +0000] "GET /metrics HTTP/1.1" 200 1128 "-" "curl/7.68.0" (web_log.py:206)
[2021-03-09 15:59:53,651] INFO: Finished running ansible in 16s (shed.py:75)
[2021-03-09 15:59:53,651] INFO: Parsing ansible run output to update stats (shed.py:79)
[2021-03-09 15:59:53,652] DEBUG: Host Results: home2.cooperlees.com - ok=7    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0    (shed.py:92)
[2021-03-09 15:59:53,652] DEBUG: Updating prometheus stats due to event being set (shed.py:129)
[2021-03-09 15:59:53,652] INFO: Updated 10 metrics (shed.py:141)
[2021-03-09 15:59:53,652] INFO: Finished ansible run in 17s. Sleeping for 43s (shed.py:176)
[2021-03-09 15:59:53,652] DEBUG: Stats:
{
  "ansible_last_run_returncode": 0,
  "ansible_last_run_time": 16,
  "ansible_stats_last_updated": 1615305593,
  "host_home2.cooperlees.com_changed": 0,
  "host_home2.cooperlees.com_failed": 0,
  "host_home2.cooperlees.com_ignored": 0,
  "host_home2.cooperlees.com_ok": 7,
  "host_home2.cooperlees.com_rescued": 0,
  "host_home2.cooperlees.com_skipped": 1,
  "host_home2.cooperlees.com_unreachable": 0
} (shed.py:177)
[2021-03-09 15:59:57,045] DEBUG: negotiating {'*/*'} resulted in choosing TextFormatter (negotiator.py:32)
[2021-03-09 15:59:57,047] INFO: ::1 [09/Mar/2021:15:59:57 +0000] "GET /metrics HTTP/1.1" 200 1577 "-" "curl/7.68.0" (web_log.py:206)

Metrics Example:

# HELP ansible_changed Number of 'changed' plays
# TYPE ansible_changed gauge
ansible_changed{hostname="home2.cooperlees.com"}
# HELP ansible_failed Number of failed plays on hosts
# TYPE ansible_failed gauge
ansible_failed{hostname="home2.cooperlees.com"} 0
# HELP ansible_ignored Number of ignored plays on hosts
# TYPE ansible_ignored gauge
ansible_ignored{hostname="home2.cooperlees.com"} 0
# HELP ansible_last_run_returncode UNIX return code of the ansible-playbook process
# TYPE ansible_last_run_returncode gauge
ansible_last_run_returncode 0
# HELP ansible_last_run_time Time in seconds it took the ansible-playbook process to execute
# TYPE ansible_last_run_time gauge
ansible_last_run_time 17
# HELP ansible_ok Number of 'ok' (no change) plays
# TYPE ansible_ok gauge
ansible_ok{hostname="home2.cooperlees.com"} 7
# HELP ansible_rescued Number of rescued plays on hosts
# TYPE ansible_rescued gauge
ansible_rescued{hostname="home2.cooperlees.com"} 0
# HELP ansible_skipped Number of skipped plays on hosts
# TYPE ansible_skipped gauge
ansible_skipped{hostname="home2.cooperlees.com"} 1
# HELP ansible_stats_last_updated UNIX timestamp of last time we updated the stats
# TYPE ansible_stats_last_updated gauge
ansible_stats_last_updated 1615305655
# HELP ansible_unreachable Number of inaccessible hosts
# TYPE ansible_unreachable gauge
ansible_unreachable{hostname="home2.cooperlees.com"} 0
  • Avaliable http://IP:PORT/metrics
  • Additional REST APIs (token-authenticated using X-API-Token header):
    • POST /pause with timestamp in JSON body (UNIX epoch or ISO8601) or query
    • POST /force-run
    • GET /healthz validates ansible-playbook --help and git --help

API CLI

ansible_shed now installs ansible-shed-cli in the same Python environment as the service. It reads api_token and port from the same config file:

  • ansible-shed-cli --config /etc/ansible_shed.ini pause --timestamp 1735689600
  • ansible-shed-cli --config /etc/ansible_shed.ini force-run
  • ansible-shed-cli --config /etc/ansible_shed.ini healthz

Grafana Dashboard

Install

We're not on PyPI as I don't feel the need (if we get popular that's easy to fix).

  • pip install git+https://github.com/cooperlees/ansible_shed

or if you want ansible tools installed into the same Python environment use our ansible extra install:

  • pip install git+https://github.com/cooperlees/ansible_shed#egg=ansible_shed[ansible]

SystemD

Today I only run it by systemd cause it makes SSH auth easier. Would happily take a Dockerfile PR.

Config

(TODO: Full config file docs - PR welcome)

We have a simple ini file to point @ your ansbile-playbook binary and arguments. If not specified, ansible_shed defaults to look for /etc/ansible_shed.ini

Config Settings:

  • interval: Minutes between ansible-playbook runs
  • start_splay: Upper max of time to wait before first ansible-playbook run after starting the service - Code generates a random int from 0 to this upper max.
  • port: Statistics listening port + interval
  • vault_pass_file: (Optional) Path to Ansible vault password file. If set, this file will be copied to .vault_pass in the checked out repo and ansible-playbook will be run with --vault-password-file flag.
  • api_token: API token required in X-API-Token for /pause, /force-run, and /healthz
  • ansible_playbook_binary: Must point to an ansible-playbook binary inside a Python virtualenv (<venv>/bin/ansible-playbook); ansible_shed uses the sibling <venv>/bin/activate script path to activate that venv environment

mypyc build/install

ansible_shed can be compiled with mypyc. The code is strictly typed and that allows for it to be converted to C and compiled.

To enable, set a environment variable asking for a mypyc build

Only tested on Linux

  • export MYPYC_BUILD=1
  • pip install -U pip mypy setuptools wheel
  • pip install ansible_shed

Release files for ansible-shed 2026.7.27

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ansible-shed 2026.7.27
File Size Uploaded
ansible_shed-2026.7.27.tar.gz 29.9 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for ansible-shed 2026.7.27
File
ansible_shed-2026.7.27-py3-none-any.whl Python 3 none any Details
ansible_shed-2026.7.27-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
ansible_shed-2026.7.27-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.14 CPython 3.14 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
ansible_shed-2026.7.27-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
ansible_shed-2026.7.27-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details

Total release size: 1.8 MB

Release files / ansible_shed-2026.7.27.tar.gz

Download URL ansible_shed-2026.7.27.tar.gz
Size 29.9 kB
Tags Source
SHA-256 checksum
How to use checksums
17518384b16963028276d6117e7fef9cade27068aece7c4af6740e67c853a4ef
BLAKE2b-256 checksum
How to use checksums
770e4d458fe5f153c21c8c4cc4636bf6e616277a7c2e6273e0251df500d45a84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Release files / ansible_shed-2026.7.27-py3-none-any.whl

Download URL ansible_shed-2026.7.27-py3-none-any.whl
Size 33.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b1dbfd9f24fcfecfd0f6b789f160d4fd4d9b7df29444ed2edaea524300d7e39
BLAKE2b-256 checksum
How to use checksums
4a1d116d6982fcaccae8c68dc9027deb26a2bfa201bf7abd8ecf82908681f474
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Release files / ansible_shed-2026.7.27-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL ansible_shed-2026.7.27-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 441.2 kB
Tags CPython 3.14 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
ca31e4abf6bf58400d033b751fe48257395fc4c7111f8f3deddb34a39f482bae
BLAKE2b-256 checksum
How to use checksums
4e7b5af09b6b0732ff8761e0cef3080879d857ec66c3653329f45beffaa1472b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Release files / ansible_shed-2026.7.27-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL ansible_shed-2026.7.27-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 426.2 kB
Tags CPython 3.14 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
41cd2b50663182eac91fa1295bec2fb90e101e07e93659447d1bc8ae89bc806b
BLAKE2b-256 checksum
How to use checksums
071d7381856ebd5782aafb68cc36c4b6f547ee013c00a468ac9c10b35046cd27
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Release files / ansible_shed-2026.7.27-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL ansible_shed-2026.7.27-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 440.2 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
9635732d7099dd0797e88247922a9b5cdff828cbc5e2d42ab7f1b66edf50f53b
BLAKE2b-256 checksum
How to use checksums
388e716c12bb9f8b2545dba260003466591c3db542fb961a4361f59125051d28
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Release files / ansible_shed-2026.7.27-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL ansible_shed-2026.7.27-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 423.8 kB
Tags CPython 3.13 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
7ab2fedd4389fa835be45567c1adbf999b370f17f9748ee7c58cd17d1f77adb5
BLAKE2b-256 checksum
How to use checksums
a2c39a0275e49c7ef8af4ca3dd6c8daf9282fc43d3a813ec7ced6a81eed85549
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 27, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2026.7.27 This release

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page