Merge branch 'integration/0.3.0' of github.com:Start9Labs/embassy-os into integration/0.3.0

This commit is contained in:
Matt Hill
2021-09-28 11:10:11 -06:00
31 changed files with 337 additions and 196 deletions

59
appmgr/Cargo.lock generated
View File

@@ -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",

View File

@@ -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"] }

View File

@@ -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<String>,
#[serde(default)]
pub mounts: IndexMap<VolumeId, PathBuf>,
pub mounts: BTreeMap<VolumeId, PathBuf>,
#[serde(default)]
pub io_format: Option<IoFormat>,
#[serde(default)]

View File

@@ -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,7 +14,7 @@ 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, Version};
use crate::volume::Volumes;
use crate::{Error, ResultExt};
@@ -21,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<S: AsRef<str> = String>(Id<S>);
impl FromStr for ActionId {
type Err = InvalidId;
@@ -68,7 +69,7 @@ where
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Actions(pub IndexMap<ActionId, Action>);
pub struct Actions(pub BTreeMap<ActionId, Action>);
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "version")]
@@ -80,7 +81,7 @@ pub enum ActionResult {
#[derive(Debug, Serialize, Deserialize)]
pub struct ActionResultV0 {
pub message: String,
pub value: ValuePrimative,
pub value: Option<String>,
pub copyable: bool,
pub qr: bool,
}
@@ -183,8 +184,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()
);
}
}
}

View File

@@ -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<String, Session>,
sessions: BTreeMap<String, Session>,
}
#[command(subcommands(list, kill))]

View File

@@ -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 {

View File

@@ -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<Signal>,
pub depends_on: IndexMap<PackageId, IndexSet<HealthCheckId>>,
pub depends_on: BTreeMap<PackageId, BTreeSet<HealthCheckId>>,
}

View File

@@ -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<BreakageRes, 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,
@@ -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<WithRevision<()>, 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<Config>,
timeout: &'a Option<Duration>,
dry_run: bool,
overrides: &'a mut IndexMap<PackageId, Config>,
breakages: &'a mut IndexMap<PackageId, TaggedDependencyError>,
overrides: &'a mut BTreeMap<PackageId, Config>,
breakages: &'a mut BTreeMap<PackageId, TaggedDependencyError>,
) -> BoxFuture<'a, Result<(), Error>> {
async move {
crate::db::DatabaseModel::new()
@@ -332,11 +333,11 @@ 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<PackageId, CurrentDependencyInfo> = dependencies
let mut current_dependencies: BTreeMap<PackageId, CurrentDependencyInfo> = dependencies
.0
.iter()
.filter_map(|(id, info)| {
if info.optional.is_none() {
if info.requirement.required() {
Some((id.clone(), CurrentDependencyInfo::default()))
} else {
None
@@ -353,7 +354,7 @@ pub fn configure<'a, Db: DbHandle>(
package_id,
CurrentDependencyInfo {
pointers: vec![target],
health_checks: IndexSet::new(),
health_checks: BTreeSet::new(),
},
);
}

View File

@@ -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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
value: &mut Value,
) -> Result<(), ConfigurationError> {
match self {
@@ -471,7 +472,7 @@ impl ValueSpec for ValueSpecBoolean {
&self,
ctx: &RpcContext,
_db: &mut Db,
_config_overrides: &IndexMap<PackageId, Config>,
_config_overrides: &BTreeMap<PackageId, Config>,
_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<String>,
pub value_names: IndexMap<String, String>,
pub value_names: BTreeMap<String, String>,
}
impl<'de> serde::de::Deserialize<'de> for ValueSpecEnum {
fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
@@ -516,7 +517,7 @@ impl<'de> serde::de::Deserialize<'de> for ValueSpecEnum {
pub struct _ValueSpecEnum {
pub values: IndexSet<String>,
#[serde(default)]
pub value_names: IndexMap<String, String>,
pub value_names: BTreeMap<String, String>,
}
let mut r#enum = _ValueSpecEnum::deserialize(deserializer)?;
@@ -559,7 +560,7 @@ impl ValueSpec for ValueSpecEnum {
&self,
ctx: &RpcContext,
_db: &mut Db,
_config_overrides: &IndexMap<PackageId, Config>,
_config_overrides: &BTreeMap<PackageId, Config>,
_value: &mut Value,
) -> Result<(), ConfigurationError> {
Ok(())
@@ -644,7 +645,7 @@ where
&self,
ctx: &RpcContext,
db: &mut Db,
config_overrides: &IndexMap<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
value: &mut Value,
) -> Result<(), ConfigurationError> {
match self {
@@ -869,7 +870,7 @@ impl ValueSpec for ValueSpecNumber {
&self,
ctx: &RpcContext,
_db: &mut Db,
_config_overrides: &IndexMap<PackageId, Config>,
_config_overrides: &BTreeMap<PackageId, Config>,
_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<D>(deserializer: D) -> Result<Self, D::Error>
// 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<E: Error>(self, value: i8) -> Result<Self::Value, E> {
// Ok(Number(value.into()))
// }
// fn visit_i16<E: Error>(self, value: i16) -> Result<Self::Value, E> {
// Ok(Number(value.into()))
// }
// fn visit_i32<E: Error>(self, value: i32) -> Result<Self::Value, E> {
// Ok(Number(value.into()))
// }
// fn visit_i64<E: Error>(self, value: i64) -> Result<Self::Value, E> {
// Ok(Number(value as f64))
// }
// fn visit_u8<E: Error>(self, value: u8) -> Result<Self::Value, E> {
// Ok(Number(value.into()))
// }
// fn visit_u16<E: Error>(self, value: u16) -> Result<Self::Value, E> {
// Ok(Number(value.into()))
// }
// fn visit_u32<E: Error>(self, value: u32) -> Result<Self::Value, E> {
// Ok(Number(value.into()))
// }
// fn visit_u64<E: Error>(self, value: u64) -> Result<Self::Value, E> {
// Ok(Number(value as f64))
// }
// fn visit_f32<E: Error>(self, value: f32) -> Result<Self::Value, E> {
// Ok(Number(value.into()))
// }
// fn visit_f64<E: Error>(self, value: f64) -> Result<Self::Value, E> {
// Ok(Number(value))
// }
// }
// deserializer.deserialize_any(NumberVisitor)
// }
// }
impl DefaultableWith for ValueSpecNumber {
type DefaultSpec = Option<Number>;
type Error = crate::util::Never;
@@ -981,7 +932,7 @@ impl ValueSpec for ValueSpecObject {
&self,
ctx: &RpcContext,
db: &mut Db,
config_overrides: &IndexMap<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<String, ValueSpecAny>);
pub struct ConfigSpec(pub BTreeMap<String, ValueSpecAny>);
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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
_config_overrides: &BTreeMap<PackageId, Config>,
_value: &mut Value,
) -> Result<(), ConfigurationError> {
Ok(())
@@ -1263,14 +1214,14 @@ pub struct UnionTag {
pub id: String,
pub name: String,
pub description: Option<String>,
pub variant_names: IndexMap<String, String>,
pub variant_names: BTreeMap<String, String>,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct ValueSpecUnion {
pub tag: UnionTag,
pub variants: IndexMap<String, ConfigSpec>,
pub variants: BTreeMap<String, ConfigSpec>,
pub display_as: Option<String>,
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<String, ConfigSpec>,
pub variants: BTreeMap<String, ConfigSpec>,
pub tag: _UnionTag,
pub display_as: Option<String>,
#[serde(default)]
@@ -1381,7 +1332,7 @@ impl ValueSpec for ValueSpecUnion {
&self,
ctx: &RpcContext,
db: &mut Db,
config_overrides: &IndexMap<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
value: &mut Value,
) -> Result<(), ConfigurationError> {
match self {
@@ -1561,7 +1512,7 @@ impl PackagePointerSpec {
&self,
ctx: &RpcContext,
db: &mut Db,
config_overrides: &IndexMap<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
) -> Result<Value, ConfigurationError> {
match &self.target {
PackagePointerSpecVariant::TorAddress { interface } => {
@@ -1665,7 +1616,7 @@ impl ValueSpec for PackagePointerSpec {
&self,
ctx: &RpcContext,
db: &mut Db,
config_overrides: &IndexMap<PackageId, Config>,
config_overrides: &BTreeMap<PackageId, Config>,
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<PackageId, Config>,
_config_overrides: &BTreeMap<PackageId, Config>,
value: &mut Value,
) -> Result<(), ConfigurationError> {
*value = self.deref(db).await?;

View File

@@ -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<Url>,
#[serde(deserialize_with = "crate::util::deserialize_from_str_opt")]
pub proxy: Option<Url>,
pub developer_key_path: Option<PathBuf>,
pub cookie_path: Option<PathBuf>,
#[serde(flatten)]
pub server_config: RpcContextConfig,
}
#[derive(Debug)]
@@ -36,7 +32,6 @@ pub struct CliContextSeed {
pub client: Client,
pub cookie_store: Arc<CookieStoreMutex>,
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<Self, crate::Error> {
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<ed25519_dalek::Keypair, Error> {
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;

View File

@@ -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<CliContext> for () {
@@ -23,6 +25,11 @@ impl From<RpcContext> for () {
()
}
}
impl From<SdkContext> for () {
fn from(_: SdkContext) -> Self {
()
}
}
impl From<SetupContext> for () {
fn from(_: SetupContext) -> Self {
()

64
appmgr/src/context/sdk.rs Normal file
View File

@@ -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<PathBuf>,
}
#[derive(Debug)]
pub struct SdkContextSeed {
pub developer_key_path: PathBuf,
}
#[derive(Debug, Clone)]
pub struct SdkContext(Arc<SdkContextSeed>);
impl SdkContext {
/// BLOCKING
pub fn init(matches: &ArgMatches) -> Result<Self, crate::Error> {
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<ed25519_dalek::Keypair, Error> {
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 {}

View File

@@ -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(

View File

@@ -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<PackageId, PackageDataEntry>);
pub struct AllPackageData(pub BTreeMap<PackageId, PackageDataEntry>);
impl Map for AllPackageData {
type Key = PackageId;
type Value = PackageDataEntry;
@@ -216,11 +216,11 @@ pub struct InstalledPackageDataEntry {
pub manifest: Manifest,
pub system_pointers: Vec<SystemPointerSpec>,
#[model]
pub dependency_info: IndexMap<PackageId, StaticDependencyInfo>,
pub dependency_info: BTreeMap<PackageId, StaticDependencyInfo>,
#[model]
pub current_dependents: IndexMap<PackageId, CurrentDependencyInfo>,
pub current_dependents: BTreeMap<PackageId, CurrentDependencyInfo>,
#[model]
pub current_dependencies: IndexMap<PackageId, CurrentDependencyInfo>,
pub current_dependencies: BTreeMap<PackageId, CurrentDependencyInfo>,
#[model]
pub interface_addresses: InterfaceAddressMap,
}
@@ -236,11 +236,11 @@ pub struct StaticDependencyInfo {
#[serde(rename_all = "kebab-case")]
pub struct CurrentDependencyInfo {
pub pointers: Vec<PackagePointerSpecVariant>,
pub health_checks: IndexSet<HealthCheckId>,
pub health_checks: BTreeSet<HealthCheckId>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct InterfaceAddressMap(pub IndexMap<InterfaceId, InterfaceAddresses>);
pub struct InterfaceAddressMap(pub BTreeMap<InterfaceId, InterfaceAddresses>);
impl Map for InterfaceAddressMap {
type Key = InterfaceId;
type Value = InterfaceAddresses;

View File

@@ -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<HealthCheckId, HealthCheckResult>,
failures: BTreeMap<HealthCheckId, HealthCheckResult>,
}, // { "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<PackageId, TaggedDependencyError>,
pub breakages: BTreeMap<PackageId, TaggedDependencyError>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Dependencies(pub IndexMap<PackageId, DepInfo>);
pub struct Dependencies(pub BTreeMap<PackageId, DepInfo>);
impl Map for Dependencies {
type Key = PackageId;
type Value = DepInfo;
@@ -116,12 +117,25 @@ impl HasModel for Dependencies {
type Model = MapModel<Self>;
}
#[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<String>,
pub recommended: bool,
pub requirement: DependencyRequirement,
pub description: Option<String>,
pub critical: bool,
#[serde(default)]
@@ -196,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());

View File

@@ -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() {

View File

@@ -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<Vec<DiskInfo>, 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<Vec<DiskInfo>, Error> {
part_path.display().to_string(),
)
})?;
disks[&disk].insert(part);
disks.get_mut(&disk).unwrap().insert(part);
}
}
Ok(disks)

View File

@@ -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<S: AsRef<str> = String>(S);
impl<S: AsRef<str>> Id<S> {
pub fn try_from(value: S) -> Result<Self, InvalidId> {
@@ -137,7 +137,7 @@ impl<S: AsRef<str>> Serialize for Id<S> {
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
pub struct ImageId<S: AsRef<str> = String>(Id<S>);
impl<S: AsRef<str>> std::fmt::Display for ImageId<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

View File

@@ -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<R: AsyncRead + AsyncSeek + Unpin>(
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<Manifest> = match reqwest::get(format!(
@@ -532,7 +531,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
.0
.iter()
.filter_map(|(id, info)| {
if info.optional.is_none() {
if info.requirement.required() {
Some((id.clone(), CurrentDependencyInfo::default()))
} else {
None
@@ -542,7 +541,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
update_current_dependents(&mut tx, pkg_id, &current_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<R: AsyncRead + AsyncSeek + Unpin>(
None,
&None,
false,
&mut IndexMap::new(),
&mut IndexMap::new(),
&mut BTreeMap::new(),
&mut BTreeMap::new(),
)
.await?;
todo!("set as running if viable");

View File

@@ -54,9 +54,6 @@ pub fn echo(#[arg] message: String) -> Result<String, RpcError> {
#[command(subcommands(
version::git_info,
echo,
developer::init,
s9pk::pack,
s9pk::verify,
inspect::inspect,
server,
package,

View File

@@ -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(

View File

@@ -75,7 +75,7 @@ impl Stream for DecryptStream {
aeskey.as_mut_slice(),
);
let ctr = Nonce::<Aes256Ctr>::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);

View File

@@ -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<InterfaceId, Interface>); // TODO
pub struct Interfaces(pub BTreeMap<InterfaceId, Interface>); // TODO
impl Interfaces {
pub async fn install<Ex>(
&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<S: AsRef<str> = String>(Id<S>);
impl<S: AsRef<str>> From<Id<S>> for InterfaceId<S> {
fn from(id: Id<S>) -> Self {
@@ -148,7 +148,7 @@ pub struct Interface {
pub name: String,
pub description: String,
pub tor_config: Option<TorConfig>,
pub lan_config: Option<IndexMap<Port, LanPortConfig>>,
pub lan_config: Option<BTreeMap<Port, LanPortConfig>>,
pub ui: bool,
pub protocols: IndexSet<String>,
}
@@ -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<Port, Port>,
pub port_mapping: BTreeMap<Port, Port>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]

View File

@@ -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<Port, LanPortConfig>,
pub lan_config: BTreeMap<Port, LanPortConfig>,
pub protocols: IndexSet<String>,
}

View File

@@ -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<S: AsRef<str> = String>(Id<S>);
impl<'a> PackageId<&'a str> {
pub fn owned(&self) -> PackageId {

View File

@@ -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<PathBuf>) -> Result<(), Error> {
pub fn pack(#[context] ctx: SdkContext, #[arg] path: Option<PathBuf>) -> Result<(), Error> {
use std::fs::File;
use std::io::Read;

View File

@@ -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<S: AsRef<str> = String>(Id<S>);
impl<S: AsRef<str>> std::fmt::Display for HealthCheckId<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -43,7 +43,7 @@ impl<S: AsRef<str>> AsRef<Path> for HealthCheckId<S> {
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct HealthChecks(pub IndexMap<HealthCheckId, HealthCheck>);
pub struct HealthChecks(pub BTreeMap<HealthCheckId, HealthCheck>);
impl HealthChecks {
pub async fn check_all(
&self,
@@ -52,7 +52,7 @@ impl HealthChecks {
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
) -> Result<IndexMap<HealthCheckId, HealthCheckResult>, Error> {
) -> Result<BTreeMap<HealthCheckId, HealthCheckResult>, Error> {
let res = futures::future::try_join_all(self.0.iter().map(|(id, check)| async move {
Ok::<_, Error>((
id.clone(),

View File

@@ -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::<IndexMap<PackageId, CurrentDependencyInfo>>()
.collect::<BTreeMap<PackageId, CurrentDependencyInfo>>()
}),
));
}
@@ -182,7 +181,7 @@ pub async fn check_all(ctx: &RpcContext) -> Result<(), Error> {
id: &PackageId,
statuses: Arc<HashMap<PackageId, MainStatus>>,
model: InstalledPackageDataEntryModel,
current_deps: Arc<IndexMap<PackageId, CurrentDependencyInfo>>,
current_deps: Arc<BTreeMap<PackageId, CurrentDependencyInfo>>,
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<Utc>,
health: IndexMap<HealthCheckId, HealthCheckResult>,
health: BTreeMap<HealthCheckId, HealthCheckResult>,
},
BackingUp {
started: Option<DateTime<Utc>>,
health: IndexMap<HealthCheckId, HealthCheckResult>,
health: BTreeMap<HealthCheckId, HealthCheckResult>,
},
Restoring {
running: bool,
@@ -394,7 +393,7 @@ impl MainStatus {
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct DependencyErrors(pub IndexMap<PackageId, DependencyError>);
pub struct DependencyErrors(pub BTreeMap<PackageId, DependencyError>);
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<PackageId, CurrentDependencyInfo>,
current_dependencies: &BTreeMap<PackageId, CurrentDependencyInfo>,
) -> Result<DependencyErrors, Error> {
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<PackageId, TaggedDependencyError>,
breakages: &'a mut BTreeMap<PackageId, TaggedDependencyError>,
) -> BoxFuture<'a, Result<(), Error>> {
async move {
let mut status = model.clone().status().get_mut(db).await?;

View File

@@ -704,7 +704,68 @@ impl<H: Digest, W: std::io::Write> std::io::Write for HashWriter<H, W> {
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub fn deserialize_number_permissive<
'de,
D: serde::de::Deserializer<'de>,
T: FromStr<Err = E> + num::cast::FromPrimitive,
E: std::fmt::Display,
>(
deserializer: D,
) -> std::result::Result<T, D::Error> {
use num::cast::FromPrimitive;
struct Visitor<T: FromStr<Err = E> + num::cast::FromPrimitive, E>(std::marker::PhantomData<T>);
impl<'de, T: FromStr<Err = Err> + num::cast::FromPrimitive, Err: std::fmt::Display>
serde::de::Visitor<'de> for Visitor<T, Err>
{
type Value = T;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "a parsable string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
v.parse().map_err(|e| serde::de::Error::custom(e))
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
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<E>(self, v: u64) -> Result<Self::Value, E>
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<E>(self, v: i64) -> Result<Self::Value, E>
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<D>(deserializer: D) -> Result<Self, D::Error>
@@ -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 {

View File

@@ -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<S: AsRef<str> = String> {
Backup,
Custom(Id<S>),
@@ -73,7 +73,7 @@ impl<S: AsRef<str>> Serialize for VolumeId<S> {
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Volumes(IndexMap<VolumeId, Volume>);
pub struct Volumes(BTreeMap<VolumeId, Volume>);
impl Volumes {
pub async fn install(
&self,
@@ -111,7 +111,7 @@ impl Volumes {
}
}
impl Deref for Volumes {
type Target = IndexMap<VolumeId, Volume>;
type Target = BTreeMap<VolumeId, Volume>;
fn deref(&self) -> &Self::Target {
&self.0
}
@@ -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)