From 57397fe86db7f15553f573baf39e1acfcd2bdc97 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 15 Dec 2023 15:06:22 -0500 Subject: [PATCH 1/2] install: Propagate skopeo stderr We're going to need to consistently use a helper to get this right in the future...basically most uses of `.output()` are wrong. Signed-off-by: Colin Walters --- lib/src/install.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/install.rs b/lib/src/install.rs index f43a99043..20ff786c6 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -694,6 +694,7 @@ fn skopeo_supports_containers_storage() -> Result { let o = run_in_host_mountns("skopeo").arg("--version").output()?; let st = o.status; if !st.success() { + let _ = std::io::copy(&mut std::io::Cursor::new(o.stderr), &mut std::io::stderr()); // Ignore errors copying stderr anyhow::bail!("Failed to run skopeo --version: {st:?}"); } let stdout = String::from_utf8(o.stdout).context("Parsing skopeo version")?; From d82446a6f9dfbf18b3962b64ee3e2db4a3a3bb6d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 15 Dec 2023 15:07:02 -0500 Subject: [PATCH 2/2] install: Fix exec helper to not swallow unexpected args Our `exec-in-host-mount-namespace` internal helper was intended to be a "passthrough" that accepts whatever child arguments. However I misunderstood how to do this in clap. Before this change we get: ``` $ bootc blabla ERROR Re-exec in host mountns: Missing command ``` i.e. the exec code kicks in because `external_subcommand` takes over *everything* unknown. Fix things to use `trailing_var_arg` which is intended for this case. After this patch: ``` $ bootc blabla error: unrecognized subcommand 'blabla' Usage: bootc For more information, try '--help'. ``` Signed-off-by: Colin Walters --- lib/src/cli.rs | 9 +++++---- lib/src/install.rs | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/src/cli.rs b/lib/src/cli.rs index 215feef06..0db4821b8 100644 --- a/lib/src/cli.rs +++ b/lib/src/cli.rs @@ -167,9 +167,10 @@ pub(crate) enum Opt { /// Execute the given command in the host mount namespace #[cfg(feature = "install")] #[clap(hide = true)] - #[command(external_subcommand)] - ExecInHostMountNamespace(Vec), - + ExecInHostMountNamespace { + #[clap(trailing_var_arg = true, allow_hyphen_values = true)] + args: Vec, + }, /// Internal integration testing helpers. #[clap(hide(true), subcommand)] #[cfg(feature = "internal-testing-api")] @@ -468,7 +469,7 @@ async fn run_from_opt(opt: Opt) -> Result<()> { InstallOpts::ToFilesystem(opts) => crate::install::install_to_filesystem(opts).await, }, #[cfg(feature = "install")] - Opt::ExecInHostMountNamespace(args) => { + Opt::ExecInHostMountNamespace { args } => { crate::install::exec_in_host_mountns(args.as_slice()) } Opt::Status(opts) => super::status::status(opts).await, diff --git a/lib/src/install.rs b/lib/src/install.rs index 20ff786c6..cc483813f 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -673,7 +673,7 @@ pub(crate) fn run_in_host_mountns(cmd: &str) -> Command { #[context("Re-exec in host mountns")] pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> { - let (cmd, args) = args[1..] + let (cmd, args) = args .split_first() .ok_or_else(|| anyhow::anyhow!("Missing command"))?; tracing::trace!("{cmd:?} {args:?}");