Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions docs/src/experimental-composefs.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,6 @@ The composefs backend is experimental; on-disk formats are subject to change.
- How container signature enforcement carries over from installation into the
installed system is not settled yet.
- Extended install APIs: Ability to cleanly implement anaconda %post and osbuild post mutations and general post-install pre-reboot; right now some tools just mount the deployment directory (note this one also relates to [APIs in general](https://github.com/bootc-dev/bootc/issues/522))
- [zstd:chunked pull failures](https://github.com/bootc-dev/bootc/issues/2408):
images pushed with `--compression-format zstd:chunked` currently fail to
pull on the composefs backend ("unexpected EOF reading tar entry"). Until a
composefs-rs decode fix is incorporated, publish with plain zstd or gzip.

## Related issues

Expand Down
7 changes: 7 additions & 0 deletions tmt/plans/integration.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -331,4 +331,11 @@ execute:
enabled: true
extra-try_bind_storage: true
extra-skip_if_ostree: true

/plan-50-switch-zstd-chunked:
summary: Switch to an image with zstd:chunked compressed layers
discover:
how: fmf
test:
- /tmt/tests/tests/test-50-switch-zstd-chunked
# END GENERATED PLANS
89 changes: 89 additions & 0 deletions tmt/tests/booted/test-switch-zstd-chunked.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# number: 50
# tmt:
# summary: Switch to an image with zstd:chunked compressed layers
# duration: 30m
#
# zstd:chunked layers are multi-frame zstd streams with skippable frames
# holding a table of contents, which a naive zstd decoder truncates; see
# https://github.com/bootc-dev/bootc/issues/2408
#
# This test does:
# podman build <derived from the booted image>
# podman push --compression-format zstd:chunked <to an OCI directory>
# bootc switch <to that OCI directory>
# Verify we boot into the new image
#
# An OCI directory is used rather than a registry to avoid a network
# dependency. The layers still go through the same decompression code
# as a registry pull on both backends.
use std assert
use tap.nu

const image_dir = "/var/tmp/bootc-zstd-chunked"
const data_dir = "/usr/share/testing-bootc-zstd-chunked"
const zstd_media_type = "application/vnd.oci.image.layer.v1.tar+zstd"
# Annotation that c/image adds to each zstd:chunked layer
const chunked_annotation = "io.github.containers.zstd-chunked.manifest-checksum"

# This code runs on *each* boot.
bootc status
let st = bootc status --json | from json
let booted = $st.status.booted.image

def initial_build [] {
tap begin "switch to zstd:chunked image"

let td = mktemp -d
cd $td

bootc image copy-to-storage
# Layers we already have (i.e. all the base image ones) are skipped when
# pulling, so only the layer added here is actually decompressed. Put a
# number of files in it: zstd:chunked compresses each into its own
# frame(s), so this layer is multi-frame too. The checksums verify
# nothing got silently truncated.
let gen_data = 'for i in $(seq 64); do head -c 65536 /dev/urandom > data$i; done && sha256sum data* > SHA256SUMS'
(
tap make_uki_containerfile $"
FROM localhost/bootc as base
RUN mkdir -p ($data_dir) && cd ($data_dir) && ($gen_data)
") | save Dockerfile
podman build -t localhost/bootc-zstd-chunked .

rm -rf $image_dir
podman push --compression-format zstd:chunked --force-compression localhost/bootc-zstd-chunked $"oci:($image_dir)"
# Free up space; we only need the OCI directory from here on
podman rmi localhost/bootc-zstd-chunked localhost/bootc

# Make sure we're actually testing what we think we are
let manifest = skopeo inspect --raw $"oci:($image_dir)" | from json
assert (($manifest.layers | length) > 0)
for layer in $manifest.layers {
assert equal $layer.mediaType $zstd_media_type
assert ($chunked_annotation in ($layer.annotations? | default {} | columns)) $"layer ($layer.digest) is not zstd:chunked"
}

bootc switch --transport oci $image_dir
let st = bootc status --json | from json
assert equal $st.status.staged.image.image.transport oci
tmt-reboot
}

def second_boot [] {
print "verifying second boot"
assert equal $booted.image.transport oci
assert equal $booted.image.image $image_dir
cd $data_dir
sha256sum --check --quiet SHA256SUMS
bootc internals fsck
tap ok
}

def main [] {
# See https://tmt.readthedocs.io/en/stable/stories/features.html#reboot-during-test
match $env.TMT_REBOOT_COUNT? {
null | "0" => initial_build,
"1" => second_boot,
$o => { error make { msg: $"Invalid TMT_REBOOT_COUNT ($o)" } },
}
}
5 changes: 5 additions & 0 deletions tmt/tests/tests.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,8 @@ check:
- when: composefs_bridge == true
enabled: true
test: nu booted/test-49-composefs-1-16-bridge.nu

/test-50-switch-zstd-chunked:
summary: Switch to an image with zstd:chunked compressed layers
duration: 30m
test: nu booted/test-switch-zstd-chunked.nu
Loading