feat(systemd): Systemd trait + LiveSystemd + MockSystemd + parsers#12
Merged
Conversation
Plan §6.8 — third M1 Week 2 adapter probe path. Inventory only at M1;
enable / disable / mask / restart arrive with M2 per Plan §7.3.
Public surface:
- pub trait Systemd { fn inventory(&self) -> Result<ServiceInventory, SystemdError>; }
- pub struct LiveSystemd with new() / with_binary() / binary().
- pub struct MockSystemd (test-mocks feature) with new() / with_inventory().
- pub fn parse_list_unit_files(&str) -> (BTreeSet<String>, BTreeSet<String>, BTreeSet<String>)
returning (enabled, disabled, masked).
- pub fn parse_list_units(&str) -> BTreeSet<String> returning the
loaded+active set.
- pub fn compose_inventory(unit_files, units) -> ServiceInventory.
- pub enum SystemdError — NotInPath, Io, InvocationFailed, NotUtf8.
Parser semantics:
- list-unit-files: enabled and enabled-runtime → enabled set;
disabled → disabled; masked and masked-runtime → masked. static,
alias, indirect, generated, transient skipped (not user-configurable
enable values).
- list-units: filter LOAD == "loaded" && ACTIVE == "active" so the
active set excludes not-found, error, masked, and inactive units.
LiveSystemd invokes:
- systemctl list-unit-files --no-pager --no-legend
- systemctl list-units --no-pager --no-legend --all --plain
Tests (10 passing):
- inventory: list_unit_files_distinguishes_enabled_disabled_masked,
list_unit_files_skips_static_alias_indirect,
list_units_filters_to_loaded_active, empty_outputs_yield_empty_inventory,
compose_combines_both_streams, truncated_lines_are_skipped.
- live: systemctl_not_in_path_error_class,
live_systemd_inventory_succeeds_when_systemctl_present (silent-skips
if systemctl missing — CI runners have it).
- mock: empty_mock_yields_empty_inventory, with_inventory_round_trips.
Verification:
- cargo test -p pearlite-systemd (10 passed; 0 failed)
- cargo clippy --workspace --all-targets -- -D warnings (zero warnings)
- cargo fmt --all --check
- scripts/ci/check-spdx.sh
- pearlite-audit check . (1 check, 0 violations)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plan §6.8 — third M1 Week 2 adapter probe path. Inventory only at M1; enable/disable/mask/restart arrive in M2.
Public surface
trait Systemd { fn inventory() -> Result<ServiceInventory, SystemdError>; }struct LiveSystemd— invokessystemctl list-unit-files+list-units.struct MockSystemd— feature-gated, canned inventory.fn parse_list_unit_files/parse_list_units/compose_inventoryexposed pub for direct use.Parser semantics
enabled+enabled-runtime→ enabled;disabled→ disabled;masked+masked-runtime→ masked.static/alias/indirect/generated/transientskipped.LOAD == loaded && ACTIVE == active— excludes not-found, error, masked, inactive.Tests (10 passing)
systemctl_not_in_path_error_class,live_systemd_inventory_succeeds_when_systemctl_present(silent-skips when systemctl missing).Verification
cargo test -p pearlite-systemd— 10 passed; 0 failedcargo clippy --workspace --all-targets -- -D warningscargo fmt --all --checkscripts/ci/check-spdx.shpearlite-audit check .— 1 check, 0 violations🤖 Generated with Claude Code