Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
982 changes: 459 additions & 523 deletions Cargo.lock

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ musl-aarch64-modules-dist:
$(call stage_modules_dist_from,release,aarch64-unknown-linux-musl,$(MUSL_MODULE_PACKAGE_SPECS),$(call musl_modules_dist_dir,aarch64,release))

all-dev:
@scripts/maybe-mxrun.sh all-dev || $(MAKE) _all_dev
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _all_dev; else scripts/maybe-mxrun.sh all-dev || $(MAKE) _all_dev; fi

_all_dev:
cargo build -v --workspace $(PLATFORM_WORKSPACE_EXCLUDES)
Expand All @@ -202,7 +202,7 @@ _all_dev:
$(call write_mxrun_manifest,all-dev,)

all:
@scripts/maybe-mxrun.sh all || $(MAKE) _all
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _all; else scripts/maybe-mxrun.sh all || $(MAKE) _all; fi

_all:
cargo build --release --workspace $(PLATFORM_WORKSPACE_EXCLUDES)
Expand All @@ -211,7 +211,7 @@ _all:
$(call write_mxrun_manifest,all,)

dev:
@scripts/maybe-mxrun.sh dev || $(MAKE) _dev
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _dev; else scripts/maybe-mxrun.sh dev || $(MAKE) _dev; fi

_dev:
cargo build -v --workspace $(CORE_EXCLUDES)
Expand All @@ -220,7 +220,7 @@ _dev:
$(call write_mxrun_manifest,dev,)

build:
@scripts/maybe-mxrun.sh release || $(MAKE) _build
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _build; else scripts/maybe-mxrun.sh release || $(MAKE) _build; fi

_build:
cargo build --release --workspace $(CORE_EXCLUDES)
Expand All @@ -229,23 +229,23 @@ _build:
$(call write_mxrun_manifest,release,)

modules-dev:
@scripts/maybe-mxrun.sh modules-dev || $(MAKE) _modules_dev
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _modules_dev; else scripts/maybe-mxrun.sh modules-dev || $(MAKE) _modules_dev; fi

_modules_dev:
@CARGO_BUILD_JOBS=$(MODULE_BUILD_JOBS) cargo build -v $(foreach pkg,$(MODULE_PACKAGE_SPECS),-p $(pkg))
$(call stage_profile_modules,debug,)
$(call write_mxrun_manifest,modules-dev,)

modules:
@scripts/maybe-mxrun.sh modules || $(MAKE) _modules
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _modules; else scripts/maybe-mxrun.sh modules || $(MAKE) _modules; fi

_modules:
@CARGO_BUILD_JOBS=$(MODULE_BUILD_JOBS) cargo build --release $(foreach pkg,$(MODULE_PACKAGE_SPECS),-p $(pkg))
$(call stage_profile_modules,release,)
$(call write_mxrun_manifest,modules,)

modules-dist-dev:
@scripts/maybe-mxrun.sh modules-dist-dev || $(MAKE) _modules_dist_dev
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _modules_dist_dev; else scripts/maybe-mxrun.sh modules-dist-dev || $(MAKE) _modules_dist_dev; fi

_modules_dist_dev:
@CARGO_BUILD_JOBS=$(MODULE_BUILD_JOBS) cargo build --release $(foreach pkg,$(MODULE_PACKAGE_SPECS),-p $(pkg))
Expand All @@ -254,31 +254,31 @@ _modules_dist_dev:
$(call write_mxrun_manifest,modules-dist-dev,with-dist)

test: setup
@scripts/maybe-mxrun.sh test || $(MAKE) _test
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _test; else scripts/maybe-mxrun.sh test || $(MAKE) _test; fi

_test:
@CARGO_BUILD_JOBS=$(TEST_BUILD_JOBS) cargo nextest run --no-fail-fast --workspace $(PLATFORM_WORKSPACE_EXCLUDES) --test-threads $(TEST_RUN_THREADS)

test-core: setup
@scripts/maybe-mxrun.sh test-core || $(MAKE) _test_core
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _test_core; else scripts/maybe-mxrun.sh test-core || $(MAKE) _test_core; fi

_test_core:
@CARGO_BUILD_JOBS=$(TEST_BUILD_JOBS) cargo nextest run --no-fail-fast $(foreach pkg,$(CORE_PACKAGE_SPECS),-p $(pkg)) --lib --bins --test-threads $(TEST_RUN_THREADS)

test-modules: setup
@scripts/maybe-mxrun.sh test-modules || $(MAKE) _test_modules
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _test_modules; else scripts/maybe-mxrun.sh test-modules || $(MAKE) _test_modules; fi

_test_modules:
@CARGO_BUILD_JOBS=$(TEST_BUILD_JOBS) cargo nextest run --no-fail-fast $(foreach pkg,$(MODULE_PACKAGE_SPECS),-p $(pkg)) --bins --test-threads $(TEST_RUN_THREADS)

test-sensors: setup
@scripts/maybe-mxrun.sh test-sensors || $(MAKE) _test_sensors
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _test_sensors; else scripts/maybe-mxrun.sh test-sensors || $(MAKE) _test_sensors; fi

_test_sensors:
@CARGO_BUILD_JOBS=$(TEST_BUILD_JOBS) cargo nextest run --no-fail-fast $(foreach pkg,$(SENSOR_PACKAGE_SPECS),-p $(pkg)) --lib --bins --test-threads $(TEST_RUN_THREADS)

test-integration: setup
@scripts/maybe-mxrun.sh test-integration || $(MAKE) _test_integration
@if [ -n "$$SSH_CONNECTION" ]; then $(MAKE) _test_integration; else scripts/maybe-mxrun.sh test-integration || $(MAKE) _test_integration; fi

_test_integration:
@CARGO_BUILD_JOBS=$(TEST_BUILD_JOBS) cargo nextest run --no-fail-fast $(INTEGRATION_TEST_TARGETS) --test-threads $(TEST_RUN_THREADS)
Expand Down
29 changes: 20 additions & 9 deletions libmodpak/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1129,34 +1129,45 @@ impl SysInspectModPak {
self.remove_profile_entry(name)
}

/// Add module or library selectors to the named profile.
pub fn add_profile_matches(&self, name: &str, matches: Vec<String>, library: bool) -> Result<(), SysinspectError> {
/// Add module, model, or library selectors to the named profile.
pub fn add_profile_matches(&self, name: &str, matches: Vec<String>, library: bool, model: bool) -> Result<(), SysinspectError> {
let mut profile = self.get_profile(name)?;
if library {
if model {
profile.add_models(matches);
} else if library {
profile.add_libraries(matches);
} else {
profile.add_modules(matches);
}
self.set_profile(name, &profile)
}

/// Remove module or library selectors from the named profile.
pub fn remove_profile_matches(&self, name: &str, matches: Vec<String>, library: bool) -> Result<(), SysinspectError> {
/// Remove module, model, or library selectors from the named profile.
pub fn remove_profile_matches(&self, name: &str, matches: Vec<String>, library: bool, model: bool) -> Result<(), SysinspectError> {
let mut profile = self.get_profile(name)?;
if library {
if model {
profile.remove_models(matches);
} else if library {
profile.remove_libraries(matches);
} else {
profile.remove_modules(matches);
}
self.set_profile(name, &profile)
}

/// List module or library selectors for profiles matching the optional glob expression.
pub fn list_profile_matches(&self, expr: Option<&str>, library: bool) -> Result<Vec<String>, SysinspectError> {
/// List module, model, or library selectors for profiles matching the optional glob expression.
pub fn list_profile_matches(&self, expr: Option<&str>, library: bool, model: bool) -> Result<Vec<String>, SysinspectError> {
let mut out = Vec::new();
for profile in self.list_profiles(expr)? {
let data = self.get_profile(&profile)?;
for entry in if library { data.libraries() } else { data.modules() } {
let entries: &[String] = if model {
data.models()
} else if library {
data.libraries()
} else {
data.modules()
};
for entry in entries {
out.push(format!("{profile}: {entry}"));
}
}
Expand Down
25 changes: 15 additions & 10 deletions libmodpak/src/lib_ut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,18 +356,23 @@ mod tests {
let repo = SysInspectModPak::new(root.path().join("repo")).expect("repo should be created");

repo.new_profile("toto").expect("profile should be created");
repo.add_profile_matches("toto", vec!["runtime.lua".to_string(), "net.*".to_string()], false).expect("module selectors should be added");
repo.add_profile_matches("toto", vec!["runtime/lua/*.lua".to_string()], true).expect("library selectors should be added");
repo.add_profile_matches("toto", vec!["runtime.lua".to_string(), "net.*".to_string()], false, false)
.expect("module selectors should be added");
repo.add_profile_matches("toto", vec!["runtime/lua/*.lua".to_string()], true, false).expect("library selectors should be added");

assert_eq!(repo.list_profiles(None).expect("profiles should list"), vec!["toto".to_string()]);
assert!(repo.list_profile_matches(Some("toto"), false).expect("profile modules should list").contains(&"toto: runtime.lua".to_string()));
assert!(repo.list_profile_matches(Some("toto"), false).expect("profile modules should list").contains(&"toto: net.*".to_string()));
assert!(
repo.list_profile_matches(Some("toto"), true).expect("profile libraries should list").contains(&"toto: runtime/lua/*.lua".to_string())
repo.list_profile_matches(Some("toto"), false, false).expect("profile modules should list").contains(&"toto: runtime.lua".to_string())
);
assert!(repo.list_profile_matches(Some("toto"), false, false).expect("profile modules should list").contains(&"toto: net.*".to_string()));
assert!(
repo.list_profile_matches(Some("toto"), true, false)
.expect("profile libraries should list")
.contains(&"toto: runtime/lua/*.lua".to_string())
);

repo.remove_profile_matches("toto", vec!["net.*".to_string()], false).expect("module selector should be removed");
assert!(!repo.list_profile_matches(Some("toto"), false).expect("profile modules should list").contains(&"toto: net.*".to_string()));
repo.remove_profile_matches("toto", vec!["net.*".to_string()], false, false).expect("module selector should be removed");
assert!(!repo.list_profile_matches(Some("toto"), false, false).expect("profile modules should list").contains(&"toto: net.*".to_string()));

repo.delete_profile("toto").expect("profile should be deleted");
assert!(repo.list_profiles(None).expect("profiles should list").is_empty());
Expand Down Expand Up @@ -405,7 +410,7 @@ mod tests {
fs::write(root.path().join("profiles.index"), "profiles:\n Toto:\n file: totobullshit.profile\n checksum: deadbeef\n")
.expect("profiles index should be written");

repo.add_profile_matches("Toto", vec!["net.*".to_string()], false).expect("profile should be updated");
repo.add_profile_matches("Toto", vec!["net.*".to_string()], false, false).expect("profile should be updated");

let idx = repo.get_profiles_index().expect("profiles index should load");
let profile = repo.get_profile("Toto").expect("profile should load");
Expand Down Expand Up @@ -446,8 +451,8 @@ mod tests {
write_module(&mut repo, "linux", "x86_64", "runtime.lua", "runtime/lua");
write_module(&mut repo, "netbsd", "noarch", "runtime.lua", "runtime/lua");
repo.new_profile("toto").expect("profile should be created");
repo.add_profile_matches("toto", vec!["runtime.lua".to_string()], false).expect("module selector should be added");
repo.add_profile_matches("toto", vec!["runtime/lua/*.lua".to_string()], true).expect("library selector should be added");
repo.add_profile_matches("toto", vec!["runtime.lua".to_string()], false, false).expect("module selector should be added");
repo.add_profile_matches("toto", vec!["runtime/lua/*.lua".to_string()], true, false).expect("library selector should be added");

let rendered = repo.show_profile("toto").expect("profile should render");
let module_pos = rendered.find("runtime.lua").expect("module row should exist");
Expand Down
21 changes: 21 additions & 0 deletions libmodpak/src/mpk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ impl ModPakProfileRef {
pub struct ModPakProfile {
name: String,
#[serde(default)]
models: Vec<String>,
#[serde(default)]
modules: Vec<String>,
#[serde(default)]
libraries: Vec<String>,
Expand All @@ -201,6 +203,11 @@ impl ModPakProfile {
pub fn libraries(&self) -> &[String] {
&self.libraries
}

/// Return the model identifier list.
pub fn models(&self) -> &[String] {
&self.models
}
}

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
Expand Down Expand Up @@ -340,6 +347,20 @@ impl ModPakProfile {
self.libraries.retain(|library| !libraries.contains(library));
}

/// Add model identifiers, keeping insertion order and skipping duplicates.
pub fn add_models(&mut self, models: Vec<String>) {
for model in models {
if !self.models.contains(&model) {
self.models.push(model);
}
}
}

/// Remove matching model identifiers.
pub fn remove_models(&mut self, models: Vec<String>) {
self.models.retain(|model| !models.contains(model));
}

/// Serialize one profile file to YAML.
pub fn to_yaml(&self) -> Result<String, SysinspectError> {
Ok(serde_yaml::to_string(self)?)
Expand Down
18 changes: 9 additions & 9 deletions libmodpak/tests/profile_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ async fn narrow_profile_syncs_only_allowed_artifacts_and_removes_old_ones() {
set_script_modules(&master.path().join("data/repo"), &["alpha.demo", "beta.demo"]);
repo.new_profile("Alpha").expect("Alpha should be created");
repo.new_profile("Beta").expect("Beta should be created");
repo.add_profile_matches("Alpha", vec!["alpha.demo".to_string()], false).expect("Alpha module selector should be added");
repo.add_profile_matches("Alpha", vec!["runtime/lua/alpha.lua".to_string()], true).expect("Alpha library selector should be added");
repo.add_profile_matches("Beta", vec!["beta.demo".to_string()], false).expect("Beta module selector should be added");
repo.add_profile_matches("Beta", vec!["runtime/lua/beta.lua".to_string()], true).expect("Beta library selector should be added");
repo.add_profile_matches("Alpha", vec!["alpha.demo".to_string()], false, false).expect("Alpha module selector should be added");
repo.add_profile_matches("Alpha", vec!["runtime/lua/alpha.lua".to_string()], true, false).expect("Alpha library selector should be added");
repo.add_profile_matches("Beta", vec!["beta.demo".to_string()], false, false).expect("Beta module selector should be added");
repo.add_profile_matches("Beta", vec!["runtime/lua/beta.lua".to_string()], true, false).expect("Beta library selector should be added");

let (port, server) = start_fileserver(master.path().join("data")).await;
let minion = tempfile::tempdir().expect("minion tempdir should be created");
Expand Down Expand Up @@ -136,8 +136,8 @@ async fn overlapping_multi_profile_sync_merges_by_union_and_dedup() {
set_script_modules(&master.path().join("data/repo"), &["alpha.demo", "beta.demo", "gamma.demo"]);
repo.new_profile("One").expect("One should be created");
repo.new_profile("Two").expect("Two should be created");
repo.add_profile_matches("One", vec!["alpha.demo".to_string(), "beta.demo".to_string()], false).expect("One selectors should be added");
repo.add_profile_matches("Two", vec!["beta.demo".to_string(), "gamma.demo".to_string()], false).expect("Two selectors should be added");
repo.add_profile_matches("One", vec!["alpha.demo".to_string(), "beta.demo".to_string()], false, false).expect("One selectors should be added");
repo.add_profile_matches("Two", vec!["beta.demo".to_string(), "gamma.demo".to_string()], false, false).expect("Two selectors should be added");

let (port, server) = start_fileserver(master.path().join("data")).await;
let minion = tempfile::tempdir().expect("minion tempdir should be created");
Expand Down Expand Up @@ -165,7 +165,7 @@ async fn sync_fails_if_effective_profiles_are_missing_from_profiles_index() {
add_script_module(&master.path().join("data/repo"), "alpha.demo", "# alpha");
set_script_modules(&master.path().join("data/repo"), &["alpha.demo"]);
repo.new_profile("Existing").expect("Existing should be created");
repo.add_profile_matches("Existing", vec!["alpha.demo".to_string()], false).expect("Existing selector should be added");
repo.add_profile_matches("Existing", vec!["alpha.demo".to_string()], false, false).expect("Existing selector should be added");

let (port, server) = start_fileserver(master.path().join("data")).await;
let minion = tempfile::tempdir().expect("minion tempdir should be created");
Expand Down Expand Up @@ -212,7 +212,7 @@ async fn sync_allows_implicit_default_when_profiles_index_has_named_profiles() {
add_script_module(&master.path().join("data/repo"), "alpha.demo", "# alpha");
set_script_modules(&master.path().join("data/repo"), &["alpha.demo"]);
repo.new_profile("Existing").expect("Existing should be created");
repo.add_profile_matches("Existing", vec!["alpha.demo".to_string()], false).expect("Existing selector should be added");
repo.add_profile_matches("Existing", vec!["alpha.demo".to_string()], false, false).expect("Existing selector should be added");

let (port, server) = start_fileserver(master.path().join("data")).await;
let minion = tempfile::tempdir().expect("minion tempdir should be created");
Expand Down Expand Up @@ -258,7 +258,7 @@ async fn sync_fails_if_downloaded_profile_checksum_does_not_match_index() {
add_script_module(&master.path().join("data/repo"), "alpha.demo", "# alpha");
set_script_modules(&master.path().join("data/repo"), &["alpha.demo"]);
repo.new_profile("Broken").expect("Broken should be created");
repo.add_profile_matches("Broken", vec!["alpha.demo".to_string()], false).expect("Broken selector should be added");
repo.add_profile_matches("Broken", vec!["alpha.demo".to_string()], false, false).expect("Broken selector should be added");
fs::write(master.path().join("data/profiles.index"), "profiles:\n Broken:\n file: broken.profile\n checksum: deadbeef\n")
.expect("profiles index should be overwritten");

Expand Down
3 changes: 3 additions & 0 deletions libsysinspect/src/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ pub struct ConsoleModelRow {
/// Public direct action entrypoints exported through `interface.actions`.
#[serde(default)]
pub public_actions: Vec<String>,
/// Deduplicated module ids referenced by the model's actions.
#[serde(default)]
pub modules: Vec<String>,
/// Declared state names across all actions.
#[serde(default)]
pub states: Vec<String>,
Expand Down
7 changes: 7 additions & 0 deletions libsysinspect/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ pub struct ProfileConsoleRequest {
#[serde(default)]
library: bool,
#[serde(default)]
model: bool,
#[serde(default)]
profiles: Vec<String>,
}

Expand Down Expand Up @@ -120,6 +122,11 @@ impl ProfileConsoleRequest {
self.library
}

/// Return whether the request targets model identifiers instead of module selectors.
pub fn model(&self) -> bool {
self.model
}

/// Return the profile names carried by tag or untag requests.
pub fn profiles(&self) -> &[String] {
&self.profiles
Expand Down
1 change: 1 addition & 0 deletions libsysinspect/src/mdescr/browse_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub struct BrowsedModel {
pub public_entrypoints: Vec<BrowsedEntrypoint>,
pub public_actions: Vec<String>,
pub actions: Vec<BrowsedAction>,
pub modules: Vec<String>,
/// Deduplicated list of all declared action state keys.
pub states: Vec<String>,
pub diagnostics: Vec<ModelBrowseDiagnostic>,
Expand Down
9 changes: 9 additions & 0 deletions libsysinspect/src/mdescr/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ impl ModelBrowser {

let (actions, a_diags) = self.actions();
diagnostics.extend(a_diags);
let modules = action_modules(&actions);

let (interface_checkbooks, interface_entities, interface_actions, interface_diags) = self.interface_lists();
diagnostics.extend(interface_diags);
Expand Down Expand Up @@ -538,6 +539,7 @@ impl ModelBrowser {
public_entrypoints,
public_actions,
actions,
modules,
states,
diagnostics,
})
Expand Down Expand Up @@ -604,6 +606,13 @@ impl ModelBrowser {
}
}

fn action_modules(actions: &[BrowsedAction]) -> Vec<String> {
let mut modules: Vec<String> = actions.iter().map(|action| action.module.clone()).filter(|name| !name.trim().is_empty()).collect();
modules.sort();
modules.dedup();
modules
}

/// Convert a serde_yaml Value to a human-readable display string.
fn value_to_display(v: &serde_yaml::Value) -> String {
match v {
Expand Down
Loading
Loading