Skip to content

Commit 87aa093

Browse files
committed
to-disk: Add --bootc-install-podman-arg for extra inner podman args
Adds a repeatable --bootc-install-podman-arg flag that passes additional arguments to the inner `podman run` that executes `bootc install to-disk`. I wanted to test out passing `--read-only` in particular (which we can't make the default just yet...) Assisted-by: OpenCode (claude-sonnet-4-6) Signed-off-by: Colin Walters <walters@verbum.org>
1 parent b32b57d commit 87aa093

3 files changed

Lines changed: 75 additions & 0 deletions

File tree

crates/integration-tests/src/tests/to_disk.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,30 @@ fn test_to_disk_different_imgref_same_digest() -> TestResult {
232232
}
233233
integration_test!(test_to_disk_different_imgref_same_digest);
234234

235+
/// Test that --bootc-install-podman-arg passes an innocuous extra arg to the inner podman run
236+
fn test_to_disk_bootc_install_podman_arg() -> TestResult {
237+
let sh = shell()?;
238+
let bck = get_bck_command()?;
239+
let label = INTEGRATION_TEST_LABEL;
240+
let image = get_test_image();
241+
242+
let temp_dir = TempDir::new().expect("Failed to create temp directory");
243+
let disk_path = Utf8PathBuf::try_from(temp_dir.path().join("test-disk.img"))
244+
.expect("temp path is not UTF-8");
245+
246+
// Pass an innocuous podman label arg - this exercises the new flag without
247+
// affecting the installation outcome.
248+
let output = cmd!(
249+
sh,
250+
"{bck} to-disk --label {label} --bootc-install-podman-arg=--label=bcvk-test=1 {image} {disk_path}"
251+
)
252+
.output()?;
253+
254+
validate_disk_image(&disk_path, &output, "test_to_disk_bootc_install_podman_arg")?;
255+
Ok(())
256+
}
257+
integration_test!(test_to_disk_bootc_install_podman_arg);
258+
235259
/// Test to-disk with various bootc images to ensure compatibility
236260
///
237261
/// This parameterized test runs to-disk with multiple container images,

crates/kit/src/to_disk.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,15 @@ pub struct ToDiskAdditionalOpts {
142142
/// Check if the disk would be regenerated without actually creating it
143143
#[clap(long)]
144144
pub dry_run: bool,
145+
146+
/// Pass an extra argument to the inner `podman run` that executes `bootc
147+
/// install`. May be specified multiple times. Useful for testing edge
148+
/// cases; for example `--bootc-install-podman-arg=--read-only` stresses
149+
/// the install path by making the container rootfs read-only, which
150+
/// exercises bootloader code paths that avoid writing to the host's
151+
/// read-only /boot (similar to osbuild sandbox environments).
152+
#[clap(long = "bootc-install-podman-arg")]
153+
pub bootc_install_podman_args: Vec<String>,
145154
}
146155

147156
/// Configuration options for installing a bootc container image to disk
@@ -222,6 +231,19 @@ impl ToDiskOpts {
222231
.map(|v| format!("--env=RUST_LOG={v}"))
223232
.unwrap_or_default();
224233

234+
// Build extra podman args as a shell-safe string
235+
let extra_podman_args = self
236+
.additional
237+
.bootc_install_podman_args
238+
.iter()
239+
.map(|a| {
240+
shlex::try_quote(a)
241+
.map(|q| q.to_string())
242+
.map_err(|e| eyre!("Failed to quote podman arg '{}': {}", a, e))
243+
})
244+
.collect::<Result<Vec<_>>>()?
245+
.join(" ");
246+
225247
// Size /var/tmp tmpfs to match swap size (disk_size)
226248
// This avoids duplicating size calculation logic
227249
let tmpfs_size_str = format!("size={}k", disk_size / 1024);
@@ -271,6 +293,7 @@ impl ToDiskOpts {
271293
--security-opt label=type:unconfined_t \
272294
--env=STORAGE_OPTS \
273295
{INSTALL_LOG} \
296+
{EXTRA_PODMAN_ARGS} \
274297
{SOURCE_IMGREF} \
275298
bootc install to-disk \
276299
--generic-image \
@@ -309,6 +332,7 @@ EOF
309332
--security-opt label=type:unconfined_t \
310333
--env=STORAGE_OPTS \
311334
{INSTALL_LOG} \
335+
{EXTRA_PODMAN_ARGS} \
312336
containers-storage:{SOURCE_IMAGE} \
313337
bootc install to-disk \
314338
--generic-image \
@@ -330,6 +354,7 @@ EOF
330354
.replace("{SOURCE_IMGREF}", &quoted_source_imgref)
331355
.replace("{SOURCE_IMAGE}", &quoted_source_image)
332356
.replace("{INSTALL_LOG}", &install_log)
357+
.replace("{EXTRA_PODMAN_ARGS}", &extra_podman_args)
333358
.replace("{BOOTC_ARGS}", &bootc_args);
334359

335360
Ok(vec!["/bin/bash".to_string(), "-c".to_string(), script])
@@ -684,4 +709,26 @@ mod tests {
684709

685710
Ok(())
686711
}
712+
713+
/// Clap parses `--flag=--value` by treating everything after `=` as the raw
714+
/// value, so `--bootc-install-podman-arg=--read-only` works without needing
715+
/// `allow_hyphen_values = true`. This test documents and locks that behaviour.
716+
#[test]
717+
fn test_podman_arg_equals_form_accepts_hyphen_values() {
718+
use clap::Parser;
719+
720+
let opts = ToDiskOpts::try_parse_from([
721+
"bcvk",
722+
"test:latest",
723+
"/tmp/test.img",
724+
"--bootc-install-podman-arg=--read-only",
725+
"--bootc-install-podman-arg=--env=FOO=bar",
726+
])
727+
.expect("--flag=--value form must parse without allow_hyphen_values");
728+
729+
assert_eq!(
730+
opts.additional.bootc_install_podman_args,
731+
["--read-only", "--env=FOO=bar"]
732+
);
733+
}
687734
}

docs/src/man/bcvk-to-disk.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ The installation process:
127127

128128
Check if the disk would be regenerated without actually creating it
129129

130+
**--bootc-install-podman-arg**=*BOOTC_INSTALL_PODMAN_ARGS*
131+
132+
Pass an extra argument to the inner `podman run` that executes `bootc install`. May be specified multiple times. Useful for testing edge cases; for example `--bootc-install-podman-arg=--read-only` stresses the install path by making the container rootfs read-only, which exercises bootloader code paths that avoid writing to the host's read-only /boot (similar to osbuild sandbox environments)
133+
130134
<!-- END GENERATED OPTIONS -->
131135

132136
# ARGUMENTS

0 commit comments

Comments
 (0)