Skip to content

Commit

Permalink
Merge pull request #381 from prestist/build-lint
Browse files Browse the repository at this point in the history
cli: add container lint
  • Loading branch information
cgwalters authored Jun 3, 2024
2 parents f152bfe + 858acbe commit ebe1530
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 0 deletions.
23 changes: 23 additions & 0 deletions docs/src/man/bootc-container-lint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# NAME

bootc-container-lint - Perform relatively inexpensive static analysis
checks as part of a container build

# SYNOPSIS

**bootc container lint** \[**-h**\|**\--help**\]

# DESCRIPTION

Perform relatively inexpensive static analysis checks as part of a
container build

# OPTIONS

**-h**, **\--help**

: Print help

# VERSION

v0.1.11
33 changes: 33 additions & 0 deletions docs/src/man/bootc-container.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# NAME

bootc-container - Operations which can be executed as part of a
container build

# SYNOPSIS

**bootc container** \[**-h**\|**\--help**\] \<*subcommands*\>

# DESCRIPTION

Operations which can be executed as part of a container build

# OPTIONS

**-h**, **\--help**

: Print help

# SUBCOMMANDS

bootc-container-lint(8)

: Perform relatively inexpensive static analysis checks as part of a
container build

bootc-container-help(8)

: Print this message or the help of the given subcommand(s)

# VERSION

v0.1.11
4 changes: 4 additions & 0 deletions docs/src/man/bootc.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ bootc-install(8)

: Install the running container to a target

bootc-container(8)

: Operations which can be executed as part of a container build

bootc-help(8)

: Print this message or the help of the given subcommand(s)
Expand Down
1 change: 1 addition & 0 deletions hack/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ FROM $base
COPY --from=build /out/bootc.tar.zst /tmp
COPY --from=build /build/target/dev-rootfs/ /
RUN tar -C / --zstd -xvf /tmp/bootc.tar.zst && rm -vf /tmp/*
RUN bootc container lint
25 changes: 25 additions & 0 deletions lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use std::os::unix::process::CommandExt;
use std::process::Command;

use crate::deploy::RequiredHostSpec;
use crate::lints;
use crate::spec::Host;
use crate::spec::ImageReference;
use crate::utils::sigpolicy_from_opts;
Expand Down Expand Up @@ -143,6 +144,14 @@ pub(crate) struct ManOpts {
pub(crate) directory: Utf8PathBuf,
}

/// Subcommands which can be executed as part of a container build.
#[derive(Debug, clap::Subcommand, PartialEq, Eq)]
pub(crate) enum ContainerOpts {
/// Perform relatively inexpensive static analysis checks as part of a container
/// build.
Lint,
}

/// Hidden, internal only options
#[derive(Debug, clap::Subcommand, PartialEq, Eq)]
pub(crate) enum InternalsOpts {
Expand Down Expand Up @@ -292,6 +301,9 @@ pub(crate) enum Opt {
#[clap(subcommand)]
#[cfg(feature = "install")]
Install(InstallOpts),
/// Operations which can be executed as part of a container build.
#[clap(subcommand)]
Container(ContainerOpts),
/// Execute the given command in the host mount namespace
#[cfg(feature = "install")]
#[clap(hide = true)]
Expand Down Expand Up @@ -662,6 +674,19 @@ 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::Container(opts) => match opts {
ContainerOpts::Lint => {
if !ostree_ext::container_utils::is_ostree_container()? {
anyhow::bail!(
"Not in a ostree container, this command only verifies ostree containers."
);
}

let root = cap_std::fs::Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
lints::lint(&root)?;
Ok(())
}
},
#[cfg(feature = "install")]
Opt::Install(opts) => match opts {
InstallOpts::ToDisk(opts) => crate::install::install_to_disk(opts).await,
Expand Down
1 change: 1 addition & 0 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub mod cli;
pub(crate) mod deploy;
pub(crate) mod generator;
pub(crate) mod journal;
mod lints;
mod lsm;
pub(crate) mod metadata;
mod reboot;
Expand Down
72 changes: 72 additions & 0 deletions lib/src/lints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//! # Implementation of container build lints
//!
//! This module implements `bootc container lint`.

use anyhow::Result;
use cap_std::fs::Dir;
use cap_std_ext::cap_std;
use cap_std_ext::dirext::CapStdExtDirExt as _;
use fn_error_context::context;

/// 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")]
pub(crate) fn lint(root: &Dir) -> Result<()> {
let lints = [check_var_run, check_kernel];
for lint in lints {
lint(&root)?;
}
println!("Checks passed: {}", lints.len());
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);
Ok(())
}

#[cfg(test)]
fn fixture() -> Result<cap_std_ext::cap_tempfile::TempDir> {
let tempdir = cap_std_ext::cap_tempfile::tempdir(cap_std::ambient_authority())?;
Ok(tempdir)
}

#[test]
fn test_var_run() -> Result<()> {
let root = &fixture()?;
// This one should pass
check_var_run(root).unwrap();
root.create_dir_all("var/run/foo")?;
assert!(check_var_run(root).is_err());
root.remove_dir_all("var/run")?;
// Now we should pass again
check_var_run(root).unwrap();
Ok(())
}

#[test]
fn test_kernel_lint() -> Result<()> {
let root = &fixture()?;
// This one should pass
check_kernel(root).unwrap();
root.create_dir_all("usr/lib/modules/5.7.2")?;
root.write("usr/lib/modules/5.7.2/vmlinuz", "old vmlinuz")?;
root.create_dir_all("usr/lib/modules/6.3.1")?;
root.write("usr/lib/modules/6.3.1/vmlinuz", "new vmlinuz")?;
assert!(check_kernel(root).is_err());
root.remove_dir_all("usr/lib/modules/5.7.2")?;
// Now we should pass again
check_kernel(root).unwrap();
Ok(())
}

0 comments on commit ebe1530

Please sign in to comment.