-
Feature Request
-
Resolution: Unresolved
-
Normal
-
None
-
2.5, 2.6
-
None
-
False
-
-
False
- What is the nature and description of the request?
The customer is requesting a new feature for the Ansible Automation Platform (AAP) installer — specifically for the image copy/push workflow involving Skopeo and Private Automation Hub (PAH).
Current behavior:
-
- During installation, AAP always executes skopeo copy for each execution environment (EE) listed.
-
- The installer does not check whether the image already exists in PAH.
-
- As a result, the installer attempts to re-copy/re-push all images every time, even if:
-
-
- The image already exists in PAH
-
-
-
- The customer uses custom EE images already loaded into PAH
-
Requested enhancement:
-
- Add logic that skips the image copy step if the image already exists in Private Automation Hub.
-
- The installer should behave intelligently and avoid redundant copying.
- Why does the customer need this? (List the business requirements here)
The customer needs this enhancement for the following reasons:
-
- Reduce installation failures
-
-
- Failures in the copy process (e.g., due to proxy, CDN restrictions, or network filtering) should not affect images that already exist locally.
-
-
-
- Their custom EE images were impacted even though they should not need syncing from any external registry.
-
-
-
-
- Private Automation Hub is designed to operate fully offline, especially in secure environments.
-
-
-
-
-
- If images already exist, trying to copy from external sources is unnecessary and introduces risk.
-
-
-
- Increase installation efficiency
-
-
- Copying large container images is slow and resource-intensive.
-
-
-
- Skipping already-present images saves bandwidth, time, and storage.
-
-
- Prevent corruption of local custom EE images
-
-
- The installer's forced re-copy logic caused partially written images, resulting in broken blobs (404 errors).
-
-
-
- Avoiding unnecessary copying prevents corruption from incomplete transfers.
-
- How would you like to achieve this? (List the functional requirements here)
To meet the above business needs, the customer requests:
- Pre-copy validation logic
-
- Before running skopeo copy, the installer should check if the image (name + tag) already exists in Private Automation Hub.
-
- Validation method could include:
-
-
- Manifest digest comparison
-
-
-
- Tag existence check via PAH API
-
-
-
- Local hash/digest lookup in Pulp
-
- Conditional behavior
-
- If the target image exists and is identical → Skip copy
-
- If it does not exist or differs → Proceed with skopeo copy
-
- Idempotency
-
-
- Allow repeated installer runs without breaking existing images in PAH.
-
-
-
- Prevent partially written or corrupted blobs.
-
$ cat collections/ansible_collections/ansible/automation_platform_installer/roles/misc/tasks/setup_ee_images.yml
The failing snippet is as follows:
~~~~
—
- block:
- name: Ensure skopeo exists
dnf:
name: skopeo
state: present
register: installed_skopeo
- name: Set list of images to upload for controller and execution nodes
set_fact:
_images_to_upload: '{{ ee_images }}'
when: inventory_hostname in groups.get('automationcontroller', []) | union(groups.get('execution_nodes', []))
- name: Set list of images to upload for hub
set_fact:
_images_to_upload: '{{ ee_images | union(de_images) | union(extra_images) }}'
when: inventory_hostname in groups.get('automationhub', [])
- name: Set list of images to upload for EDA
set_fact:
_images_to_upload: '{{ de_images }}'
when: inventory_hostname in _automationedacontroller_web_hosts
- name: Set up images
block:
- name: Set source registry credential (username)
set_fact:
src_registry_creds: "--src-creds '{{ registry_username }}'"
when:
- registry_username | default('') | length
- not registry_password | default('') | length
- name: Set source registry credential (username and password)
set_fact:
src_registry_creds: "--src-creds '{{ registry_username }}:{{ registry_password }}'"
when:
- registry_username | default('') | length
- registry_password | default('') | length
no_log: "{{ _no_log }}"
- name: Push images to Automation Hub registry
command: skopeo copy \
--retry-times 5 \
{{ src_registry_creds | default('') }} --src-tls-verify={{ _registry_verify_ssl | default(true) | bool }} \
--dest-creds '{{ _automationgateway_admin_username }}:{{ automationgateway_admin_password }}' --dest-tls-verify=false \
docker://{{ _ee_image_base }}{{ item }}:latest \
docker://{{ _automationgateway_main_netloc }}/{{ item }}:latest
environment:
HTTP_PROXY: "{{ http_proxy | default('') }}"
HTTPS_PROXY: "{{ https_proxy | default('') }}"
NO_PROXY: "{{ no_proxy | default('') }}"
register: _push_ee_result
ignore_errors: true
no_log: "{{ _no_log }}"
with_items: '{{ _images_to_upload }}'
- name: Catch error when not all images are processed
set_fact:
_image_push_error: "{{ _image_push_error | default([]) + [_push_ee_result.msg] }}"
when: _push_ee_result.results is not defined
- name: Parse error messages
set_fact:
_image_push_error: "{{ _image_push_error | default([]) + [item.stderr] }}"
with_items: "{{ _push_ee_result.results }}"
no_log: "{{ _no_log }}"
when: item | default({}) is failed
when:
- inventory_hostname in groups['automationhub'] | default([])
- not bundle_install | default(false) | bool
- name: Set up images (bundle)
include_tasks: push_bundle_ee_image.yml
with_items: '{{ _images_to_upload }}'
when: bundle_install | default(false) | bool
- name: Parse error messages
set_fact:
_image_push_error_messages: "{{ _image_push_error | default([]) + _bundle_image_push_error | default([]) }}"
no_log: "{{ _no_log }}"
- name: Ensure images are pushed
fail:
msg: "Failed to push image(s), reason: {{ _image_push_error_messages }}"
when: _image_push_error_messages | default([]) | length
always:
- name: Remove skopeo if added by installer
dnf:
name: skopeo
state: absent
autoremove: true
when: installed_skopeo is changed
~~~~