From a086c809e499e81372031a72b395ebbe45e5363c Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Tue, 21 Sep 2021 15:17:26 -0600 Subject: [PATCH] splits out types for different package pointers --- appmgr/src/config/mod.rs | 15 +-- appmgr/src/config/spec.rs | 226 +++++++++++++++++++++----------------- appmgr/src/db/model.rs | 4 +- 3 files changed, 135 insertions(+), 110 deletions(-) diff --git a/appmgr/src/config/mod.rs b/appmgr/src/config/mod.rs index 483dae9c0..0dc3746ba 100644 --- a/appmgr/src/config/mod.rs +++ b/appmgr/src/config/mod.rs @@ -13,7 +13,6 @@ use rpc_toolkit::command; use serde_json::Value; use crate::action::docker::DockerAction; -use crate::config::spec::PackagePointerSpecVariant; use crate::context::RpcContext; use crate::db::model::{ CurrentDependencyInfo, InstalledPackageDataEntry, InstalledPackageDataEntryModel, @@ -346,14 +345,16 @@ pub fn configure<'a, Db: DbHandle>( .collect(); for ptr in spec.pointers(&config)? { match ptr { - ValueSpecPointer::Package(PackagePointerSpec { package_id, target }) => { - if let Some(current_dependency) = current_dependencies.get_mut(&package_id) { - current_dependency.pointers.push(target); + ValueSpecPointer::Package(pkg_ptr) => { + if let Some(current_dependency) = + current_dependencies.get_mut(pkg_ptr.package_id()) + { + current_dependency.pointers.push(pkg_ptr); } else { current_dependencies.insert( - package_id, + pkg_ptr.package_id().to_owned(), CurrentDependencyInfo { - pointers: vec![target], + pointers: vec![pkg_ptr], health_checks: BTreeSet::new(), }, ); @@ -448,7 +449,7 @@ pub fn configure<'a, Db: DbHandle>( // handle backreferences for ptr in &dep_info.pointers { - if let PackagePointerSpecVariant::Config(cfg_ptr) = ptr { + if let PackagePointerSpec::Config(cfg_ptr) = ptr { if cfg_ptr.select(&next) != cfg_ptr.select(&prev) { if let Err(e) = configure( ctx, db, dependent, None, timeout, dry_run, overrides, breakages, diff --git a/appmgr/src/config/spec.rs b/appmgr/src/config/spec.rs index c8ff6a3a9..94c3bc29e 100644 --- a/appmgr/src/config/spec.rs +++ b/appmgr/src/config/spec.rs @@ -12,6 +12,7 @@ use async_trait::async_trait; use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; use jsonpath_lib::Compiled as CompiledJsonPath; +use lazy_static::__Deref; use patch_db::{DbHandle, OptionModel}; use rand::{CryptoRng, Rng}; use regex::Regex; @@ -1501,93 +1502,40 @@ impl ValueSpec for ValueSpecPointer { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(tag = "target")] #[serde(rename_all = "kebab-case")] -pub struct PackagePointerSpec { - pub package_id: PackageId, - #[serde(flatten)] - pub target: PackagePointerSpecVariant, -} -impl fmt::Display for PackagePointerSpec { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}: {}", self.package_id, self.target) - } +pub enum PackagePointerSpec { + TorAddress(TorAddressPointer), + LanAddress(LanAddressPointer), + Config(ConfigPointer), } impl PackagePointerSpec { + pub fn package_id(&self) -> &PackageId { + match self { + PackagePointerSpec::TorAddress(TorAddressPointer { package_id, .. }) => package_id, + PackagePointerSpec::LanAddress(LanAddressPointer { package_id, .. }) => package_id, + PackagePointerSpec::Config(ConfigPointer { package_id, .. }) => package_id, + } + } async fn deref( &self, ctx: &RpcContext, db: &mut Db, config_overrides: &BTreeMap, ) -> Result { - match &self.target { - PackagePointerSpecVariant::Tor(TorAddressPointer { interface }) => { - let addr = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&self.package_id) - .and_then(|pde| pde.installed()) - .and_then(|installed| installed.interface_addresses().idx_model(interface)) - .and_then(|addresses| addresses.tor_address()) - .get(db, true) - .await - .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; - Ok(addr.to_owned().map(Value::String).unwrap_or(Value::Null)) - } - PackagePointerSpecVariant::Lan(LanAddressPointer { interface }) => { - let addr = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&self.package_id) - .and_then(|pde| pde.installed()) - .and_then(|installed| installed.interface_addresses().idx_model(interface)) - .and_then(|addresses| addresses.lan_address()) - .get(db, true) - .await - .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; - Ok(addr.to_owned().map(Value::String).unwrap_or(Value::Null)) - } - PackagePointerSpecVariant::Config(ConfigPointer { selector, multi }) => { - if let Some(cfg) = config_overrides.get(&self.package_id) { - Ok(selector.select(*multi, &Value::Object(cfg.clone()))) - } else { - let manifest_model: OptionModel = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&self.package_id) - .and_then(|pde| pde.installed()) - .map(|installed| installed.manifest()) - .into(); - let version = manifest_model - .clone() - .map(|manifest| manifest.version()) - .get(db, true) - .await - .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; - let cfg_actions = manifest_model - .clone() - .and_then(|manifest| manifest.config()) - .get(db, true) - .await - .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; - let volumes = manifest_model - .map(|manifest| manifest.volumes()) - .get(db, true) - .await - .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; - if let (Some(version), Some(cfg_actions), Some(volumes)) = - (&*version, &*cfg_actions, &*volumes) - { - let cfg_res = cfg_actions - .get(&ctx, &self.package_id, version, volumes) - .await - .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; - if let Some(cfg) = cfg_res.config { - Ok(selector.select(*multi, &Value::Object(cfg))) - } else { - Ok(Value::Null) - } - } else { - Ok(Value::Null) - } - } - } + match &self { + PackagePointerSpec::TorAddress(tor) => tor.deref(db).await, + PackagePointerSpec::LanAddress(lan) => lan.deref(db).await, + PackagePointerSpec::Config(cfg) => cfg.deref(ctx, db, config_overrides).await, + } + } +} +impl fmt::Display for PackagePointerSpec { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + PackagePointerSpec::TorAddress(tor) => write!(f, "{}", tor), + PackagePointerSpec::LanAddress(lan) => write!(f, "{}", lan), + PackagePointerSpec::Config(cfg) => write!(f, "{}", cfg), } } } @@ -1607,13 +1555,14 @@ impl ValueSpec for PackagePointerSpec { Ok(()) } fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> { - if manifest.id != self.package_id && !manifest.dependencies.0.contains_key(&self.package_id) + if &manifest.id != self.package_id() + && !manifest.dependencies.0.contains_key(self.package_id()) { return Err(NoMatchWithPath::new(MatchError::InvalidPointer( ValueSpecPointer::Package(self.clone()), ))); } - match self.target { + match self { _ => Ok(()), } } @@ -1633,7 +1582,7 @@ impl ValueSpec for PackagePointerSpec { Ok(pointers) } fn requires(&self, id: &PackageId, _value: &Value) -> bool { - &self.package_id == id + self.package_id() == id } fn eq(&self, _lhs: &Value, _rhs: &Value) -> bool { false @@ -1641,48 +1590,70 @@ impl ValueSpec for PackagePointerSpec { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(tag = "target")] #[serde(rename_all = "kebab-case")] -pub enum PackagePointerSpecVariant { - Tor(TorAddressPointer), - Lan(LanAddressPointer), - Config(ConfigPointer), -} -impl fmt::Display for PackagePointerSpecVariant { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Self::Tor(tor) => write!(f, "{}", tor), - Self::Lan(lan) => write!(f, "{}", lan), - Self::Config(cfg) => write!(f, "{}", cfg), - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct TorAddressPointer { + package_id: PackageId, interface: InterfaceId, } +impl TorAddressPointer { + async fn deref(&self, db: &mut Db) -> Result { + let addr = crate::db::DatabaseModel::new() + .package_data() + .idx_model(&self.package_id) + .and_then(|pde| pde.installed()) + .and_then(|installed| installed.interface_addresses().idx_model(&self.interface)) + .and_then(|addresses| addresses.tor_address()) + .get(db, true) + .await + .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; + Ok(addr.to_owned().map(Value::String).unwrap_or(Value::Null)) + } +} impl fmt::Display for TorAddressPointer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - TorAddressPointer { interface } => write!(f, "tor-address: {}", interface), + TorAddressPointer { + package_id, + interface, + } => write!(f, "{}: tor-address: {}", package_id, interface), } } } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] pub struct LanAddressPointer { + package_id: PackageId, interface: InterfaceId, } impl fmt::Display for LanAddressPointer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - LanAddressPointer { interface } => write!(f, "lan-address: {}", interface), + LanAddressPointer { + package_id, + interface, + } => write!(f, "{}: lan-address: {}", package_id, interface), } } } +impl LanAddressPointer { + async fn deref(&self, db: &mut Db) -> Result { + let addr = crate::db::DatabaseModel::new() + .package_data() + .idx_model(&self.package_id) + .and_then(|pde| pde.installed()) + .and_then(|installed| installed.interface_addresses().idx_model(&self.interface)) + .and_then(|addresses| addresses.lan_address()) + .get(db, true) + .await + .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; + Ok(addr.to_owned().map(Value::String).unwrap_or(Value::Null)) + } +} #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] pub struct ConfigPointer { + package_id: PackageId, selector: Arc, multi: bool, } @@ -1690,11 +1661,64 @@ impl ConfigPointer { pub fn select(&self, val: &Value) -> Value { self.selector.select(self.multi, val) } + async fn deref( + &self, + ctx: &RpcContext, + db: &mut Db, + config_overrides: &BTreeMap, + ) -> Result { + if let Some(cfg) = config_overrides.get(&self.package_id) { + Ok(self.select(&Value::Object(cfg.clone()))) + } else { + let manifest_model: OptionModel<_> = crate::db::DatabaseModel::new() + .package_data() + .idx_model(&self.package_id) + .and_then(|pde| pde.installed()) + .map(|installed| installed.manifest()) + .into(); + let version = manifest_model + .clone() + .map(|manifest| manifest.version()) + .get(db, true) + .await + .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; + let cfg_actions = manifest_model + .clone() + .and_then(|manifest| manifest.config()) + .get(db, true) + .await + .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; + let volumes = manifest_model + .map(|manifest| manifest.volumes()) + .get(db, true) + .await + .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; + if let (Some(version), Some(cfg_actions), Some(volumes)) = + (&*version, &*cfg_actions, &*volumes) + { + let cfg_res = cfg_actions + .get(&ctx, &self.package_id, version, volumes) + .await + .map_err(|e| ConfigurationError::SystemError(Error::from(e)))?; + if let Some(cfg) = cfg_res.config { + Ok(self.select(&Value::Object(cfg))) + } else { + Ok(Value::Null) + } + } else { + Ok(Value::Null) + } + } + } } impl fmt::Display for ConfigPointer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - ConfigPointer { selector, .. } => write!(f, "config: {}", selector), + ConfigPointer { + package_id, + selector, + .. + } => write!(f, "{}: config: {}", package_id, selector), } } } diff --git a/appmgr/src/db/model.rs b/appmgr/src/db/model.rs index 087e081e0..9d2c47a9d 100644 --- a/appmgr/src/db/model.rs +++ b/appmgr/src/db/model.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use torut::onion::TorSecretKeyV3; -use crate::config::spec::{PackagePointerSpecVariant, SystemPointerSpec}; +use crate::config::spec::{PackagePointerSpec, SystemPointerSpec}; use crate::install::progress::InstallProgress; use crate::net::interface::InterfaceId; use crate::s9pk::manifest::{Manifest, ManifestModel, PackageId}; @@ -235,7 +235,7 @@ pub struct StaticDependencyInfo { #[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] pub struct CurrentDependencyInfo { - pub pointers: Vec, + pub pointers: Vec, pub health_checks: BTreeSet, }