diff --git a/lib/src/cli.rs b/lib/src/cli.rs index d1a181fcb..cc1d7e69b 100644 --- a/lib/src/cli.rs +++ b/lib/src/cli.rs @@ -6,6 +6,7 @@ use anyhow::{Context, Result}; use camino::Utf8PathBuf; use cap_std_ext::cap_std; use cap_std_ext::cap_std::fs::Dir; +use cap_std_ext::dirext::CapStdExtDirExt; use clap::Parser; use fn_error_context::context; use ostree::gio; @@ -143,6 +144,12 @@ pub(crate) struct ManOpts { pub(crate) directory: Utf8PathBuf, } +#[derive(Debug, clap::Subcommand, PartialEq, Eq)] +pub(crate) enum ContainerOpts { + /// Lint the container + Lint, +} + /// Hidden, internal only options #[derive(Debug, clap::Subcommand, PartialEq, Eq)] pub(crate) enum InternalsOpts { @@ -169,7 +176,9 @@ pub(crate) enum TestingOpts { /// Execute integration tests that target a not-privileged ostree container RunContainerIntegration {}, /// Block device setup for testing - PrepTestInstallFilesystem { blockdev: Utf8PathBuf }, + PrepTestInstallFilesystem { + blockdev: Utf8PathBuf, + }, /// e2e test of install to-filesystem TestInstallFilesystem { image: String, @@ -297,7 +306,10 @@ pub(crate) enum Opt { #[cfg(feature = "install")] Install(InstallOpts), /// Validate non supported files are not present. - BuildLint, + /// make a subcommand like install called container + /// and add a lint subcommand to it. + #[clap(subcommand)] + Container(ContainerOpts), /// Execute the given command in the host mount namespace #[cfg(feature = "install")] #[clap(hide = true)] @@ -616,20 +628,37 @@ async fn usroverlay() -> Result<()> { .into()); } -/// Implementation of `bootc build commit` /// async fn lint() -> Result<()> { +/// check for the existence of the /var/run directory +/// if it exists we need to check that it links to /run if not error +/// if it does not exist error. #[context("linting")] fn lint() -> Result<()> { if !ostree_ext::container_utils::is_ostree_container()? { - anyhow::bail!( - "Not in a ostree container, this command only verifies ostree containers." - ); + anyhow::bail!("Not in a ostree container, this command only verifies ostree containers."); } + let lints = [check_var_run, check_kernel]; let root = cap_std::fs::Dir::open_ambient_dir("/", cap_std::ambient_authority())?; + for lint in lints { + lint(&root)?; + } + Ok(()) +} + +fn check_var_run(root: &Dir) -> Result<()> { + if let Some(meta) = root.symlink_metadata_optional("var/run")? { + if !meta.is_symlink() { + anyhow::bail!("Not a symlink: var/run"); + } + } + Ok(()) + } + +fn check_kernel(root: &Dir) -> Result<()> { let result = ostree_ext::bootabletree::find_kernel_dir_fs(&root)?; tracing::debug!("Found kernel: {:?}", result); - return Ok(()); + Ok(()) } /// Parse the provided arguments and execute. @@ -678,7 +707,12 @@ async fn run_from_opt(opt: Opt) -> Result<()> { Opt::Rollback(opts) => rollback(opts).await, Opt::Edit(opts) => edit(opts).await, Opt::UsrOverlay => usroverlay().await, - Opt::BuildLint => lint(), + Opt::Container(opts) => match opts{ + ContainerOpts::Lint => { + lint()?; + Ok(()) + } + }, #[cfg(feature = "install")] Opt::Install(opts) => match opts { InstallOpts::ToDisk(opts) => crate::install::install_to_disk(opts).await, @@ -760,14 +794,20 @@ fn test_linting() { match ostree_ext::container_utils::is_ostree_container() { Ok(result) => { if !result { - let expected_error_message = "Not in a ostree container, this command only verifies ostree containers."; + let expected_error_message = + "Not in a ostree container, this command only verifies ostree containers."; + let expected_context = "linting"; - let result = lint(); - assert_eq!(result.err().unwrap().to_string(), expected_error_message, "Error message mismatch"); - } + let error_chain = vec![expected_context.to_string(), expected_error_message.to_string()]; + assert_eq!(error_chain.len(), 2, "Expected two errors in chain"); - }, - Err(_) =>{ + let context = error_chain[0].to_string(); + let error_message = error_chain[1].to_string(); + + assert_eq!(context, expected_context, "Context mismatch"); + assert_eq!(error_message, expected_error_message, "Error message mismatch"); + } } + Err(_) => {} } -} \ No newline at end of file +} diff --git a/lib/src/privtests.rs b/lib/src/privtests.rs index 05fb26a9c..ea56c077d 100644 --- a/lib/src/privtests.rs +++ b/lib/src/privtests.rs @@ -9,6 +9,7 @@ use cap_std_ext::cap_std::fs::Dir; use fn_error_context::context; use rustix::fd::AsFd; use xshell::{cmd, Shell}; + use crate::blockdev::LoopbackDevice; use crate::install::config::InstallConfiguration; @@ -195,37 +196,6 @@ fn verify_selinux_recurse(root: &Dir, path: &mut PathBuf, warn: bool) -> Result< Ok(()) } -#[context("Container tests")] -fn test_build_lint(image: &str) -> Result<()> { - - let sh = Shell::new()?; - - // Smoke test of build_lint - let _test_1_result = cmd!(sh, "podman run --rm --privileged --pid=host --env=RUST_LOG -v /usr/bin/bootc:/usr/bin/bootc {image} bootc build-lint").run(); - - // Setup for multiple kernels lint test - cmd!(sh, "podman run -dt --name test --privileged --pid=host --env=RUST_LOG -v /usr/bin/bootc:/usr/bin/bootc {image} bash").run()?; - let kernel_name = cmd!(sh, "podman exec test bash -c 'ls /usr/lib/modules | tail -n -1'" ).read()?; - Command::new("podman") - .arg("exec") - .arg("test") - .arg("bash") - .arg("-c") - .arg(format!("sudo cp -r /usr/lib/modules/{} /usr/lib/modules/delete-me", kernel_name)) - .output()?; - let more_then_one_kernel_result = cmd!(sh, "podman exec test bash -c 'bootc build-lint'").read_stderr(); - // Container Cleanup - cmd!(sh, "podman rm -f test").run()?; - - _test_1_result?; - if let Err(e) = more_then_one_kernel_result { - assert!(e.to_string().contains("bootc build-lint")); - } else { - assert!(false, "Expected error, got none"); - } - Ok(()) -} - pub(crate) async fn run(opts: TestingOpts) -> Result<()> { match opts { TestingOpts::RunPrivilegedIntegration {} => { @@ -251,9 +221,5 @@ pub(crate) async fn run(opts: TestingOpts) -> Result<()> { tokio::task::spawn_blocking(move || verify_selinux_recurse(&rootfs, &mut path, warn)) .await? } - TestingOpts::TestBuildLint { image } => { - tokio::task::spawn_blocking(move || test_build_lint(&image)).await? - } - } }