Ansible Runner

repository·devel·Indexed 22 days ago

https://github.com/ansible/ansible-runner

A stable, consistent abstraction layer for interfacing with Ansible via a Python API and CLI. It provides container and process isolation runtime capabilities using Execution Environments (OCI-compliant images), modularizes task execution and output gathering, and supports emitting status and event data to external systems via plugins.

Tokens
16.3K
Snippets
49
Records
79
Agent score
77%

What's inside ansible-runner

  1. What is Ansible Runner?

    devel

    Ansible Runner is a tool and Python library designed to provide a stable, consistent interface abstraction for Ansible. It is used to interface with ansible and ansible-playbook tasks, making it easier to embed Ansible into other systems like CI/CD platforms (e.g., Jenkins) or automated tooling without managing the complexities of the Ansible interface directly.

    It modularizes the task execution and output gathering logic (similar to how Ansible AWX operates) and provides a system for storing stdout, host-level event data, and fact data.

  2. Parse Runner Artifact Job Events

    devel

    Instead of parsing raw stdout, you can use the JSON files in the job_events directory to programmatically process Ansible execution details. Runner assigns order to these events and includes the associated stdout and line numbers for each event.

    Key event types include:

    • playbook_on_task_start: Emitted when a task begins.
    • playbook_on_stats: The final event emitted if a playbook runs to completion without being killed, containing the PLAY RECAP data.

    Each event JSON object typically includes:

    • uuid: Unique identifier for the event.
    • event: The type of event (e.g., playbook_on_task_start).
    • event_data: Metadata specific to the event (e.g., task_uuid, playbook, task_args).
    • stdout: The relevant portion of stdout for that event.
    • start_line / end_line: The line range in the stdout file.
    • created: Timestamp of the event.
    {
      "uuid": "8c164553-8573-b1e0-76e1-000000000008",
      "parent_uuid": "xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "counter": 5,
      "stdout": "\r\nTASK [debug] *******************************************************************",
      "start_line": 5,
      "end_line": 7,
      "event": "playbook_on_task_start",
      "event_data": {
        "playbook": "test.yml",
        "playbook_uuid": "34437b34-addd-45ae-819a-4d8c9711e191",
        "play": "all",
        "play_uuid": "8c164553-8573-b1e0-76e1-000000000006",
        "play_pattern": "all",
        "task": "debug",
        "task_uuid": "8c164553-8573-b1e0-76e1-000000000008",
        "task_action": "debug",
        "task_path": "\/home\/mjones\/ansible\/ansible-runner\/demo\/project\/test.yml:3",
        "task_args": "msg=Test!",
        "name": "debug",
        "is_conditional": false,
        "pid": 10640
      },
      "pid": 10640,
      "created": "2018-06-07T14:54:58.410605"
    }
  3. Understand the structure of emitted events

    devel

    Plugins receive two distinct types of events from ansible-runner:

    1. status events: Emitted whenever the Runner's status changes (e.g., moving to running). Example: {"status": "running", "runner_ident": "XXXX" }

    2. ansible events: Emitted during playbook execution for every event received from Ansible (e.g., host or playbook events). Example: {"runner_ident": "XXXX", <rest of event structure> }

  4. Manage Ansible Runner execution modes

    devel

    Ansible Runner provides several command modes to control how the process is launched:

    • run: Starts Runner in the foreground. It waits for the underlying Ansible process to complete before returning. Output is visible in the console and saved to the artifacts directory.
    • start: Starts Runner as a background daemon process and generates a pid file.
    • stop: Terminates a background process previously started with start.
    • is-alive: Checks the status of a background process started with start.

    Regardless of the mode, Runner creates an artifacts directory containing the output and status. You can control the location of the artifacts directory using the -i IDENT argument; otherwise, a random UUID is used.

    ansible-runner run /tmp/private -p playbook.yml
  5. Understand the Ansible Runner Input Directory Hierarchy

    devel

    Ansible Runner can be driven by a directory structure that maps inputs to specific locations. This allows automation tools to gather inputs from various sources (like databases) and prepare them in a single directory for Runner to consume.

    An active configuration follows this hierarchy:

    .
    ├── env
    │   ├── envvars
    │   ├── extravars
    │   ├── passwords
    │   ├── cmdline
    │   ├── settings
    │   └── ssh_key
    ├── inventory
    │   └── hosts
    └── project
        ├── test.yml
        └── roles
            └── testrole
                ├── defaults
                ├── handlers
                ├── meta
                ├── tasks
                └── vars

    Note that not all files are required; Runner will use defaults or omit values if they are not provided.

  6. Understand the Runner Artifacts Directory Hierarchy

    devel

    When a Runner invocation completes, it produces an artifacts directory. This directory is organized under an identifier (either a user-supplied ID or a generated UUID).

    Inside the identifier directory, you will find:

    • fact_cache/: Contains cached facts (e.g., for localhost).
    • job_events/: A collection of JSON files containing detailed task and playbook events.
    • rc: A file containing the actual return code from the Ansible process.
    • status: A file indicating the execution outcome. Possible values are:
      • success: The Ansible process finished successfully.
      • failed: The Ansible process failed.
      • timeout: The Runner timeout was reached.
    • stdout: A file containing the captured standard output from the run.
    .
    ├── artifacts
    │   └── <identifier>
    │       ├── fact_cache
    │       │   └── localhost
    │       ├── job_events
    │       │   ├── <event_id>.json
    │       ├── rc
    │       ├── status
    │       └── stdout
  7. Use Execution Environments with Ansible Runner

    devel

    In the context of Ansible Runner, an Execution Environment is the container runtime execution of Ansible using an OCI-compliant container image. This image bundles Ansible Base, Ansible Collection Content, and necessary runtime dependencies.

    When using Execution Environments, Ansible Runner provides process isolation via a container runtime (using podman by default). This allows you to run Ansible jobs in a consistent, reproducible, and portable manner, similar to how they run in Ansible AWX.

  8. Understand container naming conventions for jobs

    devel

    Every Ansible Runner job has a unique identifier (which is also the name of the artifacts subfolder). When a container is launched for job isolation, it is named using the pattern:

    ansible_runner_<job identifier>

    Some characters from the job identifier may be replaced with underscores to ensure compatibility with the naming constraints of Podman and Docker. This name is used internally to manage the container, such as stopping it if a job is canceled.

  9. Ways to interact with Ansible Runner

    devel

    You can interact with Ansible Runner in three primary ways depending on your use case:

    1. Standalone Command Line Tool: Use the ansible-runner CLI to run tasks in the foreground or asynchronously in the background.
    2. Python Module: Import ansible-runner as a library to integrate Ansible execution directly into your Python applications.
    3. Plugin Interface: Configure Runner to send status and event data to external systems (e.g., sending status to Ansible AWX or events to an external logging service).
  10. How remote job execution works in Ansible Runner

    devel

    Ansible Runner supports executing jobs on a remote host via a three-phase process. This is primarily designed for use with Receptor.

    1. Transmit: Converts the job (private data directory and parameters) into a compressed binary stream emitted to stdout. This stage uses the same command-line parameters as the run command.
    2. Worker: Accepts the binary stream, executes the job, and generates a new compressed binary stream containing job events and artifacts. It can optionally use --private-data-dir to extract the transmitted contents into a specific directory.
    3. Process: Accepts the result stream from the worker, processes job events, fires callbacks, and saves artifacts to the specified data directory.
    ansible-runner transmit ./demo -p test.yml | ansible-runner worker | ansible-runner process ./demo