# bootc container lint - Technical Reference ## Architecture Overview The bootc lint system is built on a distributed slice architecture using the `linkme` crate, allowing for modular lint registration and execution. The system supports both regular and recursive lints, with configurable execution and output formatting. ## Core Components ### 1. Lint Registration System ```rust // From lints.rs:86-87 #[distributed_slice] pub(crate) static LINTS: [Lint]; ``` **Purpose**: Central registry for all lint checks **Implementation**: Uses `linkme` distributed slices for automatic registration **Benefits**: Modular design, easy addition of new lints ### 2. Lint Types #### Fatal Lints ```rust // From lints.rs:92-98 enum LintType { Fatal, // Must pass for installation Warning, // Recommended but not required } ``` **Fatal Lints**: Prevent bootc installation if they fail **Warning Lints**: Show warnings but allow installation to proceed ### 3. Root Type Classification ```rust // From lints.rs:106-111 enum RootType { Running, // Running system root Alternative, // Alternative/container root } ``` **Running**: Lints that apply to running systems **Alternative**: Lints that apply to container images ## Lint Execution Engine ### 1. Execution Flow ```rust // From lints.rs:254-364 fn lint_inner<'skip>( root: &Dir, root_type: RootType, config: &LintExecutionConfig, skip: impl IntoIterator, mut output: impl std::io::Write, ) -> Result ``` **Process**: 1. Filter applicable lints based on root type 2. Separate regular and recursive lints 3. Execute regular lints 4. Execute recursive lints via filesystem walk 5. Collect and report results ### 2. Recursive Lint Execution ```rust // From lints.rs:295-328 root.walk( &WalkConfiguration::default() .noxdev() .path_base(Path::new("/")), |e| -> std::io::Result<_> { // Execute recursive lints on each filesystem entry }, )?; ``` **Features**: - Filesystem traversal with `noxdev` (no cross-device) - Early termination on first error - Efficient processing of large filesystems ### 3. Output Formatting ```rust // From lints.rs:200-235 fn format_items( config: &LintExecutionConfig, header: &str, items: impl Iterator, o: &mut String, ) -> Result<()> ``` **Features**: - Configurable truncation (default: 5 items) - Consistent formatting across lints - Support for custom display implementations ## Individual Lint Implementations ### 1. var-run Lint ```rust // From lints.rs:397-410 static LINT_VAR_RUN: Lint = Lint::new_fatal( "var-run", "Check for /var/run being a physical directory; this is always a bug.", check_var_run, ); ``` **Purpose**: Ensures `/var/run` is a symlink to `/run` **Check**: Validates symlink existence and target **Rationale**: Required for proper systemd operation ### 2. etc-usretc Lint ```rust // From lints.rs:435-458 static LINT_ETC_USRUSETC: Lint = Lint::new_fatal( "etc-usretc", "Verify that only one of /etc or /usr/etc exist...", check_usretc, ); ``` **Purpose**: Prevents both `/etc` and `/usr/etc` from existing **Check**: Validates mutual exclusivity **Rationale**: `/usr/etc` is a bootc implementation detail ### 3. bootc-kargs Lint ```rust // From lints.rs:461-471 static LINT_KARGS: Lint = Lint::new_fatal( "bootc-kargs", "Verify syntax of /usr/lib/bootc/kargs.d.", check_parse_kargs, ); ``` **Purpose**: Validates kernel argument configuration **Check**: Parses TOML files in `/usr/lib/bootc/kargs.d/` **Integration**: Uses `crate::bootc_kargs::get_kargs_in_root` ### 4. kernel Lint ```rust // From lints.rs:473-486 static LINT_KERNEL: Lint = Lint::new_fatal( "kernel", "Check for multiple kernels...", check_kernel, ); ``` **Purpose**: Ensures exactly one kernel is present **Check**: Validates `/usr/lib/modules/$kver` directories **Integration**: Uses `ostree_ext::bootabletree::find_kernel_dir_fs` ### 5. utf8 Lint (Recursive) ```rust // From lints.rs:489-522 static LINT_UTF8: Lint = Lint { name: "utf8", description: "Check for non-UTF8 filenames...", ty: LintType::Fatal, root_type: None, f: LintFnTy::Recursive(check_utf8), }; ``` **Purpose**: Ensures all filenames and symlink targets are UTF-8 **Check**: Recursively validates filesystem entries **Features**: Handles symlinks, broken links, and special cases ### 6. api-base-directories Lint ```rust // From lints.rs:535-558 static LINT_API_DIRS: Lint = Lint::new_fatal( "api-base-directories", "Verify that expected base API directories exist...", check_api_dirs, ); ``` **Purpose**: Validates required systemd API directories **Check**: Ensures `/dev`, `/proc`, `/sys`, `/run`, `/tmp`, `/var` exist **Rationale**: Required by systemd and Linux standards ### 7. baseimage-root Lint ```rust // From lints.rs:610-632 static LINT_BASEIMAGE_ROOT: Lint = Lint::new_fatal( "baseimage-root", "Check that expected files are present in the root...", check_baseimage_root, ); ``` **Purpose**: Validates bootc-specific root structure **Check**: Ensures `/sysroot` exists and `/ostree` symlinks correctly **Integration**: Checks embedded documentation for consistency ## Warning Lints ### 1. buildah-injected Lint ```rust // From lints.rs:412-433 static LINT_BUILDAH_INJECTED: Lint = Lint::new_warning( "buildah-injected", "Check for an invalid /etc/hostname or /etc/resolv.conf...", check_buildah_injected, ) .set_root_type(RootType::Alternative); ``` **Purpose**: Detects empty files injected by build systems **Check**: Looks for empty `/etc/hostname` or `/etc/resolv.conf` **Scope**: Only applies to alternative roots (container images) ### 2. baseimage-composefs Lint ```rust // From lints.rs:560-581 static LINT_COMPOSEFS: Lint = Lint::new_warning( "baseimage-composefs", "Check that composefs is enabled for ostree...", check_composefs, ); ``` **Purpose**: Recommends composefs for ostree **Check**: Validates composefs configuration **Integration**: Uses `ostree_prepareroot` for configuration parsing ### 3. var-log Lint ```rust // From lints.rs:656-682 static LINT_VARLOG: Lint = Lint::new_warning( "var-log", "Check for non-empty regular files in /var/log...", check_varlog, ); ``` **Purpose**: Warns about log files in container images **Check**: Identifies non-empty files in `/var/log` **Features**: Recursive directory scanning with size checking ### 4. var-tmpfiles Lint ```rust // From lints.rs:684-712 static LINT_VAR_TMPFILES: Lint = Lint::new_warning( "var-tmpfiles", "Check for content in /var that does not have corresponding systemd tmpfiles.d entries...", check_var_tmpfiles, ) .set_root_type(RootType::Running); ``` **Purpose**: Validates tmpfiles.d configuration **Check**: Ensures `/var` content has corresponding tmpfiles.d entries **Scope**: Only applies to running systems **Integration**: Uses `bootc_tmpfiles` crate ### 5. sysusers Lint ```rust // From lints.rs:714-743 static LINT_SYSUSERS: Lint = Lint::new_warning( "sysusers", "Check for users in /etc/passwd and groups in /etc/group...", check_sysusers, ); ``` **Purpose**: Validates user/group definitions **Check**: Ensures sysusers.d entries exist for passwd/group entries **Integration**: Uses `bootc_sysusers` crate ### 6. nonempty-boot Lint ```rust // From lints.rs:745-773 static LINT_NONEMPTY_BOOT: Lint = Lint::new_warning( "nonempty-boot", "The /boot directory should be present, but empty...", check_boot, ); ``` **Purpose**: Warns about content in `/boot` directory **Check**: Ensures `/boot` is empty in container images **Rationale**: Kernel content should be in `/usr/lib/modules` ## Configuration and Options ### 1. LintExecutionConfig ```rust // From lints.rs:69-72 struct LintExecutionConfig { no_truncate: bool, } ``` **no_truncate**: Controls output truncation (default: false, shows 5 items) ### 2. WarningDisposition ```rust // From lints.rs:101-104 enum WarningDisposition { AllowWarnings, // Warnings don't fail the build FatalWarnings, // Warnings are treated as fatal } ``` **Purpose**: Controls how warnings are handled **Default**: AllowWarnings ### 3. RootType ```rust // From lints.rs:106-111 enum RootType { Running, // Running system root Alternative, // Alternative/container root } ``` **Purpose**: Determines which lints apply to which root types **Filtering**: Lints can be restricted to specific root types ## Error Handling ### 1. LintError Type ```rust // From lints.rs:38-67 struct LintError(String); impl std::fmt::Display for LintError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&self.0) } } ``` **Purpose**: Represents lint failures **Features**: Custom display implementation for formatted output ### 2. Result Types ```rust // From lints.rs:44 type LintResult = Result>; ``` **Outer Result**: Runtime errors (file system issues, etc.) **Inner Result**: Lint success/failure **Pattern**: `Ok(Ok(()))` = success, `Ok(Err(LintError))` = lint failure ### 3. Error Reporting ```rust // From lints.rs:340-356 if let Err(e) = r { match lint.ty { LintType::Fatal => { writeln!(output, "Failed lint: {name}: {e}")?; fatal += 1; } LintType::Warning => { writeln!(output, "Lint warning: {name}: {e}")?; warnings += 1; } } } ``` **Format**: Consistent error message formatting **Categorization**: Separate handling for fatal vs warning errors ## Performance Optimizations ### 1. Early Termination ```rust // From lints.rs:300-303 if recursive_lints.is_empty() { return Ok(ControlFlow::Break(())); } ``` **Feature**: Stops processing when no recursive lints remain **Benefit**: Avoids unnecessary filesystem traversal ### 2. Lint Filtering ```rust // From lints.rs:265-275 let (mut applicable_lints, skipped_lints): (Vec<_>, Vec<_>) = LINTS.iter().partition(|lint| { if skip.contains(lint.name) { return false; } if let Some(lint_root_type) = lint.root_type { if lint_root_type != root_type { return false; } } true }); ``` **Feature**: Only runs applicable lints **Benefit**: Reduces execution time for irrelevant checks ### 3. Output Truncation ```rust // From lints.rs:221-233 if config.no_truncate { // Show all items } else { // Show limited items with count if rest > 0 { writeln!(o, " ...and {rest} more")?; } } ``` **Feature**: Configurable output length **Default**: 5 items per lint **Benefit**: Prevents overwhelming output for large issues ## Testing Framework ### 1. Test Fixtures ```rust // From lints.rs:788-814 fn passing_fixture() -> Result { let root = cap_std_ext::cap_tempfile::tempdir(cap_std::ambient_authority())?; for d in API_DIRS { root.create_dir(d)?; } // ... setup valid filesystem structure Ok(root) } ``` **Purpose**: Creates test filesystems for lint validation **Features**: Both passing and failing test cases ### 2. Individual Lint Tests ```rust // From lints.rs:816-828 #[test] fn test_var_run() -> Result<()> { let root = &fixture()?; let config = &LintExecutionConfig::default(); // Test passing case check_var_run(root, config).unwrap().unwrap(); // Test failing case root.create_dir_all("var/run/foo")?; assert!(check_var_run(root, config).unwrap().is_err()); Ok(()) } ``` **Coverage**: Each lint has dedicated tests **Scenarios**: Both success and failure cases ### 3. Integration Tests ```rust // From lints.rs:844-889 #[test] fn test_lint_inner() -> Result<()> { let root = &passing_fixture()?; let config = &LintExecutionConfig::default(); let mut out = Vec::new(); let root_type = RootType::Alternative; let r = lint_inner(root, root_type, config, [], &mut out).unwrap(); // Verify results assert_eq!(r.passed, *ALTROOT_LINTS); Ok(()) } ``` **Purpose**: Tests the complete lint execution flow **Validation**: Verifies correct counting and categorization ## Integration Points ### 1. OSTree Integration - Uses `ostree_ext::bootabletree` for kernel detection - Integrates with `ostree_prepareroot` for composefs validation - Leverages OSTree's filesystem understanding ### 2. Systemd Integration - Validates systemd API directories - Checks tmpfiles.d configuration - Validates sysusers.d entries ### 3. Container Runtime Integration - Designed for container build processes - Supports various root filesystem types - Handles container-specific issues ## Future Enhancements ### 1. Extensibility - Plugin system for custom lints - Configuration file support - Custom output formats ### 2. Performance - Parallel lint execution - Incremental checking - Caching mechanisms ### 3. Integration - IDE integration - CI/CD pipeline optimization - Real-time feedback This technical reference provides comprehensive understanding of the bootc lint system's architecture, implementation, and usage patterns.