diff --git a/system-images/compat/src/config/mod.rs b/system-images/compat/src/config/mod.rs index 40070648f..1240f801a 100644 --- a/system-images/compat/src/config/mod.rs +++ b/system-images/compat/src/config/mod.rs @@ -1,10 +1,12 @@ use std::borrow::Cow; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::path::Path; use beau_collector::BeauCollector; use embassy::config::action::SetResult; use embassy::config::{spec, Config}; +use embassy::s9pk::manifest::PackageId; +use embassy::status::health_check::HealthCheckId; use linear_map::LinearMap; pub mod rules; @@ -12,15 +14,39 @@ pub mod rules; use anyhow::anyhow; pub use rules::{ConfigRuleEntry, ConfigRuleEntryWithSuggestions}; +use self::rules::ConfigRule; +pub type DepInfo = HashMap; +#[derive(Clone, Debug, serde::Deserialize)] +pub struct DepRuleInfo { + condition: ConfigRule, + health_checks: BTreeSet, +} + pub fn validate_configuration( name: &str, config: Config, rules_path: &Path, config_path: &Path, + maybe_deps_path: Option<&str>, ) -> Result { let rules: Vec = serde_yaml::from_reader(std::fs::File::open(rules_path)?)?; let mut cfgs = LinearMap::new(); cfgs.insert(name, Cow::Borrowed(&config)); + + let mut depends_on = BTreeMap::new(); + if let Some(deps_path) = maybe_deps_path.map(Path::new) { + if deps_path.exists() { + let deps: DepInfo = serde_yaml::from_reader(std::fs::File::open(deps_path)?)?; + // check if new config is set to depend on any optional dependencies + depends_on.extend( + deps.into_iter() + .filter(|(_, data)| (data.condition.compiled)(&config, &cfgs)) + .map(|(pkg_id, data)| (pkg_id, data.health_checks)), + ); + }; + } + + // check that all configuration rules let rule_check = rules .into_iter() .map(|r| r.check(&config, &cfgs)) @@ -35,7 +61,7 @@ pub fn validate_configuration( std::fs::rename(config_path.with_extension("tmp"), config_path)?; // return set result Ok(SetResult { - depends_on: BTreeMap::new(), + depends_on, // sending sigterm so service is restarted - in 0.3.x services, this is whatever signal is needed to send to the process to pick up the configuration signal: Some(nix::sys::signal::SIGTERM), }) diff --git a/system-images/compat/src/main.rs b/system-images/compat/src/main.rs index 9015b803c..dcd723882 100644 --- a/system-images/compat/src/main.rs +++ b/system-images/compat/src/main.rs @@ -74,6 +74,10 @@ fn inner_main() -> Result<(), anyhow::Error> { Arg::with_name("assets") .help("Path to the rules file") .required(true), + ) + .arg( + Arg::with_name("dependencies") + .help("Path to rules for optional dependency config") ), ), ) @@ -190,11 +194,13 @@ fn inner_main() -> Result<(), anyhow::Error> { }; let rules_path = Path::new(sub_m.value_of("assets").unwrap()); let name = sub_m.value_of("package_id").unwrap(); + let deps_path = sub_m.value_of("dependencies"); match validate_configuration( &name, config, rules_path, &cfg_path.join("config.yaml"), + deps_path, ) { Ok(a) => { serde_yaml::to_writer(stdout(), &a)?; @@ -304,7 +310,7 @@ fn inner_main() -> Result<(), anyhow::Error> { let stats: serde_json::Value = if stats_path.exists() { serde_yaml::from_reader(File::open(stats_path).unwrap()).unwrap() } else { - let fallbackMessage: &str = sub_m + let fallback_message: &str = sub_m .value_of("fallbackMessage") .unwrap_or_else(|| PROPERTIES_FALLBACK_MESSAGE); json!({ @@ -312,7 +318,7 @@ fn inner_main() -> Result<(), anyhow::Error> { "data": { "Not Ready": { "type": "string", - "value": fallbackMessage, + "value": fallback_message, "qr": false, "copyable": false, "masked": false,