mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
splits out types for different package pointers
This commit is contained in:
committed by
Aiden McClelland
parent
bed4c92b26
commit
4c29d8c372
@@ -13,7 +13,6 @@ use rpc_toolkit::command;
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::action::docker::DockerAction;
|
use crate::action::docker::DockerAction;
|
||||||
use crate::config::spec::PackagePointerSpecVariant;
|
|
||||||
use crate::context::RpcContext;
|
use crate::context::RpcContext;
|
||||||
use crate::db::model::{
|
use crate::db::model::{
|
||||||
CurrentDependencyInfo, InstalledPackageDataEntry, InstalledPackageDataEntryModel,
|
CurrentDependencyInfo, InstalledPackageDataEntry, InstalledPackageDataEntryModel,
|
||||||
@@ -346,14 +345,16 @@ pub fn configure<'a, Db: DbHandle>(
|
|||||||
.collect();
|
.collect();
|
||||||
for ptr in spec.pointers(&config)? {
|
for ptr in spec.pointers(&config)? {
|
||||||
match ptr {
|
match ptr {
|
||||||
ValueSpecPointer::Package(PackagePointerSpec { package_id, target }) => {
|
ValueSpecPointer::Package(pkg_ptr) => {
|
||||||
if let Some(current_dependency) = current_dependencies.get_mut(&package_id) {
|
if let Some(current_dependency) =
|
||||||
current_dependency.pointers.push(target);
|
current_dependencies.get_mut(pkg_ptr.package_id())
|
||||||
|
{
|
||||||
|
current_dependency.pointers.push(pkg_ptr);
|
||||||
} else {
|
} else {
|
||||||
current_dependencies.insert(
|
current_dependencies.insert(
|
||||||
package_id,
|
pkg_ptr.package_id().to_owned(),
|
||||||
CurrentDependencyInfo {
|
CurrentDependencyInfo {
|
||||||
pointers: vec![target],
|
pointers: vec![pkg_ptr],
|
||||||
health_checks: BTreeSet::new(),
|
health_checks: BTreeSet::new(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -448,7 +449,7 @@ pub fn configure<'a, Db: DbHandle>(
|
|||||||
|
|
||||||
// handle backreferences
|
// handle backreferences
|
||||||
for ptr in &dep_info.pointers {
|
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 cfg_ptr.select(&next) != cfg_ptr.select(&prev) {
|
||||||
if let Err(e) = configure(
|
if let Err(e) = configure(
|
||||||
ctx, db, dependent, None, timeout, dry_run, overrides, breakages,
|
ctx, db, dependent, None, timeout, dry_run, overrides, breakages,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use async_trait::async_trait;
|
|||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use jsonpath_lib::Compiled as CompiledJsonPath;
|
use jsonpath_lib::Compiled as CompiledJsonPath;
|
||||||
|
use lazy_static::__Deref;
|
||||||
use patch_db::{DbHandle, OptionModel};
|
use patch_db::{DbHandle, OptionModel};
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
@@ -1501,93 +1502,40 @@ impl ValueSpec for ValueSpecPointer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "target")]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct PackagePointerSpec {
|
pub enum PackagePointerSpec {
|
||||||
pub package_id: PackageId,
|
TorAddress(TorAddressPointer),
|
||||||
#[serde(flatten)]
|
LanAddress(LanAddressPointer),
|
||||||
pub target: PackagePointerSpecVariant,
|
Config(ConfigPointer),
|
||||||
}
|
|
||||||
impl fmt::Display for PackagePointerSpec {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}: {}", self.package_id, self.target)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl PackagePointerSpec {
|
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<Db: DbHandle>(
|
async fn deref<Db: DbHandle>(
|
||||||
&self,
|
&self,
|
||||||
ctx: &RpcContext,
|
ctx: &RpcContext,
|
||||||
db: &mut Db,
|
db: &mut Db,
|
||||||
config_overrides: &BTreeMap<PackageId, Config>,
|
config_overrides: &BTreeMap<PackageId, Config>,
|
||||||
) -> Result<Value, ConfigurationError> {
|
) -> Result<Value, ConfigurationError> {
|
||||||
match &self.target {
|
match &self {
|
||||||
PackagePointerSpecVariant::Tor(TorAddressPointer { interface }) => {
|
PackagePointerSpec::TorAddress(tor) => tor.deref(db).await,
|
||||||
let addr = crate::db::DatabaseModel::new()
|
PackagePointerSpec::LanAddress(lan) => lan.deref(db).await,
|
||||||
.package_data()
|
PackagePointerSpec::Config(cfg) => cfg.deref(ctx, db, config_overrides).await,
|
||||||
.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())
|
impl fmt::Display for PackagePointerSpec {
|
||||||
.get(db, true)
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
.await
|
match self {
|
||||||
.map_err(|e| ConfigurationError::SystemError(Error::from(e)))?;
|
PackagePointerSpec::TorAddress(tor) => write!(f, "{}", tor),
|
||||||
Ok(addr.to_owned().map(Value::String).unwrap_or(Value::Null))
|
PackagePointerSpec::LanAddress(lan) => write!(f, "{}", lan),
|
||||||
}
|
PackagePointerSpec::Config(cfg) => write!(f, "{}", cfg),
|
||||||
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<Manifest> = 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1607,13 +1555,14 @@ impl ValueSpec for PackagePointerSpec {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> {
|
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(
|
return Err(NoMatchWithPath::new(MatchError::InvalidPointer(
|
||||||
ValueSpecPointer::Package(self.clone()),
|
ValueSpecPointer::Package(self.clone()),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
match self.target {
|
match self {
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1633,7 +1582,7 @@ impl ValueSpec for PackagePointerSpec {
|
|||||||
Ok(pointers)
|
Ok(pointers)
|
||||||
}
|
}
|
||||||
fn requires(&self, id: &PackageId, _value: &Value) -> bool {
|
fn requires(&self, id: &PackageId, _value: &Value) -> bool {
|
||||||
&self.package_id == id
|
self.package_id() == id
|
||||||
}
|
}
|
||||||
fn eq(&self, _lhs: &Value, _rhs: &Value) -> bool {
|
fn eq(&self, _lhs: &Value, _rhs: &Value) -> bool {
|
||||||
false
|
false
|
||||||
@@ -1641,48 +1590,70 @@ impl ValueSpec for PackagePointerSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
#[serde(tag = "target")]
|
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[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 {
|
pub struct TorAddressPointer {
|
||||||
|
package_id: PackageId,
|
||||||
interface: InterfaceId,
|
interface: InterfaceId,
|
||||||
}
|
}
|
||||||
|
impl TorAddressPointer {
|
||||||
|
async fn deref<Db: DbHandle>(&self, db: &mut Db) -> Result<Value, ConfigurationError> {
|
||||||
|
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 {
|
impl fmt::Display for TorAddressPointer {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct LanAddressPointer {
|
pub struct LanAddressPointer {
|
||||||
|
package_id: PackageId,
|
||||||
interface: InterfaceId,
|
interface: InterfaceId,
|
||||||
}
|
}
|
||||||
impl fmt::Display for LanAddressPointer {
|
impl fmt::Display for LanAddressPointer {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
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<Db: DbHandle>(&self, db: &mut Db) -> Result<Value, ConfigurationError> {
|
||||||
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct ConfigPointer {
|
pub struct ConfigPointer {
|
||||||
|
package_id: PackageId,
|
||||||
selector: Arc<ConfigSelector>,
|
selector: Arc<ConfigSelector>,
|
||||||
multi: bool,
|
multi: bool,
|
||||||
}
|
}
|
||||||
@@ -1690,11 +1661,64 @@ impl ConfigPointer {
|
|||||||
pub fn select(&self, val: &Value) -> Value {
|
pub fn select(&self, val: &Value) -> Value {
|
||||||
self.selector.select(self.multi, val)
|
self.selector.select(self.multi, val)
|
||||||
}
|
}
|
||||||
|
async fn deref<Db: DbHandle>(
|
||||||
|
&self,
|
||||||
|
ctx: &RpcContext,
|
||||||
|
db: &mut Db,
|
||||||
|
config_overrides: &BTreeMap<PackageId, Config>,
|
||||||
|
) -> Result<Value, ConfigurationError> {
|
||||||
|
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 {
|
impl fmt::Display for ConfigPointer {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ConfigPointer { selector, .. } => write!(f, "config: {}", selector),
|
ConfigPointer {
|
||||||
|
package_id,
|
||||||
|
selector,
|
||||||
|
..
|
||||||
|
} => write!(f, "{}: config: {}", package_id, selector),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use torut::onion::TorSecretKeyV3;
|
use torut::onion::TorSecretKeyV3;
|
||||||
|
|
||||||
use crate::config::spec::{PackagePointerSpecVariant, SystemPointerSpec};
|
use crate::config::spec::{PackagePointerSpec, SystemPointerSpec};
|
||||||
use crate::install::progress::InstallProgress;
|
use crate::install::progress::InstallProgress;
|
||||||
use crate::net::interface::InterfaceId;
|
use crate::net::interface::InterfaceId;
|
||||||
use crate::s9pk::manifest::{Manifest, ManifestModel, PackageId};
|
use crate::s9pk::manifest::{Manifest, ManifestModel, PackageId};
|
||||||
@@ -235,7 +235,7 @@ pub struct StaticDependencyInfo {
|
|||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
|
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct CurrentDependencyInfo {
|
pub struct CurrentDependencyInfo {
|
||||||
pub pointers: Vec<PackagePointerSpecVariant>,
|
pub pointers: Vec<PackagePointerSpec>,
|
||||||
pub health_checks: BTreeSet<HealthCheckId>,
|
pub health_checks: BTreeSet<HealthCheckId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user