--- - name: Build kubevirt images vars: kubevirt_images_to_build: "{{ images | dict2items if kubevirt_images_selected | length == 0 else ([images] | community.general.keep_keys(target=kubevirt_images_selected))[0] | dict2items }}" block: - name: Validate selected image names assert: that: - kubevirt_images_selected | length == 0 or kubevirt_images_to_build | length > 0 fail_msg: "No matching images found in `images` for `kubevirt_images_selected={{ kubevirt_images_selected }}`" - name: Validate requested container builder assert: that: - kubevirt_container_builder in ['docker', 'buildkit'] fail_msg: "Unsupported kubevirt_container_builder={{ kubevirt_container_builder }}" - name: Validate BuildKit push mode assert: that: - not (kubevirt_container_builder == 'buildkit' and kubevirt_images_push) fail_msg: "BuildKit validation currently requires kubevirt_images_push=false" - name: Check qemu-img availability command: qemu-img --version changed_when: false - name: Check Docker availability command: docker --version changed_when: false when: kubevirt_container_builder == 'docker' - name: Detect BuildKit daemonless wrapper availability shell: command -v buildctl-daemonless.sh args: executable: /bin/bash register: kubevirt_buildctl_daemonless_available changed_when: false failed_when: false when: kubevirt_container_builder == 'buildkit' - name: Check BuildKit availability shell: | set -euo pipefail if [ "{{ kubevirt_buildctl_daemonless_available.rc | default(1) }}" -eq 0 ]; then buildctl-daemonless.sh --version else buildctl --version buildkitd --version fi args: executable: /bin/bash changed_when: false when: kubevirt_container_builder == 'buildkit' - name: Create image directory file: state: directory path: "{{ images_dir }}" mode: "0755" - name: Create buildkit output directory file: state: directory path: "{{ kubevirt_buildkit_output_dir }}" mode: "0755" when: kubevirt_container_builder == 'buildkit' - name: Download images files get_url: url: "{{ item.value.url }}" dest: "{{ images_dir }}/{{ item.value.filename }}" checksum: "{{ item.value.checksum }}" mode: "0644" loop: "{{ kubevirt_images_to_build }}" - name: Unxz compressed images command: unxz --force {{ images_dir }}/{{ item.value.filename }} loop: "{{ kubevirt_images_to_build }}" when: - item.value.filename.endswith('.xz') - name: Convert images which is not in qcow2 format command: qemu-img convert -O qcow2 {{ images_dir }}/{{ item.value.filename.rstrip('.xz') }} {{ images_dir }}/{{ item.key }}.qcow2 loop: "{{ kubevirt_images_to_build }}" when: - not (item.value.converted | bool) - name: Make sure all images are ending with qcow2 command: cp {{ images_dir }}/{{ item.value.filename.rstrip('.xz') }} {{ images_dir }}/{{ item.key }}.qcow2 loop: "{{ kubevirt_images_to_build }}" when: - item.value.converted | bool - name: Resize images command: qemu-img resize {{ images_dir }}/{{ item.key }}.qcow2 +8G loop: "{{ kubevirt_images_to_build }}" # STEP 2: Include the images inside a container - name: Template default Dockerfile template: src: Dockerfile dest: "{{ images_dir }}/Dockerfile" mode: "0644" - name: Create docker images for each OS command: docker build -t {{ registry }}/vm-{{ item.key }}:{{ item.value.tag }} --build-arg cloud_image="{{ item.key }}.qcow2" {{ images_dir }} loop: "{{ kubevirt_images_to_build }}" when: kubevirt_container_builder == 'docker' - name: Create container images for each OS with BuildKit shell: | set -euo pipefail IMAGE_REF="{{ registry }}/vm-{{ item.key }}:{{ item.value.tag }}" OUTPUT_TAR="{{ kubevirt_buildkit_output_dir }}/vm-{{ item.key }}-{{ item.value.tag }}.tar" # Rootless BuildKit is the CI path; root mode must not use rootless-only flags. if [ "$(id -u)" -eq 0 ]; then BUILDKITD_FLAGS="${BUILDKITD_FLAGS:-}" else BUILDKITD_FLAGS="${BUILDKITD_FLAGS:---rootless --oci-worker-no-process-sandbox --oci-worker-snapshotter=native}" fi run_buildkit() { if [ "{{ kubevirt_buildctl_daemonless_available.rc | default(1) }}" -eq 0 ]; then export BUILDKITD_FLAGS buildctl-daemonless.sh build \ --frontend dockerfile.v0 \ --local context={{ images_dir }} \ --local dockerfile={{ images_dir }} \ --opt filename=Dockerfile \ --opt build-arg:cloud_image={{ item.key }}.qcow2 \ --output "{{ 'type=image,name=' ~ registry ~ '/vm-' ~ item.key ~ ':' ~ item.value.tag ~ ',push=true' if kubevirt_images_push else 'type=oci,dest=' ~ kubevirt_buildkit_output_dir ~ '/vm-' ~ item.key ~ '-' ~ item.value.tag ~ '.tar' }}" else BUILDKIT_ADDR="unix:///tmp/buildkitd-{{ item.key }}.sock" buildkitd ${BUILDKITD_FLAGS} --addr "${BUILDKIT_ADDR}" >/tmp/buildkitd-{{ item.key }}.log 2>&1 & buildkitd_pid=$! cleanup() { kill "${buildkitd_pid}" >/dev/null 2>&1 || true wait "${buildkitd_pid}" >/dev/null 2>&1 || true } trap cleanup EXIT for _ in $(seq 1 50); do if buildctl --addr "${BUILDKIT_ADDR}" debug workers >/dev/null 2>&1; then break fi sleep 0.2 done buildctl --addr "${BUILDKIT_ADDR}" build \ --frontend dockerfile.v0 \ --local context={{ images_dir }} \ --local dockerfile={{ images_dir }} \ --opt filename=Dockerfile \ --opt build-arg:cloud_image={{ item.key }}.qcow2 \ --output "{{ 'type=image,name=' ~ registry ~ '/vm-' ~ item.key ~ ':' ~ item.value.tag ~ ',push=true' if kubevirt_images_push else 'type=oci,dest=' ~ kubevirt_buildkit_output_dir ~ '/vm-' ~ item.key ~ '-' ~ item.value.tag ~ '.tar' }}" fi } if run_buildkit; then exit 0 fi echo "BuildKit failed in this environment; attempting Docker fallback for {{ item.key }}" >&2 if ! command -v docker >/dev/null 2>&1; then echo "Docker fallback unavailable: docker command not found" >&2 exit 1 fi docker build -t "${IMAGE_REF}" --build-arg cloud_image="{{ item.key }}.qcow2" {{ images_dir }} {% if kubevirt_images_push %} docker push "${IMAGE_REF}" {% else %} docker save -o "${OUTPUT_TAR}" "${IMAGE_REF}" {% endif %} args: executable: /bin/bash loop: "{{ kubevirt_images_to_build }}" when: kubevirt_container_builder == 'buildkit' - name: Docker login command: docker login -u="{{ docker_user }}" -p="{{ docker_password }}" "{{ docker_host }}" when: - kubevirt_container_builder == 'docker' - kubevirt_images_push - name: Docker push image command: docker push {{ registry }}/vm-{{ item.key }}:{{ item.value.tag }} loop: "{{ kubevirt_images_to_build }}" when: - kubevirt_container_builder == 'docker' - kubevirt_images_push - name: Docker logout command: docker logout "{{ docker_host }}" when: - kubevirt_container_builder == 'docker' - kubevirt_images_push