Skip to main content

Simple & Transparent Executor for Ansible-Playbooks

Project description

Ansible Runner minimal

Support Badge (Donate, Support-Licenses)


Check Docs Lint Unit-Tests Integration-Tests

DISCLAIMER: This is an unofficial community project! Do not confuse it with the vanilla Ansible/Ansible-Runner product!

WARNING: This project is still in early development. DO NOT use it in production!


Scope

The scope of this project is it to create a simple and transparent Python3-interface that can be used to execute Ansible-playbooks.

It will focus on using docker or podman to execute ansible in an isolated environment. But local execution will also be available.

The implementation will be opinionated and will have a 'narrow' interface.

Motivation

I was not 100% happy with the official ansible-runner library.

  • ansible-runner provides a lot more functionality than we actually need (only executing ansible-playbooks) and thus has a lot more complexity added-on. This makes it also hard to troubleshoot.

  • ansible-runner has lax input-validation - bad user-input might be silently skipped/ignored and thus lead to unexpected behaviour

As I needed an alternative I wanted to provide it to the community to play with. (:

I will try to create a transparent documentation and a lot of unit- & integration-tests!

All user-inputs are validated for data-type and value.

Feel free to give feedback as GitHub issues or email.


Roadmap

  • Ansible Execution
    • Config Object & Validation incl. inline-docs
    • Engines
      • Local Executor
      • Container Executor
        • Docker
        • Podman
    • Functionality
      • Playbook targeting local machine
      • Playbook targeting remote Linux server (SSH-Key, Connect-Pass, Become-Pass, Vault-Pass)
        • Pass secrets via one-time-read Pipes/FIFO (in-memory - does not write to disk)
      • Stopping job
      • Redirect output (stdout/stderr) to log-files
      • Playbook Status (per category, per host)
        • Track stati at runtime
  • Tests
    • Unit-Tests for all components (>85% coverage)
      • Execution Config-Validation
      • Execution
        • Before
          • Base-Executor
          • Local Executor-Engine
          • Containerized Executor-Engine
        • After
        • Execution-Status
    • Integration-Tests for many practical use-cases
      • Simple execution targeting localhost
      • Passing extra-vars
      • Passing env-vars
      • Enabling output-colors
      • User stopping execution
      • Execution reached timeout
      • Passing secrets (as value & as file)
        • SSH-Key (via ssh-agent)
        • Connect-Pass
        • Become-Pass
        • Ansible-Vault
      • SSH
        • SSH-Key usage
        • Known-Hosts file
      • tbc...
    • Integration-Tests also for containerized executor

Install

pip install oxl-ansible-executor

See: pypi.org/oxl-ansible-executor


Usage

from oxl_ansible_executor import Execution, ExecutionConfig

c = ExecutionConfig(
  playbook_dir='/home/demo/ansible/',
  playbook_file='test.yml',
  inventory_files='inv/env1/hosts.yml',
  debug=True,  # output infos to stdout (for testing purposes)
)
e = Execution(c)

e.run(blocking=True)
# [INFO] Creating log-files
# [INFO] Using executor: local
# [INFO] Creating secret-pipes
# [INFO] Using log files: /home/demo/.local/share/oxl-ansible-executor/ansible_1775500760_lhWOT_stdout.log & /home/demo/.local/share/oxl-ansible-executor/ansible_1775500760_lhWOT_stderr.log
# [INFO] Executing ansible-playbook
# [INFO] Command: ['ssh-agent', 'sh', '-c', 'ssh-add /tmp/ar_znjp4bih/.fIWqOdKaPzGioFfDljSw && /home/demo/.venv/bin/ansible-playbook -i inv/abc/hosts.yml -C -D -l srv1 --key-file /tmp/ar_znjp4bih/.fIWqOdKaPzGioFfDljSw --become-pass-file /tmp/ar_znjp4bih/.SHVTpOYOH93aaZBTAgVJ --vault-pass-file /tmp/ar_znjp4bih/.GwkiXZ7YrpEvGY8BnyF2 syslog.yml']

print(e.status)
# {
#   "finished": true,
#   "playbook_finished": true,
#   "failed": false,
#   "canceled": false,
#   "time_start": 1775500758,
#   "time_finish": 1775500783,
#   "timed_out": false,
#   "time_duration_sec": 25,
#   "log_stdout_file": "/home/demo/.local/share/oxl-ansible-executor/ansible_1775500760_lhWOT_stdout.log",
#   "log_stderr_file": "/home/demo/.local/share/oxl-ansible-executor/ansible_1775500760_lhWOT_stderr.log",
#   "ansible_command": [
#     "ansible-playbook",
#     "-i",
#     "inv/abc/hosts.yml",
#     "-C",
#     "-D",
#     "-l",
#     "srv1",
#     "--key-file",
#     "/tmp/ar_znjp4bih/.fIWqOdKaPzGioFfDljSw",
#     "--become-pass-file",
#     "/tmp/ar_znjp4bih/.SHVTpOYOH93aaZBTAgVJ",
#     "--vault-pass-file",
#     "/tmp/ar_znjp4bih/.GwkiXZ7YrpEvGY8BnyF2",
#     "syslog.yml"
#   ],
#   "process_command": [
#     "ssh-agent",
#     "sh",
#     "-c",
#     "ssh-add /tmp/ar_znjp4bih/.fIWqOdKaPzGioFfDljSw && /home/demo/.venv/bin/ansible-playbook -i inv/abc/hosts.yml -C -D -l srv1 --key-file /tmp/ar_znjp4bih/.fIWqOdKaPzGioFfDljSw --become-pass-file /tmp/ar_znjp4bih/.SHVTpOYOH93aaZBTAgVJ --vault-pass-file /tmp/ar_znjp4bih/.GwkiXZ7YrpEvGY8BnyF2 syslog.yml"
#   ],
#   "process_rc": 0,
#   "process_result": {
#     "failed": false,
#     "rc": 0,
#     "pid": null,
#     "stdout": "<OMITTED FOR DEMO>",
#     "stderr": "<OMITTED FOR DEMO>",
#     "stdout_lines": [
#       "PLAY [all] *********************************************************************",
#       "",
#       "TASK [Install rsyslog & logrotate] *********************************************",
#       "ok: [srv1]",
#       "",
#       "TASK [Add certificates] ********************************************************",
#       "ok: [srv1] => (item={'c': '-----BEGIN CERTIFICATE-----\\nMIIDdjCCAv2gAwIBAgIUUkucdMI33le6pBxGgw6WRP2yPlcwCgYIKoZIzj0EAwIw\\ngZExCzAJBgNVBAYTAkFUMQ8wDQYDVQQIDAZTdHlyaWExDTALBgNVBAcMBEdyYXox\\nGDAWBgNVBAoMD09YTCBJVCBTZXJ2aWNlczESMBAGA1UECwwJTG9nc2VydmVyMRUw\\nEwYDVQQDDAxMb2dzZXJ2ZXIgQ0ExHTAbBgkqhkiG9w0BCQEWDmNvbnRhY3RAb3hs\\nLmF0MB4XDTI0MTIyNDEzMjExOFoXDTQ0MTIxOTEzMjExOFowgZExCzAJBgNVBAYT\\nAkFUMQ8wDQYDVQQIDAZTdHlyaWExDTALBgNVBAcMBEdyYXoxGDAWBgNVBAoMD09Y\\nTCBJVCBTZXJ2aWNlczESMBAGA1UECwwJTG9nc2VydmVyMRUwEwYDVQQDDAxMb2dz\\nZXJ2ZXIgQ0ExHTAbBgkqhkiG9w0BCQEWDmNvbnRhY3RAb3hsLmF0MHYwEAYHKoZI\\nzj0CAQYFK4EEACIDYgAEUwaiRMy1OcN0j5odvoTir6LFAqAlUlDp708Y39ZdFduv\\nXMEJGKWeHUKnoMT4uaDEomlwqEUa5JcG3Z9R0PeCJsNXvns53uK1j1uMY395yIvW\\nyQ8yu1vDhD/OnnOMl6oro4IBEjCCAQ4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQU\\nvk1BL8cxa/eNRSQDD/T+yTyA7sswgdEGA1UdIwSByTCBxoAUvk1BL8cxa/eNRSQD\\nD/T+yTyA7suhgZekgZQwgZExCzAJBgNVBAYTAkFUMQ8wDQYDVQQIDAZTdHlyaWEx\\nDTALBgNVBAcMBEdyYXoxGDAWBgNVBAoMD09YTCBJVCBTZXJ2aWNlczESMBAGA1UE\\nCwwJTG9nc2VydmVyMRUwEwYDVQQDDAxMb2dzZXJ2ZXIgQ0ExHTAbBgkqhkiG9w0B\\nCQEWDmNvbnRhY3RAb3hsLmF0ghRSS5x0wjfeV7qkHEaDDpZE/bI+VzALBgNVHQ8E\\nBAMCAQYwCgYIKoZIzj0EAwIDZwAwZAIwHbFj7SEsIg3dUBpAkKIfLWVrpKicxDUe\\nKqUd/hcXHX/TTKKd0yehyXhZR0HBYgHEAjAbxJb8pQIVzCowHcXmv790wOiSsaFL\\nQJuH8qil1t0JSAV73EdK9zM+IDdvBVdDlBw=\\n-----END CERTIFICATE-----\\n', 'f': 'log_ca.crt'})",
#       "ok: [srv1] => (item={'c': '-----BEGIN CERTIFICATE-----\\nMIIDgTCCAwagAwIBAgIQX7p1IkBq4b97O8k0caiMfjAKBggqhkjOPQQDAjCBkTEL\\nMAkGA1UEBhMCQVQxDzANBgNVBAgMBlN0eXJpYTENMAsGA1UEBwwER3JhejEYMBYG\\nA1UECgwPT1hMIElUIFNlcnZpY2VzMRIwEAYDVQQLDAlMb2dzZXJ2ZXIxFTATBgNV\\nBAMMDExvZ3NlcnZlciBDQTEdMBsGCSqGSIb3DQEJARYOY29udGFjdEBveGwuYXQw\\nHhcNMjQxMjI0MTQyNzA4WhcNMjkxMjIzMTQyNzA4WjCBjDELMAkGA1UEBhMCQVQx\\nDzANBgNVBAgMBlN0eXJpYTENMAsGA1UEBwwER3JhejEYMBYGA1UECgwPT1hMIElU\\nIFNlcnZpY2VzMRIwEAYDVQQLDAlMb2dzZXJ2ZXIxEDAOBgNVBAMMB2dlbmVyaWMx\\nHTAbBgkqhkiG9w0BCQEWDmNvbnRhY3RAb3hsLmF0MHYwEAYHKoZIzj0CAQYFK4EE\\nACIDYgAEF2uLX4WUd/4byt3aS59XxohILfEdnNvqdg87nG0PXC85yhtB5yKMWryT\\n+cWZeGYSucdLtZ4UxDqvosQ32eql/K+VoVRqkb4UF1Mmgq5+smhHIkVxFjJCUtsg\\ni+G9aPM/o4IBJDCCASAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUmULR2FK41wLFEl/B\\nSGhYkQ0Z5v8wgdEGA1UdIwSByTCBxoAUvk1BL8cxa/eNRSQDD/T+yTyA7suhgZek\\ngZQwgZExCzAJBgNVBAYTAkFUMQ8wDQYDVQQIDAZTdHlyaWExDTALBgNVBAcMBEdy\\nYXoxGDAWBgNVBAoMD09YTCBJVCBTZXJ2aWNlczESMBAGA1UECwwJTG9nc2VydmVy\\nMRUwEwYDVQQDDAxMb2dzZXJ2ZXIgQ0ExHTAbBgkqhkiG9w0BCQEWDmNvbnRhY3RA\\nb3hsLmF0ghRSS5x0wjfeV7qkHEaDDpZE/bI+VzALBgNVHQ8EBAMCBaAwEwYDVR0l\\nBAwwCgYIKwYBBQUHAwIwCgYIKoZIzj0EAwIDaQAwZgIxAKVAFBs4EaCRx/0VEZKA\\n3/n06CaEE5I05v8kN5XBWgbJPxaDi+bcRJrzBMsn/JRjvwIxAMi4cekyGCWZYDtM\\n+8WRliIMba5dbFuR/UGAf/bIfmNWM2sSqtzseSZ/RoPdjaChlQ==\\n-----END CERTIFICATE-----\\n', 'f': 'log_client.crt'})",
#       "",
#       "TASK [Add certificate key] *****************************************************",
#       "ok: [srv1]",
#       "",
#       "TASK [Add graylog forwarding] **************************************************",
#       "ok: [srv1]",
#       "",
#       "TASK [Software log files] ******************************************************",
#       "ok: [srv1]",
#       "",
#       "TASK [Software log rotation] ***************************************************",
#       "ok: [srv1]",
#       "",
#       "TASK [Restart services] ********************************************************",
#       "changed: [srv1] => (item=rsyslog.service)",
#       "changed: [srv1] => (item=logrotate.service)",
#       "",
#       "PLAY RECAP *********************************************************************",
#       "srv1                       : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0"
#     ],
#     "stderr_lines": [
#       "Identity added: /tmp/ar_znjp4bih/.fIWqOdKaPzGioFfDljSw (Demo)"
#     ]
#   }
# }

# to stop a running execution
e = Execution(c)
e.run(blocking=False)
# you could 'tail -f' the log files
e.stop()  # executor sends signals to subprocess running ansible

Use-Cases

See: Our simple Ansible WebUI


Contribute

We are happy to see contributions. (:

  • Report issues
  • Create feature-requests
  • Provide PR's for:
    • more Unit-Tests
    • more Integration-Tests
    • fixing bugs/errors
    • enhancing the input-validation
    • ...

Security Considerations

  • Secrets are passed to Ansible via one-time-readable FIFO/Pipes
  • SSH-agent is used to pass SSH-keys to Ansible
  • Files are created with an explicit 0600 file-mode
  • By default, the temporary runtime-directory is removed after the execution has finished (only log-files remain - see example above)
  • tbc

AI-Usage Info

The coding of this project involved minimal AI-usage.

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

oxl_ansible_executor-0.1.5.tar.gz (48.5 kB view details)

Uploaded Source

Built Distribution

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

oxl_ansible_executor-0.1.5-py3-none-any.whl (53.5 kB view details)

Uploaded Python 3

File details

Details for the file oxl_ansible_executor-0.1.5.tar.gz.

File metadata

  • Download URL: oxl_ansible_executor-0.1.5.tar.gz
  • Upload date:
  • Size: 48.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.2

File hashes

Hashes for oxl_ansible_executor-0.1.5.tar.gz
Algorithm Hash digest
SHA256 796ff40241433fbbeebb27e6e73e30f4ac16bfc8c2ad84d4e95d4b66f3399cd2
MD5 e43874da4b2a3e00a2704eb48e8a93c1
BLAKE2b-256 d95d157031a9ff30669618f8b7790fb2fa30ae83c35832229df79785c3189718

See more details on using hashes here.

File details

Details for the file oxl_ansible_executor-0.1.5-py3-none-any.whl.

File metadata

File hashes

Hashes for oxl_ansible_executor-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 cf86279861f97fb05dab622b9454382d7dfe1af8f37068f40aa80fa4240169e7
MD5 ea826794bf00ef960f0c0af1e37f924e
BLAKE2b-256 3109b765ac16fce67c41dd3a993c3f47409174b8251531e8bed8a77b160a2cc7

See more details on using hashes here.

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