#!/bin/bash # Test image splitting at build time using the FROM oci-archive: trick. set -xeuo pipefail shopt -s inherit_errexit SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=SCRIPTDIR/lib.sh . "${SCRIPT_DIR}/lib.sh" BASE_IMAGE="quay.io/fedora/fedora-minimal:latest" ROOTFS_IMAGE="localhost/test-buildtime-rootfs:latest" CHUNKED_IMAGE="localhost/fedora-minimal-chunked:test" CHUNKED_IMAGE2="localhost/fedora-minimal-chunked:test2" CHUNKED_IMAGE3="localhost/fedora-minimal-chunked:test3" cleanup() { cleanup_images "${CHUNKED_IMAGE}" "${CHUNKED_IMAGE2}" "${ROOTFS_IMAGE}" } trap cleanup EXIT podman pull "${BASE_IMAGE}" # Build rootfs as a separate image so that the reproducibility check below # operates on the same rootfs both times. Without this, each buildah_build # would re-run dnf install, producing different file timestamps. # # Also create a large random file used to test reproducibility of bigfiles # components. cat > Containerfile.rootfs < Containerfile < /run/src/out.ociarchive FROM oci-archive:out.ociarchive EOF buildah_build -t "${CHUNKED_IMAGE}" -f Containerfile . # verify jq works in the resulting image podman run --rm "${CHUNKED_IMAGE}" jq --version # check for expected components assert_has_components "${CHUNKED_IMAGE}" "rpm/filesystem" "rpm/setup" "rpm/glibc" "rpm/jq" "bigfiles/chungus" "bigfiles/chungus2" # verify we got exactly 64 layers (the default) assert_layer_count "${CHUNKED_IMAGE}" 64 # verify mtime clamping: `chungus` keeps its canonical mtime (0) since it's # below SOURCE_DATE_EPOCH, while `chungus2` (wall-clock mtime) is clamped to # SOURCE_DATE_EPOCH assert_path_mtime "${CHUNKED_IMAGE}" /usr/bin/chungus 0 assert_path_mtime "${CHUNKED_IMAGE}" /usr/bin/chungus2 1700000000 # verify that security.capability xattrs are preserved caps=$(podman run --rm "${CHUNKED_IMAGE}" getcap /usr/bin/test-xattrs) [[ "${caps}" == *"cap_net_raw=ep"* ]] # verify that POSIX ACLs (system.posix_acl_access) are preserved acl=$(podman run --rm "${CHUNKED_IMAGE}" getfacl -c /usr/bin/test-xattrs) [[ "${acl}" == *"user:nobody:r--"* ]] # verify that user.* xattrs are preserved xattr1=$(podman run --rm "${CHUNKED_IMAGE}" getfattr -n user.testkey1 --only-values /usr/bin/test-xattrs) [[ "${xattr1}" == "testvalue1" ]] xattr2=$(podman run --rm "${CHUNKED_IMAGE}" getfattr -n user.testkey2 --only-values /usr/bin/test-xattrs) [[ "${xattr2}" == "testvalue2" ]] # verify reproducibility: build again with --no-cache to force chunkah to # re-run on the same rootfs and compare image IDs; this validates that xattr # sorting and trusted.* filtering produce deterministic output buildah_build --no-cache -t "${CHUNKED_IMAGE2}" -f Containerfile . id1=$(podman inspect --format '{{.Id}}' "${CHUNKED_IMAGE}") id2=$(podman inspect --format '{{.Id}}' "${CHUNKED_IMAGE2}") if [[ "${id1}" != "${id2}" ]]; then echo "ERROR: image IDs differ between builds" echo "Build 1: ${id1}" echo "Build 2: ${id2}" # this will fail; it's just a way to call into `just diff` to print the diff assert_no_diff "${CHUNKED_IMAGE}" "${CHUNKED_IMAGE2}" exit 1 # but just in case fi # Verify that bigfiles component with reproducible modification time is # reproducible even if SOURCE_DATE_EPOCH changes sed -i -e 's/\