From 93a5fca403bcf9b466e54bada681dbebbc083568 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 20 Nov 2025 13:52:45 -0500 Subject: [PATCH] tests: Change the upgrade test to support fetching from host This ensures it all can work much more elegantly/naturally with sealed UKI builds - we don't want to do the build-on-target thing. Signed-off-by: Colin Walters --- Justfile | 37 ++++++++++++++----- crates/xtask/src/tmt.rs | 1 + tmt/tests/Dockerfile.upgrade | 3 ++ tmt/tests/booted/test-image-upgrade-reboot.nu | 28 +++++++++----- 4 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 tmt/tests/Dockerfile.upgrade diff --git a/Justfile b/Justfile index fa468a58..0c4a05b6 100644 --- a/Justfile +++ b/Justfile @@ -11,6 +11,13 @@ # -------------------------------------------------------------------- +# This image is just the base image plus our updated bootc binary +base_img := "localhost/bootc" +# Derives from the above and adds nushell, cloudinit etc. +integration_img := base_img + "-integration" +# Has a synthetic upgrade +integration_upgrade_img := integration_img + "-upgrade" + # ostree: The default # composefs-sealeduki-sdboot: A system with a sealed composefs using systemd-boot variant := env("BOOTC_variant", "ostree") @@ -33,8 +40,8 @@ buildargs := "--build-arg=base=" + base + " --build-arg=variant=" + variant # Note commonly you might want to override the base image via e.g. # `just build --build-arg=base=quay.io/fedora/fedora-bootc:42` build: - podman build {{base_buildargs}} -t localhost/bootc-bin {{buildargs}} . - ./tests/build-sealed {{variant}} localhost/bootc-bin localhost/bootc + podman build {{base_buildargs}} -t {{base_img}}-bin {{buildargs}} . + ./tests/build-sealed {{variant}} {{base_img}}-bin {{base_img}} # Build a sealed image from current sources. build-sealed: @@ -66,8 +73,8 @@ package: _packagecontainer # This container image has additional testing content and utilities build-integration-test-image: build - cd hack && podman build {{base_buildargs}} -t localhost/bootc-integration-bin -f Containerfile . - ./tests/build-sealed {{variant}} localhost/bootc-integration-bin localhost/bootc-integration + cd hack && podman build {{base_buildargs}} -t {{integration_img}}-bin -f Containerfile . + ./tests/build-sealed {{variant}} {{integration_img}}-bin {{integration_img}} # Keep these in sync with what's used in hack/lbi podman pull -q --retry 5 --retry-delay 5s quay.io/curl/curl:latest quay.io/curl/curl-base:latest registry.access.redhat.com/ubi9/podman:latest @@ -76,17 +83,17 @@ test-composefs: # These first two are currently a distinct test suite from tmt that directly # runs an integration test binary in the base image via bcvk just variant=composefs-sealeduki-sdboot build - cargo run --release -p tests-integration -- composefs-bcvk localhost/bootc + cargo run --release -p tests-integration -- composefs-bcvk {{base_img}} # We're trying to move more testing to tmt, so just variant=composefs-sealeduki-sdboot test-tmt readonly # Only used by ci.yml right now build-install-test-image: build-integration-test-image - cd hack && podman build {{base_buildargs}} -t localhost/bootc-integration-install -f Containerfile.drop-lbis + cd hack && podman build {{base_buildargs}} -t {{integration_img}}-install -f Containerfile.drop-lbis # These tests accept the container image as input, and may spawn it. run-container-external-tests: - ./tests/container/run localhost/bootc + ./tests/container/run {{base_img}} # We build the unit tests into a container image build-units: @@ -101,8 +108,18 @@ validate: # # To run an individual test, pass it as an argument like: # `just test-tmt readonly` -test-tmt *ARGS: build-integration-test-image - cargo xtask run-tmt --env=BOOTC_variant={{variant}} localhost/bootc-integration {{ARGS}} +test-tmt *ARGS: build-integration-test-image _build-upgrade-image + @just test-tmt-nobuild {{ARGS}} + +# Generate a local synthetic upgrade +_build-upgrade-image: + podman build -t {{integration_upgrade_img}}-bin --from={{integration_img}}-bin -f tmt/tests/Dockerfile.upgrade /usr/share/empty + ./tests/build-sealed {{variant}} {{integration_upgrade_img}}-bin {{integration_upgrade_img}} + +# Assume the localhost/bootc-integration image is up to date, and just run tests. +# Useful for iterating on tests quickly. +test-tmt-nobuild *ARGS: + cargo xtask run-tmt --env=BOOTC_variant={{variant}} --env=BOOTC_upgrade_image={{integration_upgrade_img}} {{integration_img}} {{ARGS}} # Cleanup all test VMs created by tmt tests tmt-vm-cleanup: @@ -112,7 +129,7 @@ tmt-vm-cleanup: test-container: build-units build-integration-test-image podman run --rm --read-only localhost/bootc-units /usr/bin/bootc-units # Pass these through for cross-checking - podman run --rm --env=BOOTC_variant={{variant}} --env=BOOTC_base={{base}} localhost/bootc-integration bootc-integration-tests container + podman run --rm --env=BOOTC_variant={{variant}} --env=BOOTC_base={{base}} {{integration_img}} bootc-integration-tests container # Remove all container images built (locally) via this Justfile, by matching a label clean-local-images: diff --git a/crates/xtask/src/tmt.rs b/crates/xtask/src/tmt.rs index ce7b3036..0d148ccd 100644 --- a/crates/xtask/src/tmt.rs +++ b/crates/xtask/src/tmt.rs @@ -18,6 +18,7 @@ const COMMON_INST_ARGS: &[&str] = &[ // TODO: Pass down the Secure Boot keys for tests if present "--firmware=uefi-insecure", "--label=bootc.test=1", + "--bind-storage-ro", ]; // Import the argument types from xtask.rs diff --git a/tmt/tests/Dockerfile.upgrade b/tmt/tests/Dockerfile.upgrade new file mode 100644 index 00000000..ab3b73c7 --- /dev/null +++ b/tmt/tests/Dockerfile.upgrade @@ -0,0 +1,3 @@ +# Just creates a file as a new layer for a synthetic upgrade test +FROM localhost/bootc-integration +RUN touch --reference=/usr/bin/bash /usr/share/testing-bootc-upgrade-apply diff --git a/tmt/tests/booted/test-image-upgrade-reboot.nu b/tmt/tests/booted/test-image-upgrade-reboot.nu index a636b630..553cae52 100644 --- a/tmt/tests/booted/test-image-upgrade-reboot.nu +++ b/tmt/tests/booted/test-image-upgrade-reboot.nu @@ -15,6 +15,8 @@ use tap.nu # This code runs on *each* boot. # Here we just capture information. bootc status +journalctl --list-boots + let st = bootc status --json | from json let booted = $st.status.booted.image @@ -25,30 +27,38 @@ def parse_cmdline [] { open /proc/cmdline | str trim | split row " " } +def imgsrc [] { + $env.BOOTC_upgrade_image? | default "localhost/bootc-derived-local" +} + # Run on the first boot def initial_build [] { tap begin "local image push + pull + upgrade" - bootc image copy-to-storage + let imgsrc = imgsrc + # For the packit case, we build locally right now + if ($imgsrc | str ends-with "-local") { + bootc image copy-to-storage - # A simple derived container that adds a file - "FROM localhost/bootc + # A simple derived container that adds a file + "FROM localhost/bootc RUN touch /usr/share/testing-bootc-upgrade-apply " | save Dockerfile - # Build it - podman build -t localhost/bootc-derived . + # Build it + podman build -t $imgsrc . + } # Now, switch into the new image - tmt-reboot -c "bootc switch --apply --transport containers-storage localhost/bootc-derived" - - # We cannot perform any other checks here since the system will be automatically rebooted + print $"Applying ($imgsrc)" + bootc switch --transport containers-storage ($imgsrc) + tmt-reboot } # Check we have the updated image def second_boot [] { print "verifying second boot" assert equal $booted.image.transport containers-storage - assert equal $booted.image.image localhost/bootc-derived + assert equal $booted.image.image $"(imgsrc)" # Verify the new file exists "/usr/share/testing-bootc-upgrade-apply" | path exists