From 5c2564477e17da8555b7f0c5e2dbea4e9d19fd3f Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 27 Sep 2021 15:28:33 -0600 Subject: [PATCH 1/6] fix locker issues --- appmgr/src/action/mod.rs | 14 ++++++++++---- appmgr/src/manager/mod.rs | 6 ++++-- appmgr/src/status/mod.rs | 2 ++ patch-db | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/appmgr/src/action/mod.rs b/appmgr/src/action/mod.rs index 4ddd40794..d4a1e375f 100644 --- a/appmgr/src/action/mod.rs +++ b/appmgr/src/action/mod.rs @@ -13,7 +13,9 @@ use crate::config::{Config, ConfigSpec}; use crate::context::RpcContext; use crate::id::{Id, InvalidId}; use crate::s9pk::manifest::PackageId; -use crate::util::{IoFormat, ValuePrimative, Version, display_serializable, parse_stdin_deserializable}; +use crate::util::{ + display_serializable, parse_stdin_deserializable, IoFormat, ValuePrimative, Version, +}; use crate::volume::Volumes; use crate::{Error, ResultExt}; @@ -80,7 +82,7 @@ pub enum ActionResult { #[derive(Debug, Serialize, Deserialize)] pub struct ActionResultV0 { pub message: String, - pub value: ValuePrimative, + pub value: Option, pub copyable: bool, pub qr: bool, } @@ -183,8 +185,12 @@ fn display_action_result(action_result: ActionResult, matches: &ArgMatches<'_>) } match action_result { ActionResult::V0(ar) => { - println!("{}: {}", ar.message, serde_json::to_string(&ar.value).unwrap()); - }, + println!( + "{}: {}", + ar.message, + serde_json::to_string(&ar.value).unwrap() + ); + } } } diff --git a/appmgr/src/manager/mod.rs b/appmgr/src/manager/mod.rs index fcd8c1fc0..eb0960fc2 100644 --- a/appmgr/src/manager/mod.rs +++ b/appmgr/src/manager/mod.rs @@ -351,7 +351,8 @@ impl Manager { .await { Err(bollard::errors::Error::DockerResponseNotFoundError { .. }) - | Err(bollard::errors::Error::DockerResponseConflictError { .. }) => (), // Already stopped + | Err(bollard::errors::Error::DockerResponseConflictError { .. }) + | Err(bollard::errors::Error::DockerResponseNotModifiedError { .. }) => (), // Already stopped a => a?, }; self.shared.status.store( @@ -413,7 +414,8 @@ impl Manager { .await { Err(bollard::errors::Error::DockerResponseNotFoundError { .. }) - | Err(bollard::errors::Error::DockerResponseConflictError { .. }) => (), + | Err(bollard::errors::Error::DockerResponseConflictError { .. }) + | Err(bollard::errors::Error::DockerResponseNotModifiedError { .. }) => (), // Already stopped a => a?, }; self.shared.status.store( diff --git a/appmgr/src/status/mod.rs b/appmgr/src/status/mod.rs index 0c3e45e60..85bee780a 100644 --- a/appmgr/src/status/mod.rs +++ b/appmgr/src/status/mod.rs @@ -301,7 +301,9 @@ impl MainStatus { }, ManagerStatus::Running => match self { MainStatus::Stopped | MainStatus::Stopping | MainStatus::Restoring { .. } => { + dbg!("stopping"); manager.stop().await?; + dbg!("stopped"); } MainStatus::Running { .. } => (), MainStatus::BackingUp { .. } => { diff --git a/patch-db b/patch-db index 96ab78f8b..d26e1563e 160000 --- a/patch-db +++ b/patch-db @@ -1 +1 @@ -Subproject commit 96ab78f8b0c560f50c3c59ae61a1b151a751076d +Subproject commit d26e1563e87a7a59d328176b810429ab4056cb17 From 65e4fb5dc406953c269a5ea4127f60936eb199fc Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 27 Sep 2021 15:44:27 -0600 Subject: [PATCH 2/6] clean out dbgs --- appmgr/src/middleware/encrypt.rs | 2 +- appmgr/src/status/mod.rs | 2 -- appmgr/src/volume.rs | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/appmgr/src/middleware/encrypt.rs b/appmgr/src/middleware/encrypt.rs index 2153d2b7a..6a8a3ab2b 100644 --- a/appmgr/src/middleware/encrypt.rs +++ b/appmgr/src/middleware/encrypt.rs @@ -75,7 +75,7 @@ impl Stream for DecryptStream { aeskey.as_mut_slice(), ); let ctr = Nonce::::from_slice(&this.ctr); - let mut aes = Aes256Ctr::new(dbg!(&aeskey), dbg!(&ctr)); + let mut aes = Aes256Ctr::new(&aeskey, &ctr); let mut res = buf.to_vec(); aes.apply_keystream(&mut res); *this.aes = Some(aes); diff --git a/appmgr/src/status/mod.rs b/appmgr/src/status/mod.rs index 85bee780a..0c3e45e60 100644 --- a/appmgr/src/status/mod.rs +++ b/appmgr/src/status/mod.rs @@ -301,9 +301,7 @@ impl MainStatus { }, ManagerStatus::Running => match self { MainStatus::Stopped | MainStatus::Stopping | MainStatus::Restoring { .. } => { - dbg!("stopping"); manager.stop().await?; - dbg!("stopped"); } MainStatus::Running { .. } => (), MainStatus::BackingUp { .. } => { diff --git a/appmgr/src/volume.rs b/appmgr/src/volume.rs index 8cd68d519..5e38ed1fb 100644 --- a/appmgr/src/volume.rs +++ b/appmgr/src/volume.rs @@ -200,7 +200,7 @@ impl Volume { volume_id, path, .. - } => dbg!(ctx + } => ctx .datadir .join(PKG_VOLUME_DIR) .join(package_id) @@ -210,7 +210,7 @@ impl Volume { path.strip_prefix("/").unwrap() } else { path.as_ref() - })), + }), Volume::Certificate { interface_id } => ctx .datadir .join(PKG_VOLUME_DIR) From 72cc6b1b2a439f96c646785977e4fc6b08f2bf4a Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 27 Sep 2021 16:23:24 -0600 Subject: [PATCH 3/6] change dependency requirement structure --- appmgr/src/config/mod.rs | 2 +- appmgr/src/dependencies.rs | 17 +++++++++++++++-- appmgr/src/install/mod.rs | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/appmgr/src/config/mod.rs b/appmgr/src/config/mod.rs index 8a8b829ba..c4c4462ea 100644 --- a/appmgr/src/config/mod.rs +++ b/appmgr/src/config/mod.rs @@ -336,7 +336,7 @@ pub fn configure<'a, Db: DbHandle>( .0 .iter() .filter_map(|(id, info)| { - if info.optional.is_none() { + if info.requirement.required() { Some((id.clone(), CurrentDependencyInfo::default())) } else { None diff --git a/appmgr/src/dependencies.rs b/appmgr/src/dependencies.rs index f8a080506..d762b5f81 100644 --- a/appmgr/src/dependencies.rs +++ b/appmgr/src/dependencies.rs @@ -116,12 +116,25 @@ impl HasModel for Dependencies { type Model = MapModel; } +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +#[serde(tag = "type")] +pub enum DependencyRequirement { + OptIn { how: String }, + OptOut { how: String }, + Required, +} +impl DependencyRequirement { + pub fn required(&self) -> bool { + matches!(self, &DependencyRequirement::Required) + } +} + #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] pub struct DepInfo { pub version: VersionRange, - pub optional: Option, - pub recommended: bool, + pub requirement: DependencyRequirement, pub description: Option, pub critical: bool, #[serde(default)] diff --git a/appmgr/src/install/mod.rs b/appmgr/src/install/mod.rs index 84e88615f..935eab1ce 100644 --- a/appmgr/src/install/mod.rs +++ b/appmgr/src/install/mod.rs @@ -532,7 +532,7 @@ pub async fn install_s9pk( .0 .iter() .filter_map(|(id, info)| { - if info.optional.is_none() { + if info.requirement.required() { Some((id.clone(), CurrentDependencyInfo::default())) } else { None From 800bf8dbde290df9b7526f679f1f74bd506fe8f5 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 27 Sep 2021 17:19:58 -0600 Subject: [PATCH 4/6] use btreemap instead of indexmap to establish canonical lock ordering --- appmgr/Cargo.lock | 59 ++++++++++++++++- appmgr/Cargo.toml | 1 + appmgr/src/action/docker.rs | 4 +- appmgr/src/action/mod.rs | 11 ++-- appmgr/src/auth.rs | 4 +- appmgr/src/config/action.rs | 5 +- appmgr/src/config/mod.rs | 19 +++--- appmgr/src/config/spec.rs | 101 ++++++++---------------------- appmgr/src/control.rs | 5 +- appmgr/src/db/model.rs | 14 ++--- appmgr/src/dependencies.rs | 11 ++-- appmgr/src/disk/util.rs | 7 ++- appmgr/src/id.rs | 4 +- appmgr/src/install/mod.rs | 11 ++-- appmgr/src/net/interface.rs | 14 ++--- appmgr/src/net/nginx.rs | 6 +- appmgr/src/s9pk/manifest.rs | 2 +- appmgr/src/status/health_check.rs | 8 +-- appmgr/src/status/mod.rs | 23 ++++--- appmgr/src/util/mod.rs | 65 ++++++++++++++++++- appmgr/src/volume.rs | 8 +-- patch-db | 2 +- 22 files changed, 228 insertions(+), 156 deletions(-) diff --git a/appmgr/Cargo.lock b/appmgr/Cargo.lock index 084d50f46..b52d2a2b0 100644 --- a/appmgr/Cargo.lock +++ b/appmgr/Cargo.lock @@ -788,6 +788,7 @@ dependencies = [ "libc", "log", "nix 0.22.1", + "num", "openssh-keys", "openssl", "patch-db", @@ -1728,6 +1729,40 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +dependencies = [ + "num-traits", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -1738,6 +1773,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.14" @@ -1868,7 +1926,6 @@ dependencies = [ "async-trait", "fd-lock-rs", "futures", - "indexmap", "json-patch", "json-ptr", "lazy_static", diff --git a/appmgr/Cargo.toml b/appmgr/Cargo.toml index 89e128052..da6210189 100644 --- a/appmgr/Cargo.toml +++ b/appmgr/Cargo.toml @@ -73,6 +73,7 @@ lazy_static = "1.4" libc = "0.2.103" log = "0.4.14" nix = "0.22.1" +num = "0.4.0" openssh-keys = "0.5.0" openssl = { version = "0.10.36", features = ["vendored"] } patch-db = { version = "*", path = "../patch-db/patch-db", features = ["log"] } diff --git a/appmgr/src/action/docker.rs b/appmgr/src/action/docker.rs index 1adaf9052..3c49acd95 100644 --- a/appmgr/src/action/docker.rs +++ b/appmgr/src/action/docker.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; +use std::collections::BTreeMap; use std::ffi::{OsStr, OsString}; use std::net::Ipv4Addr; use std::path::PathBuf; -use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -26,7 +26,7 @@ pub struct DockerAction { #[serde(default)] pub args: Vec, #[serde(default)] - pub mounts: IndexMap, + pub mounts: BTreeMap, #[serde(default)] pub io_format: Option, #[serde(default)] diff --git a/appmgr/src/action/mod.rs b/appmgr/src/action/mod.rs index d4a1e375f..b11d1f960 100644 --- a/appmgr/src/action/mod.rs +++ b/appmgr/src/action/mod.rs @@ -1,9 +1,10 @@ +use std::collections::BTreeMap; use std::path::Path; use std::str::FromStr; use anyhow::anyhow; use clap::ArgMatches; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexSet; use patch_db::HasModel; use rpc_toolkit::command; use serde::{Deserialize, Serialize}; @@ -13,9 +14,7 @@ use crate::config::{Config, ConfigSpec}; use crate::context::RpcContext; use crate::id::{Id, InvalidId}; use crate::s9pk::manifest::PackageId; -use crate::util::{ - display_serializable, parse_stdin_deserializable, IoFormat, ValuePrimative, Version, -}; +use crate::util::{display_serializable, parse_stdin_deserializable, IoFormat, Version}; use crate::volume::Volumes; use crate::{Error, ResultExt}; @@ -23,7 +22,7 @@ pub mod docker; // TODO: create RPC endpoint that looks up the appropriate action and calls `execute` -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct ActionId = String>(Id); impl FromStr for ActionId { type Err = InvalidId; @@ -70,7 +69,7 @@ where } #[derive(Clone, Debug, Default, Deserialize, Serialize)] -pub struct Actions(pub IndexMap); +pub struct Actions(pub BTreeMap); #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "version")] diff --git a/appmgr/src/auth.rs b/appmgr/src/auth.rs index 555b82b31..dba55d0a7 100644 --- a/appmgr/src/auth.rs +++ b/appmgr/src/auth.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeMap; use std::marker::PhantomData; use anyhow::anyhow; @@ -6,7 +7,6 @@ use chrono::{DateTime, Utc}; use clap::ArgMatches; use http::header::COOKIE; use http::HeaderValue; -use indexmap::IndexMap; use rpc_toolkit::command; use rpc_toolkit::command_helpers::prelude::{RequestParts, ResponseParts}; use rpc_toolkit::yajrc::RpcError; @@ -160,7 +160,7 @@ pub struct Session { #[serde(rename_all = "kebab-case")] pub struct SessionList { current: String, - sessions: IndexMap, + sessions: BTreeMap, } #[command(subcommands(list, kill))] diff --git a/appmgr/src/config/action.rs b/appmgr/src/config/action.rs index bd08fb974..096f77e32 100644 --- a/appmgr/src/config/action.rs +++ b/appmgr/src/config/action.rs @@ -1,5 +1,6 @@ +use std::collections::{BTreeMap, BTreeSet}; + use anyhow::anyhow; -use indexmap::{IndexMap, IndexSet}; use nix::sys::signal::Signal; use patch_db::HasModel; use serde::{Deserialize, Serialize}; @@ -93,5 +94,5 @@ pub struct SetResult { #[serde(deserialize_with = "crate::util::deserialize_from_str_opt")] #[serde(serialize_with = "crate::util::serialize_display_opt")] pub signal: Option, - pub depends_on: IndexMap>, + pub depends_on: BTreeMap>, } diff --git a/appmgr/src/config/mod.rs b/appmgr/src/config/mod.rs index c4c4462ea..590a2f799 100644 --- a/appmgr/src/config/mod.rs +++ b/appmgr/src/config/mod.rs @@ -1,9 +1,10 @@ +use std::collections::{BTreeMap, BTreeSet}; use std::time::Duration; use anyhow::anyhow; use bollard::container::KillContainerOptions; use futures::future::{BoxFuture, FutureExt}; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexSet; use itertools::Itertools; use patch_db::DbHandle; use rand::SeedableRng; @@ -205,7 +206,7 @@ pub async fn set_dry( ) -> Result { let mut db = ctx.db.handle(); let mut tx = db.begin().await?; - let mut breakages = IndexMap::new(); + let mut breakages = BTreeMap::new(); configure( &ctx, &mut tx, @@ -213,7 +214,7 @@ pub async fn set_dry( config, &timeout, true, - &mut IndexMap::new(), + &mut BTreeMap::new(), &mut breakages, ) .await?; @@ -241,7 +242,7 @@ pub async fn set_impl( ) -> Result, Error> { let mut db = ctx.db.handle(); let mut tx = db.begin().await?; - let mut breakages = IndexMap::new(); + let mut breakages = BTreeMap::new(); configure( &ctx, &mut tx, @@ -249,7 +250,7 @@ pub async fn set_impl( config, &timeout, false, - &mut IndexMap::new(), + &mut BTreeMap::new(), &mut breakages, ) .await?; @@ -278,8 +279,8 @@ pub fn configure<'a, Db: DbHandle>( config: Option, timeout: &'a Option, dry_run: bool, - overrides: &'a mut IndexMap, - breakages: &'a mut IndexMap, + overrides: &'a mut BTreeMap, + breakages: &'a mut BTreeMap, ) -> BoxFuture<'a, Result<(), Error>> { async move { crate::db::DatabaseModel::new() @@ -332,7 +333,7 @@ pub fn configure<'a, Db: DbHandle>( // create backreferences to pointers let mut sys = pkg_model.clone().system_pointers().get_mut(db).await?; sys.truncate(0); - let mut current_dependencies: IndexMap = dependencies + let mut current_dependencies: BTreeMap = dependencies .0 .iter() .filter_map(|(id, info)| { @@ -353,7 +354,7 @@ pub fn configure<'a, Db: DbHandle>( package_id, CurrentDependencyInfo { pointers: vec![target], - health_checks: IndexSet::new(), + health_checks: BTreeSet::new(), }, ); } diff --git a/appmgr/src/config/spec.rs b/appmgr/src/config/spec.rs index 0c5cd2317..f93257912 100644 --- a/appmgr/src/config/spec.rs +++ b/appmgr/src/config/spec.rs @@ -1,4 +1,5 @@ use std::borrow::{Borrow, Cow}; +use std::collections::BTreeMap; use std::fmt; use std::fmt::Debug; use std::ops::RangeBounds; @@ -6,7 +7,7 @@ use std::sync::Arc; use std::time::Duration; use async_trait::async_trait; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexSet; use itertools::Itertools; use jsonpath_lib::Compiled as CompiledJsonPath; use patch_db::{DbHandle, OptionModel}; @@ -37,7 +38,7 @@ pub trait ValueSpec { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError>; // returns all pointers that are live in the provided config @@ -152,7 +153,7 @@ where &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { self.inner.update(ctx, db, config_overrides, value).await @@ -193,7 +194,7 @@ where &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { self.inner.update(ctx, db, config_overrides, value).await @@ -267,7 +268,7 @@ where &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { self.inner.update(ctx, db, config_overrides, value).await @@ -378,7 +379,7 @@ impl ValueSpec for ValueSpecAny { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { match self { @@ -471,7 +472,7 @@ impl ValueSpec for ValueSpecBoolean { &self, ctx: &RpcContext, _db: &mut Db, - _config_overrides: &IndexMap, + _config_overrides: &BTreeMap, _value: &mut Value, ) -> Result<(), ConfigurationError> { Ok(()) @@ -507,7 +508,7 @@ impl DefaultableWith for ValueSpecBoolean { #[serde(rename_all = "kebab-case")] pub struct ValueSpecEnum { pub values: IndexSet, - pub value_names: IndexMap, + pub value_names: BTreeMap, } impl<'de> serde::de::Deserialize<'de> for ValueSpecEnum { fn deserialize>(deserializer: D) -> Result { @@ -516,7 +517,7 @@ impl<'de> serde::de::Deserialize<'de> for ValueSpecEnum { pub struct _ValueSpecEnum { pub values: IndexSet, #[serde(default)] - pub value_names: IndexMap, + pub value_names: BTreeMap, } let mut r#enum = _ValueSpecEnum::deserialize(deserializer)?; @@ -559,7 +560,7 @@ impl ValueSpec for ValueSpecEnum { &self, ctx: &RpcContext, _db: &mut Db, - _config_overrides: &IndexMap, + _config_overrides: &BTreeMap, _value: &mut Value, ) -> Result<(), ConfigurationError> { Ok(()) @@ -644,7 +645,7 @@ where &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { if let Value::Array(ref mut ls) = value { @@ -746,7 +747,7 @@ impl ValueSpec for ValueSpecList { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { match self { @@ -869,7 +870,7 @@ impl ValueSpec for ValueSpecNumber { &self, ctx: &RpcContext, _db: &mut Db, - _config_overrides: &IndexMap, + _config_overrides: &BTreeMap, _value: &mut Value, ) -> Result<(), ConfigurationError> { Ok(()) @@ -887,56 +888,6 @@ impl ValueSpec for ValueSpecNumber { } } } -// TODO: remove -// #[derive(Clone, Copy, Debug, Serialize)] -// pub struct Number(pub f64); -// impl<'de> serde::de::Deserialize<'de> for Number { -// fn deserialize(deserializer: D) -> Result -// where -// D: serde::de::Deserializer<'de>, -// { -// use serde::de::*; -// struct NumberVisitor; -// impl<'de> Visitor<'de> for NumberVisitor { -// type Value = Number; - -// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { -// formatter.write_str("a number") -// } -// fn visit_i8(self, value: i8) -> Result { -// Ok(Number(value.into())) -// } -// fn visit_i16(self, value: i16) -> Result { -// Ok(Number(value.into())) -// } -// fn visit_i32(self, value: i32) -> Result { -// Ok(Number(value.into())) -// } -// fn visit_i64(self, value: i64) -> Result { -// Ok(Number(value as f64)) -// } -// fn visit_u8(self, value: u8) -> Result { -// Ok(Number(value.into())) -// } -// fn visit_u16(self, value: u16) -> Result { -// Ok(Number(value.into())) -// } -// fn visit_u32(self, value: u32) -> Result { -// Ok(Number(value.into())) -// } -// fn visit_u64(self, value: u64) -> Result { -// Ok(Number(value as f64)) -// } -// fn visit_f32(self, value: f32) -> Result { -// Ok(Number(value.into())) -// } -// fn visit_f64(self, value: f64) -> Result { -// Ok(Number(value)) -// } -// } -// deserializer.deserialize_any(NumberVisitor) -// } -// } impl DefaultableWith for ValueSpecNumber { type DefaultSpec = Option; type Error = crate::util::Never; @@ -981,7 +932,7 @@ impl ValueSpec for ValueSpecObject { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { if let Value::Object(o) = value { @@ -1042,7 +993,7 @@ impl Defaultable for ValueSpecObject { } #[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct ConfigSpec(pub IndexMap); +pub struct ConfigSpec(pub BTreeMap); impl ConfigSpec { pub fn matches(&self, value: &Config) -> Result<(), NoMatchWithPath> { for (key, val) in self.0.iter() { @@ -1080,7 +1031,7 @@ impl ConfigSpec { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, cfg: &mut Config, ) -> Result<(), ConfigurationError> { for (k, vs) in self.0.iter() { @@ -1171,7 +1122,7 @@ impl ValueSpec for ValueSpecString { &self, ctx: &RpcContext, _db: &mut Db, - _config_overrides: &IndexMap, + _config_overrides: &BTreeMap, _value: &mut Value, ) -> Result<(), ConfigurationError> { Ok(()) @@ -1263,14 +1214,14 @@ pub struct UnionTag { pub id: String, pub name: String, pub description: Option, - pub variant_names: IndexMap, + pub variant_names: BTreeMap, } #[derive(Clone, Debug, Serialize)] #[serde(rename_all = "kebab-case")] pub struct ValueSpecUnion { pub tag: UnionTag, - pub variants: IndexMap, + pub variants: BTreeMap, pub display_as: Option, pub unique_by: UniqueBy, } @@ -1287,7 +1238,7 @@ impl<'de> serde::de::Deserialize<'de> for ValueSpecUnion { #[derive(Deserialize)] #[serde(rename_all = "kebab-case")] pub struct _ValueSpecUnion { - pub variants: IndexMap, + pub variants: BTreeMap, pub tag: _UnionTag, pub display_as: Option, #[serde(default)] @@ -1381,7 +1332,7 @@ impl ValueSpec for ValueSpecUnion { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { if let Value::Object(o) = value { @@ -1522,7 +1473,7 @@ impl ValueSpec for ValueSpecPointer { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { match self { @@ -1561,7 +1512,7 @@ impl PackagePointerSpec { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, ) -> Result { match &self.target { PackagePointerSpecVariant::TorAddress { interface } => { @@ -1665,7 +1616,7 @@ impl ValueSpec for PackagePointerSpec { &self, ctx: &RpcContext, db: &mut Db, - config_overrides: &IndexMap, + config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { *value = self.deref(ctx, db, config_overrides).await?; @@ -1782,7 +1733,7 @@ impl ValueSpec for SystemPointerSpec { &self, ctx: &RpcContext, db: &mut Db, - _config_overrides: &IndexMap, + _config_overrides: &BTreeMap, value: &mut Value, ) -> Result<(), ConfigurationError> { *value = self.deref(db).await?; diff --git a/appmgr/src/control.rs b/appmgr/src/control.rs index f8740bfb0..b67deeac2 100644 --- a/appmgr/src/control.rs +++ b/appmgr/src/control.rs @@ -1,6 +1,7 @@ +use std::collections::BTreeMap; + use anyhow::anyhow; use chrono::Utc; -use indexmap::IndexMap; use patch_db::DbHandle; use rpc_toolkit::command; @@ -41,7 +42,7 @@ pub async fn start( *status = MainStatus::Running { started: Utc::now(), - health: IndexMap::new(), + health: BTreeMap::new(), }; status .synchronize( diff --git a/appmgr/src/db/model.rs b/appmgr/src/db/model.rs index 03f522f4a..087e081e0 100644 --- a/appmgr/src/db/model.rs +++ b/appmgr/src/db/model.rs @@ -1,6 +1,6 @@ +use std::collections::{BTreeMap, BTreeSet}; use std::sync::Arc; -use indexmap::{IndexMap, IndexSet}; use patch_db::json_ptr::JsonPointer; use patch_db::{HasModel, Map, MapModel, OptionModel}; use reqwest::Url; @@ -130,7 +130,7 @@ pub struct ConnectionAddresses { } #[derive(Debug, Default, Deserialize, Serialize)] -pub struct AllPackageData(pub IndexMap); +pub struct AllPackageData(pub BTreeMap); impl Map for AllPackageData { type Key = PackageId; type Value = PackageDataEntry; @@ -216,11 +216,11 @@ pub struct InstalledPackageDataEntry { pub manifest: Manifest, pub system_pointers: Vec, #[model] - pub dependency_info: IndexMap, + pub dependency_info: BTreeMap, #[model] - pub current_dependents: IndexMap, + pub current_dependents: BTreeMap, #[model] - pub current_dependencies: IndexMap, + pub current_dependencies: BTreeMap, #[model] pub interface_addresses: InterfaceAddressMap, } @@ -236,11 +236,11 @@ pub struct StaticDependencyInfo { #[serde(rename_all = "kebab-case")] pub struct CurrentDependencyInfo { pub pointers: Vec, - pub health_checks: IndexSet, + pub health_checks: BTreeSet, } #[derive(Debug, Deserialize, Serialize)] -pub struct InterfaceAddressMap(pub IndexMap); +pub struct InterfaceAddressMap(pub BTreeMap); impl Map for InterfaceAddressMap { type Key = InterfaceId; type Value = InterfaceAddresses; diff --git a/appmgr/src/dependencies.rs b/appmgr/src/dependencies.rs index d762b5f81..87574027d 100644 --- a/appmgr/src/dependencies.rs +++ b/appmgr/src/dependencies.rs @@ -1,6 +1,7 @@ +use std::collections::BTreeMap; + use anyhow::anyhow; use emver::VersionRange; -use indexmap::IndexMap; use patch_db::{DbHandle, DiffPatch, HasModel, Map, MapModel}; use serde::{Deserialize, Serialize}; @@ -29,7 +30,7 @@ pub enum DependencyError { }, // { "type": "config-unsatisfied", "error": "Bitcoin Core must have pruning set to manual." } NotRunning, // { "type": "not-running" } HealthChecksFailed { - failures: IndexMap, + failures: BTreeMap, }, // { "type": "health-checks-failed", "checks": { "rpc": { "time": "2021-05-11T18:21:29Z", "result": "warming-up" } } } } impl DependencyError { @@ -100,11 +101,11 @@ pub struct TaggedDependencyError { #[serde(rename_all = "kebab-case")] pub struct BreakageRes { pub patch: DiffPatch, - pub breakages: IndexMap, + pub breakages: BTreeMap, } #[derive(Clone, Debug, Default, Deserialize, Serialize)] -pub struct Dependencies(pub IndexMap); +pub struct Dependencies(pub BTreeMap); impl Map for Dependencies { type Key = PackageId; type Value = DepInfo; @@ -209,7 +210,7 @@ impl DepInfo { health, } | MainStatus::Running { health, .. } => { - let mut failures = IndexMap::with_capacity(health.len()); + let mut failures = BTreeMap::new(); for (check, res) in health { if !matches!(res.result, HealthCheckResultVariant::Success) { failures.insert(check.clone(), res.clone()); diff --git a/appmgr/src/disk/util.rs b/appmgr/src/disk/util.rs index 930f94588..df27583db 100644 --- a/appmgr/src/disk/util.rs +++ b/appmgr/src/disk/util.rs @@ -1,8 +1,9 @@ +use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use anyhow::anyhow; use futures::TryStreamExt; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexSet; use regex::Regex; use serde::{Deserialize, Serialize}; use tokio::fs::File; @@ -141,7 +142,7 @@ pub async fn list() -> Result, Error> { crate::ErrorKind::Filesystem, ) }) - .try_fold(IndexMap::new(), |mut disks, dir_entry| async move { + .try_fold(BTreeMap::new(), |mut disks, dir_entry| async move { if let Some(disk_path) = dir_entry.path().file_name().and_then(|s| s.to_str()) { let (disk_path, part_path) = if let Some(end) = PARTITION_REGEX.find(disk_path) { ( @@ -169,7 +170,7 @@ pub async fn list() -> Result, Error> { part_path.display().to_string(), ) })?; - disks[&disk].insert(part); + disks.get_mut(&disk).unwrap().insert(part); } } Ok(disks) diff --git a/appmgr/src/id.rs b/appmgr/src/id.rs index 351226dfb..f987569c4 100644 --- a/appmgr/src/id.rs +++ b/appmgr/src/id.rs @@ -69,7 +69,7 @@ impl<'de> Deserialize<'de> for IdUnchecked<&'de str> { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Id = String>(S); impl> Id { pub fn try_from(value: S) -> Result { @@ -137,7 +137,7 @@ impl> Serialize for Id { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct ImageId = String>(Id); impl> std::fmt::Display for ImageId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/appmgr/src/install/mod.rs b/appmgr/src/install/mod.rs index 935eab1ce..8df85d61a 100644 --- a/appmgr/src/install/mod.rs +++ b/appmgr/src/install/mod.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::collections::{BTreeMap, HashSet}; use std::io::SeekFrom; use std::path::Path; use std::process::Stdio; @@ -9,7 +9,6 @@ use anyhow::anyhow; use emver::VersionRange; use futures::TryStreamExt; use http::StatusCode; -use indexmap::IndexMap; use patch_db::DbHandle; use reqwest::Response; use rpc_toolkit::command; @@ -287,7 +286,7 @@ pub async fn install_s9pk( log::info!("Install {}@{}: Unpacked Manifest", pkg_id, version); log::info!("Install {}@{}: Fetching Dependency Info", pkg_id, version); - let mut dependency_info = IndexMap::with_capacity(manifest.dependencies.0.len()); + let mut dependency_info = BTreeMap::new(); let reg_url = ctx.package_registry_url().await?; for (dep, info) in &manifest.dependencies.0 { let manifest: Option = match reqwest::get(format!( @@ -542,7 +541,7 @@ pub async fn install_s9pk( update_current_dependents(&mut tx, pkg_id, ¤t_dependencies).await?; let current_dependents = { // search required dependencies - let mut deps = IndexMap::new(); + let mut deps = BTreeMap::new(); for package in crate::db::DatabaseModel::new() .package_data() .keys(&mut tx, true) @@ -648,8 +647,8 @@ pub async fn install_s9pk( None, &None, false, - &mut IndexMap::new(), - &mut IndexMap::new(), + &mut BTreeMap::new(), + &mut BTreeMap::new(), ) .await?; todo!("set as running if viable"); diff --git a/appmgr/src/net/interface.rs b/appmgr/src/net/interface.rs index 970cb11cc..76d14fb8c 100644 --- a/appmgr/src/net/interface.rs +++ b/appmgr/src/net/interface.rs @@ -1,9 +1,9 @@ -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::path::Path; use anyhow::anyhow; use futures::TryStreamExt; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexSet; use itertools::Either; use serde::{Deserialize, Deserializer, Serialize}; use sqlx::{Executor, Sqlite}; @@ -17,7 +17,7 @@ use crate::Error; #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] -pub struct Interfaces(pub IndexMap); // TODO +pub struct Interfaces(pub BTreeMap); // TODO impl Interfaces { pub async fn install( &self, @@ -27,7 +27,7 @@ impl Interfaces { where for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>, { - let mut interface_addresses = InterfaceAddressMap(IndexMap::new()); + let mut interface_addresses = InterfaceAddressMap(BTreeMap::new()); for (id, iface) in &self.0 { let mut addrs = InterfaceAddresses { tor_address: None, @@ -101,7 +101,7 @@ impl Interfaces { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct InterfaceId = String>(Id); impl> From> for InterfaceId { fn from(id: Id) -> Self { @@ -148,7 +148,7 @@ pub struct Interface { pub name: String, pub description: String, pub tor_config: Option, - pub lan_config: Option>, + pub lan_config: Option>, pub ui: bool, pub protocols: IndexSet, } @@ -156,7 +156,7 @@ pub struct Interface { #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub struct TorConfig { - pub port_mapping: IndexMap, + pub port_mapping: BTreeMap, } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/appmgr/src/net/nginx.rs b/appmgr/src/net/nginx.rs index d4c6f8517..751c5e61d 100644 --- a/appmgr/src/net/nginx.rs +++ b/appmgr/src/net/nginx.rs @@ -1,9 +1,9 @@ -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::net::Ipv4Addr; use std::path::PathBuf; use futures::FutureExt; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexSet; use sqlx::SqlitePool; use tokio::sync::Mutex; @@ -201,6 +201,6 @@ struct PackageNetInfo { } pub struct InterfaceMetadata { pub dns_base: String, - pub lan_config: IndexMap, + pub lan_config: BTreeMap, pub protocols: IndexSet, } diff --git a/appmgr/src/s9pk/manifest.rs b/appmgr/src/s9pk/manifest.rs index 66e51a97e..a5df1618c 100644 --- a/appmgr/src/s9pk/manifest.rs +++ b/appmgr/src/s9pk/manifest.rs @@ -19,7 +19,7 @@ use crate::volume::Volumes; pub const SYSTEM_PACKAGE_ID: PackageId<&'static str> = PackageId(SYSTEM_ID); -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PackageId = String>(Id); impl<'a> PackageId<&'a str> { pub fn owned(&self) -> PackageId { diff --git a/appmgr/src/status/health_check.rs b/appmgr/src/status/health_check.rs index a267151e9..b70782854 100644 --- a/appmgr/src/status/health_check.rs +++ b/appmgr/src/status/health_check.rs @@ -1,7 +1,7 @@ +use std::collections::BTreeMap; use std::path::Path; use chrono::{DateTime, Utc}; -use indexmap::IndexMap; use serde::{Deserialize, Deserializer, Serialize}; use crate::action::{ActionImplementation, NoOutput}; @@ -12,7 +12,7 @@ use crate::util::Version; use crate::volume::Volumes; use crate::Error; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct HealthCheckId = String>(Id); impl> std::fmt::Display for HealthCheckId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -43,7 +43,7 @@ impl> AsRef for HealthCheckId { } #[derive(Clone, Debug, Deserialize, Serialize)] -pub struct HealthChecks(pub IndexMap); +pub struct HealthChecks(pub BTreeMap); impl HealthChecks { pub async fn check_all( &self, @@ -52,7 +52,7 @@ impl HealthChecks { pkg_id: &PackageId, pkg_version: &Version, volumes: &Volumes, - ) -> Result, Error> { + ) -> Result, Error> { let res = futures::future::try_join_all(self.0.iter().map(|(id, check)| async move { Ok::<_, Error>(( id.clone(), diff --git a/appmgr/src/status/mod.rs b/appmgr/src/status/mod.rs index 0c3e45e60..f525c17ac 100644 --- a/appmgr/src/status/mod.rs +++ b/appmgr/src/status/mod.rs @@ -1,11 +1,10 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::sync::Arc; use anyhow::anyhow; use chrono::{DateTime, Utc}; use futures::future::BoxFuture; use futures::{FutureExt, StreamExt}; -use indexmap::IndexMap; use patch_db::{DbHandle, HasModel, Map, MapModel, ModelData}; use serde::{Deserialize, Serialize}; @@ -129,7 +128,7 @@ pub async fn check_all(ctx: &RpcContext) -> Result<(), Error> { .to_owned() .into_iter() .filter(|(id, _)| listed_deps.contains(id)) - .collect::>() + .collect::>() }), )); } @@ -182,7 +181,7 @@ pub async fn check_all(ctx: &RpcContext) -> Result<(), Error> { id: &PackageId, statuses: Arc>, model: InstalledPackageDataEntryModel, - current_deps: Arc>, + current_deps: Arc>, mut db: Db, ) -> Result<(), Error> { for (dep_id, dep_info) in &*current_deps { @@ -192,7 +191,7 @@ pub async fn check_all(ctx: &RpcContext) -> Result<(), Error> { started: Some(_), ref health, }) => { - let mut failures = IndexMap::new(); + let mut failures = BTreeMap::new(); for check in &dep_info.health_checks { let res = health .get(check) @@ -219,7 +218,7 @@ pub async fn check_all(ctx: &RpcContext) -> Result<(), Error> { dep_id, model.clone(), err, - &mut IndexMap::new(), + &mut BTreeMap::new(), ) .await?; } else { @@ -274,11 +273,11 @@ pub enum MainStatus { Stopping, Running { started: DateTime, - health: IndexMap, + health: BTreeMap, }, BackingUp { started: Option>, - health: IndexMap, + health: BTreeMap, }, Restoring { running: bool, @@ -394,7 +393,7 @@ impl MainStatus { } #[derive(Debug, Clone, Default, Deserialize, Serialize)] -pub struct DependencyErrors(pub IndexMap); +pub struct DependencyErrors(pub BTreeMap); impl Map for DependencyErrors { type Key = PackageId; type Value = DependencyError; @@ -410,9 +409,9 @@ impl DependencyErrors { ctx: &RpcContext, db: &mut Db, manifest: &Manifest, - current_dependencies: &IndexMap, + current_dependencies: &BTreeMap, ) -> Result { - let mut res = IndexMap::new(); + let mut res = BTreeMap::new(); for dep_id in current_dependencies.keys() { if let Err(e) = manifest .dependencies @@ -448,7 +447,7 @@ pub fn handle_broken_dependents<'a, Db: DbHandle>( dependency: &'a PackageId, model: InstalledPackageDataEntryModel, error: DependencyError, - breakages: &'a mut IndexMap, + breakages: &'a mut BTreeMap, ) -> BoxFuture<'a, Result<(), Error>> { async move { let mut status = model.clone().status().get_mut(db).await?; diff --git a/appmgr/src/util/mod.rs b/appmgr/src/util/mod.rs index adab08a65..fe59f6aa6 100644 --- a/appmgr/src/util/mod.rs +++ b/appmgr/src/util/mod.rs @@ -704,7 +704,68 @@ impl std::io::Write for HashWriter { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub fn deserialize_number_permissive< + 'de, + D: serde::de::Deserializer<'de>, + T: FromStr + num::cast::FromPrimitive, + E: std::fmt::Display, +>( + deserializer: D, +) -> std::result::Result { + use num::cast::FromPrimitive; + + struct Visitor + num::cast::FromPrimitive, E>(std::marker::PhantomData); + impl<'de, T: FromStr + num::cast::FromPrimitive, Err: std::fmt::Display> + serde::de::Visitor<'de> for Visitor + { + type Value = T; + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "a parsable string") + } + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + v.parse().map_err(|e| serde::de::Error::custom(e)) + } + fn visit_f64(self, v: f64) -> Result + where + E: serde::de::Error, + { + T::from_f64(v).ok_or_else(|| { + serde::de::Error::custom(format!( + "{} cannot be represented by the requested type", + v + )) + }) + } + fn visit_u64(self, v: u64) -> Result + where + E: serde::de::Error, + { + T::from_u64(v).ok_or_else(|| { + serde::de::Error::custom(format!( + "{} cannot be represented by the requested type", + v + )) + }) + } + fn visit_i64(self, v: i64) -> Result + where + E: serde::de::Error, + { + T::from_i64(v).ok_or_else(|| { + serde::de::Error::custom(format!( + "{} cannot be represented by the requested type", + v + )) + }) + } + } + deserializer.deserialize_str(Visitor(std::marker::PhantomData)) +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Port(pub u16); impl<'de> Deserialize<'de> for Port { fn deserialize(deserializer: D) -> Result @@ -712,7 +773,7 @@ impl<'de> Deserialize<'de> for Port { D: Deserializer<'de>, { //TODO: if number, be permissive - deserialize_from_str(deserializer).map(Port) + deserialize_number_permissive(deserializer).map(Port) } } impl Serialize for Port { diff --git a/appmgr/src/volume.rs b/appmgr/src/volume.rs index 5e38ed1fb..b3e08070f 100644 --- a/appmgr/src/volume.rs +++ b/appmgr/src/volume.rs @@ -1,8 +1,8 @@ use std::borrow::Borrow; +use std::collections::BTreeMap; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; -use indexmap::IndexMap; use patch_db::{HasModel, Map, MapModel}; use serde::{Deserialize, Deserializer, Serialize}; @@ -16,7 +16,7 @@ use crate::Error; pub const PKG_VOLUME_DIR: &'static str = "package-data/volumes"; pub const BACKUP_DIR: &'static str = "/mnt/embassy-os-backups/EmbassyBackups"; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum VolumeId = String> { Backup, Custom(Id), @@ -73,7 +73,7 @@ impl> Serialize for VolumeId { } #[derive(Clone, Debug, Default, Deserialize, Serialize)] -pub struct Volumes(IndexMap); +pub struct Volumes(BTreeMap); impl Volumes { pub async fn install( &self, @@ -111,7 +111,7 @@ impl Volumes { } } impl Deref for Volumes { - type Target = IndexMap; + type Target = BTreeMap; fn deref(&self) -> &Self::Target { &self.0 } diff --git a/patch-db b/patch-db index d26e1563e..6f3921e32 160000 --- a/patch-db +++ b/patch-db @@ -1 +1 @@ -Subproject commit d26e1563e87a7a59d328176b810429ab4056cb17 +Subproject commit 6f3921e329445c3a356cbcdf65daefa37c15e45b From 5c11b1438399b58fd71dd01d0b5b8e9615fddb1b Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 27 Sep 2021 18:04:11 -0600 Subject: [PATCH 5/6] update patch-db --- patch-db | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch-db b/patch-db index 6f3921e32..e442ae623 160000 --- a/patch-db +++ b/patch-db @@ -1 +1 @@ -Subproject commit 6f3921e329445c3a356cbcdf65daefa37c15e45b +Subproject commit e442ae62341a485d393e4ee8cf27cd910cb0bb36 From 69fd8da2fffc5c7f4f7419b2cbf34e1d4c69450e Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 27 Sep 2021 18:37:03 -0600 Subject: [PATCH 6/6] separate context for sdk --- appmgr/src/bin/embassy-sdk.rs | 4 +-- appmgr/src/context/cli.rs | 22 +----------- appmgr/src/context/mod.rs | 7 ++++ appmgr/src/context/sdk.rs | 64 +++++++++++++++++++++++++++++++++++ appmgr/src/developer/mod.rs | 4 +-- appmgr/src/lib.rs | 3 -- appmgr/src/s9pk/mod.rs | 4 +-- 7 files changed, 78 insertions(+), 30 deletions(-) create mode 100644 appmgr/src/context/sdk.rs diff --git a/appmgr/src/bin/embassy-sdk.rs b/appmgr/src/bin/embassy-sdk.rs index ff748629b..c33dc2f13 100644 --- a/appmgr/src/bin/embassy-sdk.rs +++ b/appmgr/src/bin/embassy-sdk.rs @@ -1,4 +1,4 @@ -use embassy::context::CliContext; +use embassy::context::SdkContext; use embassy::Error; use rpc_toolkit::run_cli; use rpc_toolkit::yajrc::RpcError; @@ -30,7 +30,7 @@ fn inner_main() -> Result<(), Error> { 4 => log::LevelFilter::Debug, _ => log::LevelFilter::Trace, }); - CliContext::init(matches)? + SdkContext::init(matches)? }, exit: |e: RpcError| { match e.data { diff --git a/appmgr/src/context/cli.rs b/appmgr/src/context/cli.rs index 4519d27a5..a59428c95 100644 --- a/appmgr/src/context/cli.rs +++ b/appmgr/src/context/cli.rs @@ -14,7 +14,6 @@ use rpc_toolkit::url::Host; use rpc_toolkit::Context; use serde::Deserialize; -use super::rpc::RpcContextConfig; use crate::{Error, ResultExt}; #[derive(Debug, Default, Deserialize)] @@ -24,10 +23,7 @@ pub struct CliContextConfig { pub host: Option, #[serde(deserialize_with = "crate::util::deserialize_from_str_opt")] pub proxy: Option, - pub developer_key_path: Option, pub cookie_path: Option, - #[serde(flatten)] - pub server_config: RpcContextConfig, } #[derive(Debug)] @@ -36,7 +32,6 @@ pub struct CliContextSeed { pub client: Client, pub cookie_store: Arc, pub cookie_path: PathBuf, - pub developer_key_path: PathBuf, } impl Drop for CliContextSeed { fn drop(&mut self) { @@ -63,7 +58,7 @@ impl CliContext { /// BLOCKING pub fn init(matches: &ArgMatches) -> Result { let cfg_path = Path::new(matches.value_of("config").unwrap_or(crate::CONFIG_PATH)); - let mut base = if cfg_path.exists() { + let base = if cfg_path.exists() { serde_yaml::from_reader( File::open(cfg_path) .with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))?, @@ -114,23 +109,8 @@ impl CliContext { }, cookie_store, cookie_path, - developer_key_path: base.developer_key_path.unwrap_or_else(|| { - cfg_path - .parent() - .unwrap_or(Path::new("/")) - .join(".developer_key") - }), }))) } - /// BLOCKING - pub fn developer_key(&self) -> Result { - if !self.developer_key_path.exists() { - return Err(Error::new(anyhow!("Developer Key does not exist! Please run `embassy-sdk init` before running this command."), crate::ErrorKind::Uninitialized)); - } - let mut keypair_buf = [0; ed25519_dalek::KEYPAIR_LENGTH]; - File::open(&self.developer_key_path)?.read_exact(&mut keypair_buf)?; - Ok(ed25519_dalek::Keypair::from_bytes(&keypair_buf)?) - } } impl std::ops::Deref for CliContext { type Target = CliContextSeed; diff --git a/appmgr/src/context/mod.rs b/appmgr/src/context/mod.rs index c094c50ab..c7bf15271 100644 --- a/appmgr/src/context/mod.rs +++ b/appmgr/src/context/mod.rs @@ -1,11 +1,13 @@ pub mod cli; pub mod diagnostic; pub mod rpc; +pub mod sdk; pub mod setup; pub use cli::CliContext; pub use diagnostic::DiagnosticContext; pub use rpc::RpcContext; +pub use sdk::SdkContext; pub use setup::SetupContext; impl From for () { @@ -23,6 +25,11 @@ impl From for () { () } } +impl From for () { + fn from(_: SdkContext) -> Self { + () + } +} impl From for () { fn from(_: SetupContext) -> Self { () diff --git a/appmgr/src/context/sdk.rs b/appmgr/src/context/sdk.rs new file mode 100644 index 000000000..96a837c56 --- /dev/null +++ b/appmgr/src/context/sdk.rs @@ -0,0 +1,64 @@ +use std::fs::File; +use std::io::Read; +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use anyhow::anyhow; +use clap::ArgMatches; +use rpc_toolkit::Context; +use serde::Deserialize; + +use crate::{Error, ResultExt}; + +#[derive(Debug, Default, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct SdkContextConfig { + pub developer_key_path: Option, +} + +#[derive(Debug)] +pub struct SdkContextSeed { + pub developer_key_path: PathBuf, +} + +#[derive(Debug, Clone)] +pub struct SdkContext(Arc); +impl SdkContext { + /// BLOCKING + pub fn init(matches: &ArgMatches) -> Result { + let cfg_path = Path::new(matches.value_of("config").unwrap_or(crate::CONFIG_PATH)); + let base = if cfg_path.exists() { + serde_yaml::from_reader( + File::open(cfg_path) + .with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))?, + ) + .with_kind(crate::ErrorKind::Deserialization)? + } else { + SdkContextConfig::default() + }; + Ok(SdkContext(Arc::new(SdkContextSeed { + developer_key_path: base.developer_key_path.unwrap_or_else(|| { + cfg_path + .parent() + .unwrap_or(Path::new("/")) + .join(".developer_key") + }), + }))) + } + /// BLOCKING + pub fn developer_key(&self) -> Result { + if !self.developer_key_path.exists() { + return Err(Error::new(anyhow!("Developer Key does not exist! Please run `embassy-sdk init` before running this command."), crate::ErrorKind::Uninitialized)); + } + let mut keypair_buf = [0; ed25519_dalek::KEYPAIR_LENGTH]; + File::open(&self.developer_key_path)?.read_exact(&mut keypair_buf)?; + Ok(ed25519_dalek::Keypair::from_bytes(&keypair_buf)?) + } +} +impl std::ops::Deref for SdkContext { + type Target = SdkContextSeed; + fn deref(&self) -> &Self::Target { + &*self.0 + } +} +impl Context for SdkContext {} diff --git a/appmgr/src/developer/mod.rs b/appmgr/src/developer/mod.rs index ac7925f46..dec75c711 100644 --- a/appmgr/src/developer/mod.rs +++ b/appmgr/src/developer/mod.rs @@ -5,12 +5,12 @@ use std::path::Path; use ed25519_dalek::Keypair; use rpc_toolkit::command; -use crate::context::CliContext; +use crate::context::SdkContext; use crate::util::display_none; use crate::{Error, ResultExt}; #[command(cli_only, blocking, display(display_none))] -pub fn init(#[context] ctx: CliContext) -> Result<(), Error> { +pub fn init(#[context] ctx: SdkContext) -> Result<(), Error> { if !ctx.developer_key_path.exists() { let parent = ctx.developer_key_path.parent().unwrap_or(Path::new("/")); if !parent.exists() { diff --git a/appmgr/src/lib.rs b/appmgr/src/lib.rs index b2ce31152..1bd497110 100644 --- a/appmgr/src/lib.rs +++ b/appmgr/src/lib.rs @@ -54,9 +54,6 @@ pub fn echo(#[arg] message: String) -> Result { #[command(subcommands( version::git_info, echo, - developer::init, - s9pk::pack, - s9pk::verify, inspect::inspect, server, package, diff --git a/appmgr/src/s9pk/mod.rs b/appmgr/src/s9pk/mod.rs index 8043f1655..ca3091f5f 100644 --- a/appmgr/src/s9pk/mod.rs +++ b/appmgr/src/s9pk/mod.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use anyhow::anyhow; use rpc_toolkit::command; -use crate::context::CliContext; +use crate::context::SdkContext; use crate::s9pk::builder::S9pkPacker; use crate::s9pk::manifest::Manifest; use crate::s9pk::reader::S9pkReader; @@ -19,7 +19,7 @@ pub mod reader; pub const SIG_CONTEXT: &'static [u8] = b"s9pk"; #[command(cli_only, display(display_none), blocking)] -pub fn pack(#[context] ctx: CliContext, #[arg] path: Option) -> Result<(), Error> { +pub fn pack(#[context] ctx: SdkContext, #[arg] path: Option) -> Result<(), Error> { use std::fs::File; use std::io::Read;