Skip to content

Execution environments

Since 7.0 (per-task execution environment images since 7.4)

An execution environment (EE) is the container image in which the site controller’s ansible-runner executes an extension’s Ansible task. Everything the playbook needs at runtime must be present in that image:

  • Ansible itself and the Python interpreter
  • Ansible (Galaxy) collections
  • Python (pip) dependencies used by modules
  • Any CLI binary the playbook shells out to (dig, jq, openshift-install, product CLIs, …)

An execution-environment.yml file inside your Ansible bundle is not read at runtime — dependencies must be baked into the EE image itself.

Every task runs in the site controller’s configured ansible-runner image unless it selects a custom EE. See Enabling the Ansible Runner Capability for enabling the runner and for customizing that default image site-wide (deriving a new image from the MetalSoft-provided one).

Customizing the default image affects every extension task at that site. Prefer a per-task EE when the dependencies are specific to one extension.

Since 7.4

An extension can ship its own EE image and select it per task:

  1. Declare an OciImage asset in the extension definition:
{
"label": "ee-my-extension",
"name": "ee-my-extension",
"assetType": "OciImage",
"url": "https://repo.example.com/extensions/ee/ee-my-extension-v1.0.0.tar.gz",
"repositoryRegistry": "registry.example.com",
"namespaceRegistry": "ee-my-extension",
"tagRegistry": "1.0.0"
}

The registry fields (repositoryRegistry, tagRegistry, plus optional hostRegistry, portRegistry, namespaceRegistry) identify the image the runner pulls. The optional url points to a docker save | gzip tarball of the same image, used to load the image into a site-local registry on air-gapped sites.

  1. Select the asset in each Ansible task via the ee option:
{
"label": "installStep",
"taskType": "ExtensionTaskAnsible",
"options": {
"asset": "my-ansible-bundle",
"playbook": "deploy.yaml",
"ee": "ee-my-extension",
"executionTimeout": 3600,
"executionTimeoutTick": 30
}
}

Every task that needs the custom image must set ee individually. A definition that sets ee on the onCreate tasks but not on the onEdit tasks will silently run the edit/scale playbooks in the default EE — where your baked-in tools are missing.

Use ansible-builder with an execution-environment.yml describing your Galaxy collections, pip requirements and system packages, then publish the resulting image. Remember that the yml file only drives the build — it does nothing at runtime.

execution-environment.yml
version: 3
images:
base_image:
name: quay.io/ansible/ansible-runner:latest
dependencies:
galaxy:
collections:
- infoblox.nios_modules
python:
- jmespath
- infoblox-client
system:
- bind-utils [platform:rpm]
- jq [platform:rpm]

Build and tag the image from the directory containing the file:

Terminal window
ansible-builder build -f execution-environment.yml -t registry.example.com/ee-my-extension:1.0.0

The tag must match what the OciImage asset’s registry fields resolve to (repositoryRegistry/namespaceRegistry/tagRegistry).

  • Galaxy collections and pip dependencies your roles use.
  • System packages for every CLI you shell out to. Package names differ across base images — for example dig ships in bind-utils on RHEL/UBI9 but bind-dnsutils on some UBI10 builds. A missing shelled-out tool typically makes dependent tasks silently skip or misbehave rather than fail loudly.
  • A quick sanity check after building:
Terminal window
docker run --rm registry.example.com/ee-my-extension:1.0.0 \
bash -c "ansible-galaxy collection list && dig -v && jq --version"
  • (Coming soon) Connected sites: push the image to a registry reachable by the site controller and reference it via the OciImage registry fields.
Terminal window
docker push registry.example.com/ee-my-extension:1.0.0
  • Air-gapped & COnnected sites: also host a tarball of the image at the asset url:
Terminal window
docker save registry.example.com/ee-my-extension:1.0.0 | gzip > ee-my-extension-v1.0.0.tar.gz
The image is then stored on an http repository, and the http url is placed in the url field OciImage asset in the extension definition.
Section titled “The image is then stored on an http repository, and the http url is placed in the url field OciImage asset in the extension definition.”

The tarball is loaded (docker load) into a site-local registry; the runner still pulls using the registry fields.