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

Download files

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

Source Distribution

ansible_shed-2026.7.27.tar.gz (29.9 kB view details)

Uploaded Source

Built Distributions

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

ansible_shed-2026.7.27-py3-none-any.whl (33.8 kB view details)

Uploaded Python 3

ansible_shed-2026.7.27-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (441.2 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

ansible_shed-2026.7.27-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (426.2 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

ansible_shed-2026.7.27-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (440.2 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

ansible_shed-2026.7.27-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (423.8 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

File details

Details for the file ansible_shed-2026.7.27.tar.gz.

File metadata

  • Download URL: ansible_shed-2026.7.27.tar.gz
  • Upload date:
  • Size: 29.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for ansible_shed-2026.7.27.tar.gz
Algorithm Hash digest
SHA256 17518384b16963028276d6117e7fef9cade27068aece7c4af6740e67c853a4ef
MD5 105aa04fbd9a3862e3971ae1b06f5da0
BLAKE2b-256 770e4d458fe5f153c21c8c4cc4636bf6e616277a7c2e6273e0251df500d45a84

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_shed-2026.7.27.tar.gz:

Publisher: release.yml on cooperlees/ansible_shed

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_shed-2026.7.27-py3-none-any.whl.

File metadata

File hashes

Hashes for ansible_shed-2026.7.27-py3-none-any.whl
Algorithm Hash digest
SHA256 4b1dbfd9f24fcfecfd0f6b789f160d4fd4d9b7df29444ed2edaea524300d7e39
MD5 a070d228279f9ac5007a2eb801d43f69
BLAKE2b-256 4a1d116d6982fcaccae8c68dc9027deb26a2bfa201bf7abd8ecf82908681f474

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_shed-2026.7.27-py3-none-any.whl:

Publisher: release.yml on cooperlees/ansible_shed

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_shed-2026.7.27-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for ansible_shed-2026.7.27-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ca31e4abf6bf58400d033b751fe48257395fc4c7111f8f3deddb34a39f482bae
MD5 02bad804d0d3d34da3d7cac7ff068b49
BLAKE2b-256 4e7b5af09b6b0732ff8761e0cef3080879d857ec66c3653329f45beffaa1472b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_shed-2026.7.27-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on cooperlees/ansible_shed

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_shed-2026.7.27-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for ansible_shed-2026.7.27-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 41cd2b50663182eac91fa1295bec2fb90e101e07e93659447d1bc8ae89bc806b
MD5 1aa85cbf7d1511901303e4543ed398af
BLAKE2b-256 071d7381856ebd5782aafb68cc36c4b6f547ee013c00a468ac9c10b35046cd27

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_shed-2026.7.27-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on cooperlees/ansible_shed

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_shed-2026.7.27-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for ansible_shed-2026.7.27-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9635732d7099dd0797e88247922a9b5cdff828cbc5e2d42ab7f1b66edf50f53b
MD5 f64102e48b124bbe3913edcc122902d3
BLAKE2b-256 388e716c12bb9f8b2545dba260003466591c3db542fb961a4361f59125051d28

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_shed-2026.7.27-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on cooperlees/ansible_shed

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_shed-2026.7.27-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for ansible_shed-2026.7.27-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7ab2fedd4389fa835be45567c1adbf999b370f17f9748ee7c58cd17d1f77adb5
MD5 01e776cd4ee6d3819c496ebfddd9a583
BLAKE2b-256 a2c39a0275e49c7ef8af4ca3dd6c8daf9282fc43d3a813ec7ced6a81eed85549

See more details on using hashes here.

Provenance

The following attestation bundles were made for ansible_shed-2026.7.27-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on cooperlees/ansible_shed

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