Skip to content

Commit 8b961d8

Browse files
committed
lints: Add description and --list
Part of #1065 Signed-off-by: Colin Walters <[email protected]>
1 parent acba25f commit 8b961d8

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ cap-std-ext = { workspace = true, features = ["fs_utf8"] }
2727
hex = { workspace = true }
2828
fn-error-context = { workspace = true }
2929
indicatif = { workspace = true }
30+
indoc = { workspace = true }
3031
libc = { workspace = true }
3132
liboverdrop = "0.1.0"
3233
libsystemd = "0.7"
@@ -50,7 +51,6 @@ comfy-table = "7.1.1"
5051
thiserror = "2.0.11"
5152

5253
[dev-dependencies]
53-
indoc = { workspace = true }
5454
similar-asserts = { workspace = true }
5555
static_assertions = { workspace = true }
5656

lib/src/cli.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,13 @@ pub(crate) enum ContainerOpts {
249249
/// Make warnings fatal.
250250
#[clap(long)]
251251
fatal_warnings: bool,
252+
253+
/// Instead of executing the lints, just print all available lints.
254+
/// At the current time, this will output in YAML format because it's
255+
/// reasonably human friendly. However, there is no commitment to
256+
/// maintaining this exact format; do not parse it via code or scripts.
257+
#[clap(long)]
258+
list: bool,
252259
},
253260
}
254261

@@ -1018,7 +1025,11 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
10181025
ContainerOpts::Lint {
10191026
rootfs,
10201027
fatal_warnings,
1028+
list,
10211029
} => {
1030+
if list {
1031+
return lints::lint_list(std::io::stdout().lock());
1032+
}
10221033
if !ostree_ext::container_utils::is_ostree_container()? {
10231034
anyhow::bail!(
10241035
"Not in a ostree container, this command only verifies ostree containers."

lib/src/lints.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use cap_std_ext::cap_std;
1313
use cap_std_ext::cap_std::fs::MetadataExt;
1414
use cap_std_ext::dirext::CapStdExtDirExt as _;
1515
use fn_error_context::context;
16+
use indoc::indoc;
17+
use serde::Serialize;
1618

1719
/// Reference to embedded default baseimage content that should exist.
1820
const BASEIMAGE_REF: &str = "usr/share/doc/bootc/baseimage/base";
@@ -51,7 +53,8 @@ impl LintError {
5153
type LintFn = fn(&Dir) -> LintResult;
5254

5355
/// The classification of a lint type.
54-
#[derive(Debug)]
56+
#[derive(Debug, Serialize)]
57+
#[serde(rename_all = "kebab-case")]
5558
enum LintType {
5659
/// If this fails, it is known to be fatal - the system will not install or
5760
/// is effectively guaranteed to fail at runtime.
@@ -60,51 +63,89 @@ enum LintType {
6063
Warning,
6164
}
6265

66+
#[derive(Debug, Serialize)]
67+
#[serde(rename_all = "kebab-case")]
6368
struct Lint {
6469
name: &'static str,
70+
#[serde(rename = "type")]
6571
ty: LintType,
72+
#[serde(skip)]
6673
f: LintFn,
74+
description: &'static str,
6775
}
6876

6977
const LINTS: &[Lint] = &[
7078
Lint {
7179
name: "var-run",
7280
ty: LintType::Fatal,
7381
f: check_var_run,
82+
description: "Check for /var/run being a physical directory; this is always a bug.",
7483
},
7584
Lint {
7685
name: "kernel",
7786
ty: LintType::Fatal,
7887
f: check_kernel,
88+
description: indoc! { r#"
89+
Check for multiple kernels, i.e. multiple directories of the form /usr/lib/modules/$kver.
90+
Only one kernel is supported in an image.
91+
"# },
7992
},
8093
Lint {
8194
name: "bootc-kargs",
8295
ty: LintType::Fatal,
8396
f: check_parse_kargs,
97+
description: "Verify syntax of /usr/lib/bootc/kargs.d.",
8498
},
8599
Lint {
86100
name: "etc-usretc",
87101
ty: LintType::Fatal,
88102
f: check_usretc,
103+
description: indoc! { r#"
104+
Verify that only one of /etc or /usr/etc exist. You should only have /etc
105+
in a container image. It will cause undefined behavior to have both /etc
106+
and /usr/etc.
107+
"#},
89108
},
90109
Lint {
91110
// This one can be lifted in the future, see https://github.com/containers/bootc/issues/975
92111
name: "utf8",
93112
ty: LintType::Fatal,
94113
f: check_utf8,
114+
description: indoc! { r#"
115+
Check for non-UTF8 filenames. Currently, the ostree backend of bootc only supports
116+
UTF-8 filenames. Non-UTF8 filenames will cause a fatal error.
117+
"#},
95118
},
96119
Lint {
97120
name: "baseimage-root",
98121
ty: LintType::Fatal,
99122
f: check_baseimage_root,
123+
description: indoc! { r#"
124+
Check that expected files are present in the root of the filesystem; such
125+
as /sysroot and a composefs configuration for ostree. More in
126+
<https://containers.github.io/bootc/bootc-images.html#standard-image-content>.
127+
"#},
100128
},
101129
Lint {
102130
name: "var-log",
103131
ty: LintType::Warning,
104132
f: check_varlog,
133+
description: indoc! { r#"
134+
Check for non-empty regular files in `/var/log`. It is often undesired
135+
to ship log files in container images. Log files in general are usually
136+
per-machine state in `/var`. Additionally, log files often include
137+
timestamps, causing unreproducible container images, and may contain
138+
sensitive build system information.
139+
"#},
105140
},
106141
];
107142

143+
pub(crate) fn lint_list(output: impl std::io::Write) -> Result<()> {
144+
// Dump in yaml format by default, it's readable enough
145+
serde_yaml::to_writer(output, LINTS)?;
146+
Ok(())
147+
}
148+
108149
/// check for the existence of the /var/run directory
109150
/// if it exists we need to check that it links to /run if not error
110151
/// if it does not exist error.
@@ -522,4 +563,12 @@ mod tests {
522563
check_baseimage_root(&td).unwrap().unwrap();
523564
Ok(())
524565
}
566+
567+
#[test]
568+
fn test_list() {
569+
let mut r = Vec::new();
570+
lint_list(&mut r).unwrap();
571+
let lints: Vec<serde_yaml::Value> = serde_yaml::from_slice(&r).unwrap();
572+
assert_eq!(lints.len(), LINTS.len());
573+
}
525574
}

0 commit comments

Comments
 (0)