Skip to content

Commit f3762cf

Browse files
committed
wip: refactor build+test to support test composefs with tmt
Signed-off-by: Colin Walters <[email protected]>
1 parent 260c376 commit f3762cf

File tree

15 files changed

+208
-96
lines changed

15 files changed

+208
-96
lines changed

.github/actions/bootc-ubuntu-setup/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ runs:
7777
shell: bash
7878
run: |
7979
set -xeuo pipefail
80-
export BCVK_VERSION=0.5.3
80+
export BCVK_VERSION=0.6.0
8181
/bin/time -f '%E %C' sudo apt install -y libkrb5-dev pkg-config libvirt-dev genisoimage qemu-utils qemu-kvm virtiofsd libvirt-daemon-system
8282
# Something in the stack is overriding this, but we want session right now for bcvk
8383
echo LIBVIRT_DEFAULT_URI=qemu:///session >> $GITHUB_ENV

.github/workflows/ci.yml

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -144,23 +144,8 @@ jobs:
144144
- name: Build container and disk image
145145
run: |
146146
set -xeuo pipefail
147-
build_args=()
148-
# Map from an ID-VERSIONID pair to a container ref
149-
target=${{ matrix.test_os }}
150-
OS_ID=$(echo "$target" | cut -d '-' -f 1)
151-
OS_VERSION_ID=$(echo "$target" | cut -d '-' -f 2)
152-
# Base image
153-
case "$OS_ID" in
154-
"centos")
155-
BASE="quay.io/centos-bootc/centos-bootc:stream${OS_VERSION_ID}"
156-
;;
157-
"fedora")
158-
BASE="quay.io/fedora/fedora-bootc:${OS_VERSION_ID}"
159-
;;
160-
*) echo "Unknown OS: ${OS_ID}" 1>&2; exit 1
161-
;;
162-
esac
163-
build_args+=("--build-arg=base=$BASE")
147+
target=$(just pullspec-for-os ${{ matrix.test_os }})
148+
build_args=("--build-arg=base=$BASE")
164149
just build ${build_args[@]}
165150
just build-integration-test-image
166151
# Cross check we're using the right base
@@ -194,7 +179,10 @@ jobs:
194179
strategy:
195180
fail-fast: false
196181
matrix:
182+
# TODO expand this matrix, we need to make it better to override the target
183+
# OS via Justfile variables too
197184
test_os: [centos-10]
185+
variant: [composefs-sealeduki-sdboot]
198186

199187
runs-on: ubuntu-24.04
200188

@@ -204,9 +192,11 @@ jobs:
204192
uses: ./.github/actions/bootc-ubuntu-setup
205193
with:
206194
libvirt: true
195+
- name: Install tmt
196+
run: pip install --user "tmt[provision-virtual]"
207197

208198
- name: Build container
209-
run: just build-sealed
199+
run: just variant=composefs-sealeduki-sdboot build-integration-test-image
210200

211-
- name: Test
212-
run: just test-composefs
201+
- name: Test (readonly)
202+
run: just variant=composefs-sealeduki-sdboot test-tmt readonly

Dockerfile

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,31 @@ RUN --mount=type=cache,target=/src/target --mount=type=cache,target=/var/roothom
9494

9595
# The final image that derives from the original base and adds the release binaries
9696
FROM base
97-
# Set this to 1 to default to systemd-boot
98-
ARG sdboot=0
97+
# See the Justfile for more on this
98+
ARG variant
9999
RUN <<EORUN
100100
set -xeuo pipefail
101101
# Ensure we've flushed out prior state (i.e. files no longer shipped from the old version);
102102
# and yes, we may need to go to building an RPM in this Dockerfile by default.
103103
rm -vf /usr/lib/systemd/system/multi-user.target.wants/bootc-*
104-
if test "$sdboot" = 1; then
105-
dnf -y install systemd-boot-unsigned
106-
# And uninstall bootupd
107-
rpm -e bootupd
108-
rm /usr/lib/bootupd/updates -rf
109-
dnf clean all
110-
rm -rf /var/cache /var/lib/{dnf,rhsm} /var/log/*
111-
fi
104+
case "${variant}" in
105+
*-sdboot)
106+
dnf -y install systemd-boot-unsigned
107+
# And uninstall bootupd
108+
rpm -e bootupd
109+
rm /usr/lib/bootupd/updates -rf
110+
dnf clean all
111+
rm -rf /var/cache /var/lib/{dnf,rhsm} /var/log/*
112+
;;
113+
esac
114+
case "${variant}" in
115+
composefs*)
116+
cat > /usr/lib/bootc/install/80-ext4-composefs.toml <<EOF
117+
[install.filesystem.root]
118+
type = "ext4"
119+
EOF
120+
;;
121+
esac
112122
EORUN
113123
# Create a layer that is our new binaries
114124
COPY --from=build /out/ /

Justfile

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,27 @@
1111

1212
# --------------------------------------------------------------------
1313

14+
# ostree: The default
15+
# composefs-sealeduki-sdboot: A system with a sealed composefs using systemd-boot
16+
variant := "ostree"
17+
1418
# Build the container image from current sources.
1519
# Note commonly you might want to override the base image via e.g.
1620
# `just build --build-arg=base=quay.io/fedora/fedora-bootc:42`
1721
build *ARGS:
18-
podman build --jobs=4 -t localhost/bootc {{ARGS}} .
19-
20-
# Build a sealed image from current sources. This will default to
21-
# generating Secure Boot keys in target/test-secureboot.
22-
build-sealed *ARGS:
23-
podman build --build-arg=sdboot=1 --jobs=4 -t localhost/bootc-unsealed {{ARGS}} .
24-
./tests/build-sealed localhost/bootc-unsealed localhost/bootc
22+
podman build --jobs=4 -t localhost/bootc-bin --build-arg=variant={{variant}} {{ARGS}} .
23+
./tests/build-sealed {{variant}} localhost/bootc-bin localhost/bootc
2524

2625
# This container image has additional testing content and utilities
27-
build-integration-test-image *ARGS:
28-
cd hack && podman build --jobs=4 -t localhost/bootc-integration -f Containerfile {{ARGS}} .
26+
build-integration-test-image *ARGS: build
27+
cd hack && podman build --jobs=4 -t localhost/bootc-integration-bin -f Containerfile {{ARGS}} .
28+
./tests/build-sealed {{variant}} localhost/bootc-integration-bin localhost/bootc-integration
2929
# Keep these in sync with what's used in hack/lbi
3030
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
3131

32-
test-composefs: build-sealed
32+
# Build+test composefs; compat alias
33+
test-composefs:
34+
just build --variant=composefs-sealeduki-sdboot
3335
cargo run --release -p tests-integration -- composefs-bcvk localhost/bootc
3436

3537
# Only used by ci.yml right now
@@ -80,6 +82,23 @@ test-container: build-units build-integration-test-image
8082
podman run --rm --read-only localhost/bootc-units /usr/bin/bootc-units
8183
podman run --rm localhost/bootc-integration bootc-integration-tests container
8284

85+
# Print the container image reference for a given short $ID-VERSION_ID
86+
pullspec-for-os NAME:
87+
#!/bin/bash
88+
OS_ID=$(echo "{{NAME}}" | cut -d '-' -f 1)
89+
OS_VERSION_ID=$(echo "{{NAME}}" | cut -d '-' -f 2)
90+
# Base image
91+
case "$OS_ID" in
92+
"centos")
93+
echo "quay.io/centos-bootc/centos-bootc:stream${OS_VERSION_ID}"
94+
;;
95+
"fedora")
96+
echo "quay.io/fedora/fedora-bootc:${OS_VERSION_ID}"
97+
;;
98+
*) echo "Unknown OS: ${OS_ID}" 1>&2; exit 1
99+
;;
100+
esac
101+
83102
build-mdbook:
84103
cd docs && podman build -t localhost/bootc-mdbook -f Dockerfile.mdbook
85104

crates/xtask/src/xtask.rs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,15 @@ fn check_dependencies(sh: &Shell) -> Result<()> {
468468
Ok(())
469469
}
470470

471+
const COMMON_INST_ARGS: &[&str] = &[
472+
// We don't use cloud-init with bcvk right now, but it needs to be there for
473+
// testing-farm+tmt
474+
"--karg=ds=iid-datasource-none",
475+
// TODO: Pass down the Secure Boot keys for tests if present
476+
"--firmware=uefi-insecure",
477+
"--label=bootc.test=1"
478+
];
479+
471480
/// Run TMT tests using bcvk for VM management
472481
/// This spawns a separate VM per test plan to avoid state leakage between tests.
473482
///
@@ -561,10 +570,13 @@ fn run_tmt(sh: &Shell, args: &[String]) -> Result<()> {
561570
println!("========================================\n");
562571

563572
// Launch VM with bcvk
564-
// Use ds=iid-datasource-none to disable cloud-init for faster boot
565-
let launch_result = cmd!(sh, "bcvk libvirt run --name {vm_name} --detach --filesystem ext4 --karg=ds=iid-datasource-none {image}")
566-
.run()
567-
.context("Launching VM with bcvk");
573+
574+
let launch_result = cmd!(
575+
sh,
576+
"bcvk libvirt run --name {vm_name} --detach {COMMON_INST_ARGS...} {image}"
577+
)
578+
.run()
579+
.context("Launching VM with bcvk");
568580

569581
if let Err(e) = launch_result {
570582
eprintln!("Failed to launch VM for plan {}: {:#}", plan, e);
@@ -743,9 +755,12 @@ fn tmt_provision(sh: &Shell, args: &[String]) -> Result<()> {
743755

744756
// Launch VM with bcvk
745757
// Use ds=iid-datasource-none to disable cloud-init for faster boot
746-
cmd!(sh, "bcvk libvirt run --name {vm_name} --detach --filesystem ext4 --karg=ds=iid-datasource-none {image}")
747-
.run()
748-
.context("Launching VM with bcvk")?;
758+
cmd!(
759+
sh,
760+
"bcvk libvirt run --name {vm_name} --detach {COMMON_INST_ARGS...} {image}"
761+
)
762+
.run()
763+
.context("Launching VM with bcvk")?;
749764

750765
println!("VM launched, waiting for SSH...");
751766

@@ -758,8 +773,7 @@ fn tmt_provision(sh: &Shell, args: &[String]) -> Result<()> {
758773
.context("Creating target directory")?;
759774
let key_path = key_dir.join(format!("{}.ssh-key", vm_name));
760775

761-
std::fs::write(&key_path, ssh_key)
762-
.context("Writing SSH key file")?;
776+
std::fs::write(&key_path, ssh_key).context("Writing SSH key file")?;
763777

764778
// Set proper permissions on key file (0600)
765779
#[cfg(unix)]
@@ -786,7 +800,10 @@ fn tmt_provision(sh: &Shell, args: &[String]) -> Result<()> {
786800
println!(" --user root --key {} \\", key_path);
787801
println!(" plan --name <PLAN_NAME>");
788802
println!("\nTo connect via SSH:");
789-
println!(" ssh -i {} -p {} -o IdentitiesOnly=yes root@localhost", key_path, ssh_port);
803+
println!(
804+
" ssh -i {} -p {} -o IdentitiesOnly=yes root@localhost",
805+
key_path, ssh_port
806+
);
790807
println!("\nTo cleanup:");
791808
println!(" bcvk libvirt rm --stop --force {}", vm_name);
792809
println!("========================================\n");

hack/provision-derived.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ dnf clean all
4545
cat <<KARGEOF >> /usr/lib/bootc/kargs.d/20-console.toml
4646
kargs = ["console=ttyS0,115200n8"]
4747
KARGEOF
48-
# And cloud-init stuff
49-
ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants
48+
# And cloud-init stuff, unless we're doing a UKI which is always
49+
# tested with bcvk
50+
if test '!' -d /boot/EFI; then
51+
ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants
52+
fi
5053

5154
# Allow root SSH login for testing with bcvk/tmt
5255
mkdir -p /etc/cloud/cloud.cfg.d

tests/build-sealed

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
set -euo pipefail
33
# This should turn into https://github.com/bootc-dev/bootc/issues/1498
44

5+
variant=$1
6+
shift
57
# The un-sealed container image we want to use
68
input_image=$1
79
shift
@@ -17,6 +19,19 @@ runv() {
1719
"$@"
1820
}
1921

22+
case $variant in
23+
ostree)
24+
# Nothing to do
25+
podman tag $input_image $output_image
26+
;;
27+
composefs-sealeduki*)
28+
;;
29+
*)
30+
echo "Unknown variant=$variant" 1>&2; exit 1
31+
;;
32+
esac
33+
34+
2035
graphroot=$(podman system info -f '{{.Store.GraphRoot}}')
2136
echo "Computing composefs digest..."
2237
cfs_digest=$(podman run --rm --privileged --read-only --security-opt=label=disable -v /sys:/sys:ro --net=none \

tmt/tests/booted/readonly/001-test-status.nu

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,23 @@ assert equal $st.apiVersion org.containers.bootc/v1
1111

1212
let st = bootc status --format=yaml | from yaml
1313
assert equal $st.apiVersion org.containers.bootc/v1
14-
assert ($st.status.booted.image.timestamp != null)
14+
# Detect composefs by checking if composefs field is present
15+
let is_composefs = ($st.status.booted.composefs? != null)
16+
if not $is_composefs {
17+
assert ($st.status.booted.image.timestamp != null)
18+
} # else { TODO composefs: timestamp is not populated with composefs }
1519
let ostree = $st.status.booted.ostree
1620
if $ostree != null {
1721
assert ($ostree.stateroot != null)
1822
}
1923

2024
let st = bootc status --json --booted | from json
2125
assert equal $st.apiVersion org.containers.bootc/v1
22-
assert ($st.status.booted.image.timestamp != null)
26+
# Detect composefs by checking if composefs field is present
27+
let is_composefs = ($st.status.booted.composefs? != null)
28+
if not $is_composefs {
29+
assert ($st.status.booted.image.timestamp != null)
30+
} # else { TODO composefs: timestamp is not populated with composefs }
2331
assert (($st.status | get rollback | default null) == null)
2432
assert (($st.status | get staged | default null) == null)
2533

tmt/tests/booted/readonly/010-test-bootc-container-store.nu

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@ use tap.nu
33

44
tap begin "verify bootc-owned container storage"
55

6-
# Just verifying that the additional store works
7-
podman --storage-opt=additionalimagestore=/usr/lib/bootc/storage images
6+
# Detect composefs by checking if composefs field is present
7+
let st = bootc status --json | from json
8+
let is_composefs = ($st.status.booted.composefs? != null)
89

9-
# And verify this works
10-
bootc image cmd list -q o>/dev/null
10+
if $is_composefs {
11+
print "# TODO composefs: skipping test - /usr/lib/bootc/storage doesn't exist with composefs"
12+
} else {
13+
# Just verifying that the additional store works
14+
podman --storage-opt=additionalimagestore=/usr/lib/bootc/storage images
15+
16+
# And verify this works
17+
bootc image cmd list -q o>/dev/null
18+
}
1119

1220
tap ok

tmt/tests/booted/readonly/011-test-ostree-ext-cli.nu

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@ tap begin "verify bootc wrapping ostree-ext"
77

88
# Parse the status and get the booted image
99
let st = bootc status --json | from json
10-
let booted = $st.status.booted.image
11-
# Then verify we can extract its metadata via the ostree-container code.
12-
let metadata = bootc internals ostree-container image metadata --repo=/ostree/repo $"($booted.image.transport):($booted.image.image)" | from json
13-
assert equal $metadata.mediaType "application/vnd.oci.image.manifest.v1+json"
10+
# Detect composefs by checking if composefs field is present
11+
let is_composefs = ($st.status.booted.composefs? != null)
12+
if $is_composefs {
13+
print "# TODO composefs: skipping test - ostree-container commands don't work with composefs"
14+
} else {
15+
let booted = $st.status.booted.image
16+
# Then verify we can extract its metadata via the ostree-container code.
17+
let metadata = bootc internals ostree-container image metadata --repo=/ostree/repo $"($booted.image.transport):($booted.image.image)" | from json
18+
assert equal $metadata.mediaType "application/vnd.oci.image.manifest.v1+json"
19+
}
20+
21+
tap ok

0 commit comments

Comments
 (0)