An Ansible Playbook to build bootc multi-architecture images on RHEL, Fedora or CentOS Stream
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
5.5 KiB

# This is an Ansible Playbook to build a bootc container image using Podman for two architectures: amd64 and arm64.
- name: Build bootc container image
hosts: builder
vars:
build_name: "example-flightctl"
bootc_project: '{{ playbook_dir }}/examples/flightctl'
image_from:
x86_64: "registry.redhat.io/rhel9/rhel-bootc:9.4"
aarch64: "quay.io/redhat-et/rhel-bootc-tegra:base"
image_to: "edge-registry.itix.fr/bootc/hello-world:latest"
validate_certs: true
# This file must be present on all builder hosts as well as on the control node if pushing to/pulling from a remote registry
# You can create it with:
# sudo REGISTRY_AUTH_FILE=/etc/containers/auth.json podman login registry.redhat.io
# sudo REGISTRY_AUTH_FILE=/etc/containers/auth.json podman login quay.io
auth_file: "/etc/containers/auth.json"
tasks:
- name: Install pre-requisite packages
ansible.builtin.dnf:
name:
- podman
- buildah
- skopeo
- rsync
state: present
- name: Check if Podman auth file exists
ansible.builtin.stat:
path: "{{ auth_file }}"
register: podman_auth_file
when: auth_file is defined
- assert:
that:
- podman_auth_file.stat.exists
fail_msg: |
Podman auth file {{ auth_file }} does not exist. Please create it to authenticate to container registries.
You can create it using the 'podman login' command.
Example:
sudo REGISTRY_AUTH_FILE=/etc/containers/auth.json podman login registry.redhat.io
sudo REGISTRY_AUTH_FILE=/etc/containers/auth.json podman login quay.io
ansible-playbook build.yaml -e auth_file=/etc/containers/auth.json
when: auth_file is defined
- name: Pull bootc base image
containers.podman.podman_image:
name: "{{ image_from[ansible_architecture] }}"
arch: "{{ ansible_architecture }}"
state: present
pull: true
validate_certs: '{{ validate_certs | default(omit) }}'
auth_file: "{{ auth_file | default(omit) }}"
- name: Create a temporary directory for the build
ansible.builtin.tempfile:
state: directory
suffix: bootc_build_
register: temp_build_dir
- name: Copy the bootc project directory to the builder
ansible.posix.synchronize:
mode: push
src: "{{ bootc_project }}/"
dest: "{{ temp_build_dir.path }}/bootc/"
archive: no
recursive: yes
compress: no
delete: no
- name: Build bootc container image
containers.podman.podman_image:
name: "localhost/{{ build_name }}-{{ ansible_architecture }}:latest"
build:
extra_args: "--from={{ image_from[ansible_architecture] }}"
cache: false
file: "{{ temp_build_dir.path }}/bootc/Containerfile"
path: "{{ temp_build_dir.path }}/bootc"
force: true
push: false
state: build
- name: Export the built image to the temporary directory
containers.podman.podman_image:
name: "localhost/{{ build_name }}-{{ ansible_architecture }}:latest"
push: true
push_args:
compress: false
dest: "{{ temp_build_dir.path }}/{{ build_name }}-{{ ansible_architecture }}.tar"
format: oci
transport: oci-archive
state: present
- name: Change ownership of the exported image archive to the ansible user
ansible.builtin.file:
path: "{{ file.path }}"
mode: "{{ file.mode }}"
loop:
- path: "{{ temp_build_dir.path }}/{{ build_name }}-{{ ansible_architecture }}.tar"
mode: '0644'
- path: "{{ temp_build_dir.path }}"
mode: '0755'
loop_control:
loop_var: file
label: "{{ file.path }}"
# The synchronize module is used here to efficiently transfer large files
- name: Fetch the exported image archive to the control node
ansible.posix.synchronize:
mode: pull
src: "{{ temp_build_dir.path }}/{{ build_name }}-{{ ansible_architecture }}.tar"
dest: "{{ playbook_dir }}/builds/"
archive: no
compress: no
delete: no
delegate_to: localhost
- name: Remove the temporary build directory
ansible.builtin.file:
path: "{{ temp_build_dir.path }}"
state: absent
- block:
- name: Remove the Podman manifest if it exists
ansible.builtin.command:
cmd: >
podman manifest rm -i localhost/{{ build_name }}:latest
- name: Create a manifest list for multi-architecture image
ansible.builtin.command:
cmd: >
podman manifest create localhost/{{ build_name }}:latest
- name: Add architecture-specific images to the manifest list
ansible.builtin.command:
cmd: >
podman manifest add localhost/{{ build_name }}:latest oci-archive:{{ playbook_dir }}/builds/{{ build_name }}-{{ architecture }}.tar
loop: '{{ architectures }}'
loop_control:
loop_var: architecture
- name: Push the multi-architecture manifest to the remote registry
ansible.builtin.command:
cmd: >
podman manifest push --quiet --rm --all --tls-verify={{ validate_certs | default('true') }} localhost/{{ build_name }}:latest {{ image_to }}
environment:
REGISTRY_AUTH_FILE: "{{ auth_file | default(omit) }}"
delegate_to: localhost
run_once: true
become: yes
vars:
# Computes the list of architectures based on the "ansible_architecture" values of the builder hosts
architectures: '{{ hostvars | dict2items | map(attribute="value") | selectattr("ansible_architecture", "defined") | map(attribute="ansible_architecture") | list }}'