switch to managers: wip

This commit is contained in:
Aiden McClelland
2021-07-13 16:55:05 -06:00
parent 36275f4a81
commit 7eaf6dabcc
26 changed files with 783 additions and 803 deletions

47
appmgr/Cargo.lock generated
View File

@@ -35,12 +35,6 @@ version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
[[package]]
name = "array_tool"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
[[package]]
name = "arrayref"
version = "0.3.6"
@@ -205,22 +199,21 @@ dependencies = [
[[package]]
name = "bollard"
version = "0.10.1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "699194c00f3a2effd3358d47f880646818e3d483190b17ebcdf598c654fb77e9"
checksum = "a4a3f238d4b66f33d9162893ade03cd8a485320f591b244ea5b7f236d3494e98"
dependencies = [
"base64 0.13.0",
"bollard-stubs",
"bytes 1.0.1",
"chrono",
"ct-logs",
"dirs-next",
"futures-core",
"futures-util",
"hex",
"http",
"hyper",
"hyper-unix-connector",
"hyperlocal",
"log",
"pin-project",
"serde",
@@ -500,15 +493,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "ct-logs"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8"
dependencies = [
"sct",
]
[[package]]
name = "curve25519-dalek"
version = "3.2.0"
@@ -684,7 +668,6 @@ dependencies = [
"futures",
"git-version",
"http",
"id-pool",
"indexmap",
"itertools 0.10.1",
"jsonpath_lib",
@@ -1157,27 +1140,18 @@ dependencies = [
]
[[package]]
name = "hyper-unix-connector"
version = "0.2.2"
name = "hyperlocal"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ef1fd95d34b4ff007d3f0590727b5cf33572cace09b42032fc817dc8b16557"
checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"
dependencies = [
"anyhow",
"futures-util",
"hex",
"hyper",
"pin-project",
"tokio 1.9.0",
]
[[package]]
name = "id-pool"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e33832e3000c359e3f67781634a5e6d58bffa8c5247c1464bd2e483f1a79cb0"
dependencies = [
"serde",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@@ -1275,12 +1249,10 @@ dependencies = [
[[package]]
name = "jsonpath_lib"
version = "0.2.6"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61352ec23883402b7d30b3313c16cbabefb8907361c4eb669d990cbb87ceee5a"
checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f"
dependencies = [
"array_tool",
"env_logger",
"log",
"serde",
"serde_json",
@@ -2747,6 +2719,7 @@ dependencies = [
"futures-core",
"pin-project-lite 0.2.7",
"tokio 1.9.0",
"tokio-util",
]
[[package]]

View File

@@ -47,7 +47,7 @@ anyhow = "1.0.40"
async-trait = "0.1.42"
avahi-sys = { git="https://github.com/Start9Labs/avahi-sys", version="0.10.0", branch="feature/dynamic-linking", features=["dynamic"], optional=true }
base32 = "0.4.0"
bollard = "0.10.1"
bollard = "0.11.0"
chrono = { version="0.4.19", features=["serde"] }
clap = "2.33"
digest = "0.9.0"
@@ -56,10 +56,9 @@ emver = { version="0.1.2", features=["serde"] }
futures = "0.3.8"
git-version = "0.3.4"
http = "0.2.3"
id-pool = { version="0.2.1", features=["u16", "serde"], default-features=false }
indexmap = { version="1.6.2", features=["serde"] }
itertools = "0.10.0"
jsonpath_lib = "0.2.6"
jsonpath_lib = "0.3.0"
lazy_static = "1.4"
libc = "0.2.86"
log = "0.4.11"
@@ -85,9 +84,9 @@ simple-logging = "2.0"
sqlx = { version="0.5", features=["runtime-tokio-rustls", "sqlite", "offline"] }
tar = "0.4.35"
thiserror = "1.0.24"
tokio = { version="1.5.0", features=["full"] }
tokio = { version="1.8.1", features=["full"] }
tokio-compat-02 = "0.2.0"
tokio-stream = { version="0.1.5", features=["io-util"] }
tokio-stream = { version="0.1.5", features=["io-util", "sync"] }
tokio-tar = "0.3.0"
tokio-util = { version="0.6.6", features=["io"] }
torut = "0.1.9"

View File

@@ -7,12 +7,13 @@ use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::id::ImageId;
use crate::net::host::Hosts;
use crate::id::{Id, ImageId};
use crate::s9pk::manifest::{PackageId, SYSTEM_PACKAGE_ID};
use crate::util::{Invoke, IoFormat, Version};
use crate::util::{IoFormat, Version};
use crate::volume::{VolumeId, Volumes};
use crate::{Error, ResultExt};
use crate::{Error, ResultExt, HOST_IP};
pub const NET_TLD: &'static str = "embassy";
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
@@ -33,33 +34,12 @@ pub struct DockerAction {
pub shm_size_mb: Option<usize>, // TODO: use postfix sizing? like 1k vs 1m vs 1g
}
impl DockerAction {
pub async fn create(
&self,
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
ip: Ipv4Addr,
) -> Result<(), Error> {
tokio::process::Command::new("docker")
.arg("create")
.arg("--net")
.arg("start9")
.arg("--ip")
.arg(format!("{}", ip))
.arg("--name")
.arg(Self::container_name(pkg_id, pkg_version))
.args(self.docker_args(pkg_id, pkg_version, volumes, false))
.invoke(crate::ErrorKind::Docker)
.await?;
Ok(())
}
pub async fn execute<I: Serialize, O: for<'de> Deserialize<'de>>(
&self,
pkg_id: &PackageId,
pkg_version: &Version,
name: Option<&str>,
volumes: &Volumes,
hosts: &Hosts,
input: Option<I>,
allow_inject: bool,
) -> Result<Result<O, (i32, String)>, Error> {
@@ -67,8 +47,12 @@ impl DockerAction {
if self.inject && allow_inject {
cmd.arg("exec");
} else {
cmd.arg("run").arg("--rm");
cmd.args(hosts.docker_args());
cmd.arg("run")
.arg("--rm")
.arg("--network=start9")
.arg(format!("--add-host=embassy:{}", Ipv4Addr::from(HOST_IP)))
.arg("--name")
.arg(Self::container_name(pkg_id, name));
}
cmd.args(self.docker_args(pkg_id, pkg_version, volumes, allow_inject));
let input_buf = if let (Some(input), Some(format)) = (&input, &self.io_format) {
@@ -126,8 +110,7 @@ impl DockerAction {
input: Option<I>,
) -> Result<Result<O, (i32, String)>, Error> {
let mut cmd = tokio::process::Command::new("docker");
cmd.arg("run").arg("--rm");
cmd.arg("--network=none");
cmd.arg("run").arg("--rm").arg("--network=none");
cmd.args(self.docker_args(pkg_id, pkg_version, &Volumes::default(), false));
let input_buf = if let (Some(input), Some(format)) = (&input, &self.io_format) {
cmd.stdin(std::process::Stdio::piped());
@@ -177,15 +160,22 @@ impl DockerAction {
})
}
pub fn container_name(pkg_id: &PackageId, version: &Version) -> String {
format!("service_{}_{}", pkg_id, version)
pub fn container_name(pkg_id: &PackageId, name: Option<&str>) -> String {
if let Some(name) = name {
format!("{}_{}.{}", pkg_id, name, NET_TLD)
} else {
format!("{}.{}", pkg_id, NET_TLD)
}
}
pub fn uncontainer_name(name: &str) -> Option<(&str, Version)> {
name.trim_start_matches("/")
.strip_prefix("service_")
.and_then(|name| name.split_once("_"))
.and_then(|(id, version)| Some((id, version.parse().ok()?)))
pub fn uncontainer_name<'a>(name: &'a str) -> Option<(PackageId<&'a str>, Option<&'a str>)> {
let (pre_tld, _) = name.split_once(".")?;
if pre_tld.contains("_") {
let (pkg, name) = name.split_once("_")?;
Some((Id::try_from(pkg).ok()?.into(), Some(name)))
} else {
Some((Id::try_from(pre_tld).ok()?.into(), None))
}
}
fn docker_args<'a>(
@@ -208,6 +198,10 @@ impl DockerAction {
continue;
};
let src = volume.path_for(pkg_id, pkg_version, volume_id);
if !src.exists() {
// TODO: this is a blocking call, make this async?
continue;
}
res.push(OsStr::new("--mount").into());
res.push(
dbg!(OsString::from(format!(
@@ -224,7 +218,7 @@ impl DockerAction {
res.push(OsString::from(format!("{}m", shm_size_mb)).into());
}
if self.inject && allow_inject {
res.push(OsString::from(Self::container_name(pkg_id, pkg_version)).into());
res.push(OsString::from(Self::container_name(pkg_id, None)).into());
res.push(OsStr::new(&self.entrypoint).into());
} else {
res.push(OsStr::new("--entrypoint").into());

View File

@@ -1,4 +1,3 @@
use std::net::Ipv4Addr;
use std::path::Path;
use anyhow::anyhow;
@@ -9,7 +8,6 @@ use serde::{Deserialize, Serialize};
use self::docker::DockerAction;
use crate::config::{Config, ConfigSpec};
use crate::id::Id;
use crate::net::host::Hosts;
use crate::s9pk::manifest::PackageId;
use crate::util::{ValuePrimative, Version};
use crate::volume::Volumes;
@@ -95,14 +93,20 @@ impl Action {
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
input: Config,
) -> Result<ActionResult, Error> {
self.input_spec
.matches(&input)
.with_kind(crate::ErrorKind::ConfigSpecViolation)?;
self.implementation
.execute(pkg_id, pkg_version, volumes, hosts, Some(input), true)
.execute(
pkg_id,
pkg_version,
Some(&format!("{}Action", self.name)),
volumes,
Some(input),
true,
)
.await?
.map_err(|e| Error::new(anyhow!("{}", e.1), crate::ErrorKind::Action))
}
@@ -115,32 +119,19 @@ pub enum ActionImplementation {
Docker(DockerAction),
}
impl ActionImplementation {
pub async fn install(
&self,
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
ip: Ipv4Addr,
) -> Result<(), Error> {
match self {
ActionImplementation::Docker(action) => {
action.create(pkg_id, pkg_version, volumes, ip).await
}
}
}
pub async fn execute<I: Serialize, O: for<'de> Deserialize<'de>>(
&self,
pkg_id: &PackageId,
pkg_version: &Version,
name: Option<&str>,
volumes: &Volumes,
hosts: &Hosts,
input: Option<I>,
allow_inject: bool,
) -> Result<Result<O, (i32, String)>, Error> {
match self {
ActionImplementation::Docker(action) => {
action
.execute(pkg_id, pkg_version, volumes, hosts, input, allow_inject)
.execute(pkg_id, pkg_version, name, volumes, input, allow_inject)
.await
}
}

View File

@@ -3,7 +3,6 @@ use patch_db::HasModel;
use serde::{Deserialize, Serialize};
use crate::action::ActionImplementation;
use crate::net::host::Hosts;
use crate::s9pk::manifest::PackageId;
use crate::util::Version;
use crate::volume::{Volume, VolumeId, Volumes};
@@ -15,17 +14,23 @@ pub struct BackupActions {
pub restore: ActionImplementation,
}
impl BackupActions {
pub async fn backup(
pub async fn create(
&self,
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
) -> Result<(), Error> {
let mut volumes = volumes.to_readonly();
volumes.insert(VolumeId::Backup, Volume::Backup { readonly: false });
self.create
.execute(pkg_id, pkg_version, &volumes, hosts, None::<()>, false)
.execute(
pkg_id,
pkg_version,
Some("CreateBackup"),
&volumes,
None::<()>,
false,
)
.await?
.map_err(|e| anyhow!("{}", e.1))
.with_kind(crate::ErrorKind::Backup)?;
@@ -37,12 +42,18 @@ impl BackupActions {
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
) -> Result<(), Error> {
let mut volumes = volumes.clone();
volumes.insert(VolumeId::Backup, Volume::Backup { readonly: true });
self.restore
.execute(pkg_id, pkg_version, &volumes, hosts, None::<()>, false)
.execute(
pkg_id,
pkg_version,
Some("RestoreBackup"),
&volumes,
None::<()>,
false,
)
.await?
.map_err(|e| anyhow!("{}", e.1))
.with_kind(crate::ErrorKind::Restore)?;

View File

@@ -7,7 +7,6 @@ use serde::{Deserialize, Serialize};
use super::{Config, ConfigSpec};
use crate::action::ActionImplementation;
use crate::dependencies::Dependencies;
use crate::net::host::Hosts;
use crate::s9pk::manifest::PackageId;
use crate::status::health_check::HealthCheckId;
use crate::util::Version;
@@ -32,10 +31,16 @@ impl ConfigActions {
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
) -> Result<ConfigRes, Error> {
self.get
.execute(pkg_id, pkg_version, volumes, hosts, None::<()>, false)
.execute(
pkg_id,
pkg_version,
Some("GetConfig"),
volumes,
None::<()>,
false,
)
.await
.and_then(|res| {
res.map_err(|e| Error::new(anyhow!("{}", e.1), crate::ErrorKind::ConfigGen))
@@ -48,12 +53,18 @@ impl ConfigActions {
pkg_version: &Version,
dependencies: &Dependencies,
volumes: &Volumes,
hosts: &Hosts,
input: &Config,
) -> Result<SetResult, Error> {
let res: SetResult = self
.set
.execute(pkg_id, pkg_version, volumes, hosts, Some(input), false)
.execute(
pkg_id,
pkg_version,
Some("SetConfig"),
volumes,
Some(input),
false,
)
.await
.and_then(|res| {
res.map_err(|e| {

View File

@@ -18,7 +18,6 @@ use crate::context::{EitherContext, ExtendedContext};
use crate::db::model::{CurrentDependencyInfo, InstalledPackageDataEntryModel};
use crate::db::util::WithRevision;
use crate::dependencies::{BreakageRes, DependencyError, TaggedDependencyError};
use crate::net::host::Hosts;
use crate::s9pk::manifest::PackageId;
use crate::util::{
display_none, display_serializable, parse_duration, parse_stdin_deserializable, IoFormat,
@@ -173,14 +172,7 @@ pub async fn get(
})?;
let version = pkg_model.clone().manifest().version().get(&mut db).await?;
let volumes = pkg_model.manifest().volumes().get(&mut db).await?;
let hosts = crate::db::DatabaseModel::new()
.network()
.hosts()
.get(&mut db)
.await?;
action
.get(ctx.extension(), &*version, &*volumes, &*hosts)
.await
action.get(ctx.extension(), &*version, &*volumes).await
}
#[command(subcommands(self(set_impl(async)), set_dry), display(display_none))]
@@ -209,17 +201,11 @@ pub async fn set_dry(
let (ctx, (id, config, timeout, _)) = ctx.split();
let rpc_ctx = ctx.as_rpc().unwrap();
let mut db = rpc_ctx.db.handle();
let hosts = crate::db::DatabaseModel::new()
.network()
.hosts()
.get(&mut db)
.await?;
let mut tx = db.begin().await?;
let mut breakages = IndexMap::new();
configure(
&mut tx,
&rpc_ctx.docker,
&*hosts,
&id,
config,
&timeout,
@@ -255,17 +241,11 @@ pub async fn set_impl(
let (ctx, (id, config, timeout, expire_id)) = ctx.split();
let rpc_ctx = ctx.as_rpc().unwrap();
let mut db = rpc_ctx.db.handle();
let hosts = crate::db::DatabaseModel::new()
.network()
.hosts()
.get(&mut db)
.await?;
let mut tx = db.begin().await?;
let mut breakages = IndexMap::new();
configure(
&mut tx,
&rpc_ctx.docker,
&*hosts,
&id,
config,
&timeout,
@@ -295,7 +275,6 @@ pub async fn set_impl(
pub fn configure<'a, Db: DbHandle>(
db: &'a mut Db,
docker: &'a Docker,
hosts: &'a Hosts,
id: &'a PackageId,
config: Option<Config>,
timeout: &'a Option<Duration>,
@@ -330,7 +309,7 @@ pub fn configure<'a, Db: DbHandle>(
let ConfigRes {
config: old_config,
spec,
} = action.get(id, &*version, &*volumes, &*hosts).await?;
} = action.get(id, &*version, &*volumes).await?;
// determine new config to use
let mut config = if let Some(config) = config.or_else(|| old_config.clone()) {
@@ -379,7 +358,7 @@ pub fn configure<'a, Db: DbHandle>(
let signal = if !dry_run {
// run config action
let res = action
.set(id, &*version, &*dependencies, &*volumes, hosts, &config)
.set(id, &*version, &*dependencies, &*volumes, &config)
.await?;
// track dependencies with no pointers
@@ -539,8 +518,7 @@ pub fn configure<'a, Db: DbHandle>(
if let PackagePointerSpecVariant::Config { selector, multi } = ptr {
if selector.select(*multi, &next) != selector.select(*multi, &prev) {
if let Err(e) = configure(
db, docker, hosts, dependent, None, timeout, dry_run, overrides,
breakages,
db, docker, dependent, None, timeout, dry_run, overrides, breakages,
)
.await
{
@@ -575,7 +553,7 @@ pub fn configure<'a, Db: DbHandle>(
if let Some(signal) = signal {
docker
.kill_container(
&DockerAction::container_name(id, &*version),
&DockerAction::container_name(id, None),
Some(KillContainerOptions {
signal: signal.to_string(),
}),
@@ -586,6 +564,7 @@ pub fn configure<'a, Db: DbHandle>(
if matches!(
e,
bollard::errors::Error::DockerResponseConflictError { .. }
| bollard::errors::Error::DockerResponseNotFoundError { .. }
) {
Ok(())
} else {

View File

@@ -1562,9 +1562,7 @@ impl PackagePointerSpec {
.package_data()
.idx_model(&self.package_id)
.and_then(|pde| pde.installed())
.and_then(|installed| {
installed.interface_info().addresses().idx_model(interface)
})
.and_then(|installed| installed.interface_addresses().idx_model(interface))
.and_then(|addresses| addresses.tor_address())
.get(db)
.await
@@ -1576,9 +1574,7 @@ impl PackagePointerSpec {
.package_data()
.idx_model(&self.package_id)
.and_then(|pde| pde.installed())
.and_then(|installed| {
installed.interface_info().addresses().idx_model(interface)
})
.and_then(|installed| installed.interface_addresses().idx_model(interface))
.and_then(|addresses| addresses.lan_address())
.get(db)
.await
@@ -1612,17 +1608,11 @@ impl PackagePointerSpec {
.get(db)
.await
.map_err(|e| ConfigurationError::SystemError(Error::from(e)))?;
let hosts = crate::db::DatabaseModel::new()
.network()
.hosts()
.get(db)
.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(&self.package_id, version, volumes, &*hosts)
.get(&self.package_id, version, volumes)
.await
.map_err(|e| ConfigurationError::SystemError(Error::from(e)))?;
if let Some(cfg) = cfg_res.config {

View File

@@ -12,10 +12,9 @@ use serde::Deserialize;
use sqlx::SqlitePool;
use tokio::fs::File;
#[cfg(feature = "avahi")]
use crate::net::mdns::MdnsController;
use crate::net::tor::TorController;
use crate::util::{from_toml_async_reader, AsyncFileExt, Container};
use crate::manager::ManagerMap;
use crate::net::NetController;
use crate::util::{from_toml_async_reader, AsyncFileExt};
use crate::{Error, ResultExt};
#[derive(Debug, Default, Deserialize)]
@@ -34,9 +33,8 @@ pub struct RpcContextSeed {
pub db: PatchDb,
pub secret_store: SqlitePool,
pub docker: Docker,
pub tor_controller: TorController,
#[cfg(feature = "avahi")]
pub mdns_controller: MdnsController,
pub net_controller: Arc<NetController>,
pub managers: ManagerMap,
}
#[derive(Clone)]
@@ -67,24 +65,27 @@ impl RpcContext {
.display()
))
.await?;
let mut db_handle = db.handle();
let tor_controller = TorController::init(
base.tor_control.unwrap_or(([127, 0, 0, 1], 9051).into()),
&mut db_handle,
let net_controller = Arc::new(
NetController::init(
base.tor_control
.unwrap_or(SocketAddr::from(([127, 0, 0, 1], 9051))),
)
.await?,
);
let managers = ManagerMap::init(
&mut db.handle(),
&mut secret_store.acquire().await?,
&*net_controller,
)
.await?;
#[cfg(feature = "avahi")]
let mdns_controller = MdnsController::init(&mut db_handle).await?;
let seed = Arc::new(RpcContextSeed {
bind_rpc: base.bind_rpc.unwrap_or(([127, 0, 0, 1], 5959).into()),
bind_ws: base.bind_ws.unwrap_or(([127, 0, 0, 1], 5960).into()),
db,
secret_store,
docker: Docker::connect_with_unix_defaults()?,
tor_controller,
#[cfg(feature = "avahi")]
mdns_controller,
net_controller,
managers,
});
Ok(Self(seed))
}

View File

@@ -11,7 +11,6 @@ use serde_json::Value;
use crate::config::spec::{PackagePointerSpecVariant, SystemPointerSpec};
use crate::install::progress::InstallProgress;
use crate::net::interface::InterfaceId;
use crate::net::Network;
use crate::s9pk::manifest::{Manifest, ManifestModel, PackageId};
use crate::status::health_check::HealthCheckId;
use crate::status::Status;
@@ -26,8 +25,6 @@ pub struct Database {
#[model]
pub package_data: AllPackageData,
pub broken_packages: Vec<PackageId>,
#[model]
pub network: Network,
pub ui: Value,
}
impl Database {
@@ -48,7 +45,6 @@ impl Database {
},
package_data: AllPackageData::default(),
broken_packages: Vec::new(),
network: Network::default(),
ui: Value::Object(Default::default()),
}
}
@@ -160,7 +156,7 @@ pub struct InstalledPackageDataEntry {
#[model]
pub current_dependencies: IndexMap<PackageId, CurrentDependencyInfo>,
#[model]
pub interface_info: InterfaceInfo,
pub interface_addresses: InterfaceAddressMap,
}
impl InstalledPackageDataEntryModel {
pub fn manifest(self) -> ManifestModel {
@@ -177,14 +173,6 @@ pub struct CurrentDependencyInfo {
pub health_checks: IndexSet<HealthCheckId>,
}
#[derive(Debug, Deserialize, Serialize, HasModel)]
#[serde(rename_all = "kebab-case")]
pub struct InterfaceInfo {
pub ip: Ipv4Addr,
#[model]
pub addresses: InterfaceAddressMap,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct InterfaceAddressMap(pub IndexMap<InterfaceId, InterfaceAddresses>);
impl Map for InterfaceAddressMap {

View File

@@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
use crate::action::ActionImplementation;
use crate::config::{Config, ConfigSpec};
use crate::net::host::Hosts;
use crate::net::interface::InterfaceId;
use crate::s9pk::manifest::PackageId;
use crate::status::health_check::{HealthCheckId, HealthCheckResult, HealthCheckResultVariant};
@@ -137,38 +136,31 @@ impl DepInfo {
dependent_id: &PackageId,
dependent_version: &Version,
) -> Result<Result<(), DependencyError>, Error> {
let dependency = crate::db::DatabaseModel::new()
let (manifest, info) = if let Some(dep_model) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(dependency_id)
.and_then(|pde| pde.installed())
.get(db)
.await?;
let info = if let Some(info) = &*dependency {
info
.check(db)
.await?
{
(
dep_model.clone().manifest().get(db).await?,
dep_model.get(db).await?,
)
} else {
return Ok(Err(DependencyError::NotInstalled));
};
if !&info.manifest.version.satisfies(&self.version) {
if !&manifest.version.satisfies(&self.version) {
return Ok(Err(DependencyError::IncorrectVersion {
expected: self.version.clone(),
received: info.manifest.version.clone(),
received: manifest.version.clone(),
}));
}
let hosts = crate::db::DatabaseModel::new()
.network()
.hosts()
.get(db)
.await?;
let dependency_config = if let Some(cfg) = dependency_config {
cfg
} else if let Some(cfg_info) = &info.manifest.config {
} else if let Some(cfg_info) = &manifest.config {
cfg_info
.get(
dependency_id,
&info.manifest.version,
&info.manifest.volumes,
&hosts,
)
.get(dependency_id, &manifest.version, &manifest.volumes)
.await?
.config
.unwrap_or_default()

View File

@@ -46,6 +46,7 @@ pub enum ErrorKind {
InvalidRequest = 38,
MigrationFailed = 39,
Uninitialized = 40,
ParseNetAddress = 41,
}
impl ErrorKind {
pub fn as_str(&self) -> &'static str {
@@ -91,6 +92,7 @@ impl ErrorKind {
InvalidRequest => "Invalid Request",
MigrationFailed => "Migration Failed",
Uninitialized => "Uninitialized",
ParseNetAddress => "Net Address Parsing Error",
}
}
}
@@ -180,6 +182,11 @@ impl From<torut::control::ConnError> for Error {
Error::new(anyhow!("{:?}", e), ErrorKind::Tor)
}
}
impl From<std::net::AddrParseError> for Error {
fn from(e: std::net::AddrParseError) -> Self {
Error::new(e, ErrorKind::ParseNetAddress)
}
}
impl From<Error> for RpcError {
fn from(e: Error) -> Self {
let mut data_object = serde_json::Map::with_capacity(2);

View File

@@ -364,23 +364,12 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
let mut tx = db.begin().await?;
let mut sql_tx = ctx.secret_store.begin().await?;
let mut network = crate::db::DatabaseModel::new()
.network()
.get_mut(&mut tx)
.await?;
log::info!("Install {}@{}: Installing main", pkg_id, version);
let ip = network.register_host(&manifest.id)?;
manifest
.main
.install(pkg_id, version, &manifest.volumes, ip)
.await?;
let hosts = network.hosts.clone();
network.save(&mut tx).await?;
log::info!("Install {}@{}: Installed main", pkg_id, version);
log::info!("Install {}@{}: Creating manager", pkg_id, version);
todo!("create manager");
log::info!("Install {}@{}: Created manager", pkg_id, version);
log::info!("Install {}@{}: Installing interfaces", pkg_id, version);
let interface_info = manifest.interfaces.install(&mut sql_tx, pkg_id, ip).await?;
let interface_addresses = manifest.interfaces.install(&mut sql_tx, pkg_id).await?;
log::info!("Install {}@{}: Installed interfaces", pkg_id, version);
let static_files = StaticFiles::local(pkg_id, version, manifest.assets.icon_type());
@@ -429,7 +418,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
deps
},
current_dependencies,
interface_info,
interface_addresses,
};
let mut pde = model.get_mut(&mut tx).await?;
let prev = std::mem::replace(
@@ -455,7 +444,6 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
pkg_id,
&prev_manifest.version,
&prev_manifest.volumes,
&hosts,
)
.await?
{
@@ -464,13 +452,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
// cleanup(pkg_id, Some(prev)).await?;
if let Some(res) = manifest
.migrations
.from(
&prev_manifest.version,
pkg_id,
version,
&manifest.volumes,
&hosts,
)
.from(&prev_manifest.version, pkg_id, version, &manifest.volumes)
.await?
{
configured &= res.configured;
@@ -479,7 +461,6 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
crate::config::configure(
&mut tx,
&ctx.docker,
&hosts,
pkg_id,
None,
&None,
@@ -492,16 +473,6 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
}
}
log::info!("Install {}@{}: Syncing Tor", pkg_id, version);
ctx.tor_controller.sync(&mut tx, &mut sql_tx).await?;
log::info!("Install {}@{}: Synced Tor", pkg_id, version);
#[cfg(feature = "avahi")]
{
log::info!("Install {}@{}: Syncing MDNS", pkg_id, version);
ctx.mdns_controller.sync(&mut tx).await?;
log::info!("Install {}@{}: Synced MDNS", pkg_id, version);
}
tx.commit(None).await?;
log::info!("Install {}@{}: Complete", pkg_id, version);

View File

@@ -27,6 +27,7 @@ pub mod error;
pub mod id;
pub mod inspect;
pub mod install;
pub mod manager;
pub mod migration;
pub mod net;
pub mod registry;

236
appmgr/src/manager/mod.rs Normal file
View File

@@ -0,0 +1,236 @@
use std::collections::HashMap;
use std::future::Future;
use std::net::Ipv4Addr;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use std::task::Poll;
use std::time::Duration;
use anyhow::anyhow;
use bollard::Docker;
use patch_db::{DbHandle, PatchDbHandle};
use sqlx::{Executor, Sqlite};
use tokio::sync::watch::error::RecvError;
use tokio::sync::watch::{channel, Receiver, Sender};
use tokio::sync::RwLock;
use tokio::task::JoinHandle;
use tokio_stream::wrappers::WatchStream;
use torut::onion::TorSecretKeyV3;
use crate::action::docker::DockerAction;
use crate::context::RpcContext;
use crate::net::interface::InterfaceId;
use crate::net::mdns::MdnsController;
use crate::net::tor::TorController;
use crate::net::NetController;
use crate::s9pk::manifest::{Manifest, PackageId};
use crate::util::Version;
use crate::{Error, ResultExt};
pub struct ManagerMap(RwLock<HashMap<(PackageId, Version), Arc<Manager>>>);
impl ManagerMap {
pub async fn init<Db: DbHandle, Ex>(
db: &mut Db,
secrets: &mut Ex,
net_ctl: &NetController,
) -> Result<Self, Error>
where
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
{
todo!()
}
pub async fn add(
&self,
docker: Docker,
net_ctl: Arc<NetController>,
manifest: Manifest,
tor_keys: HashMap<InterfaceId, TorSecretKeyV3>,
) -> Result<(), Error> {
let mut lock = self.0.write().await;
let id = (manifest.id.clone(), manifest.version.clone());
if lock.contains_key(&id) {
return Ok(());
}
lock.insert(
id,
Arc::new(Manager::create(docker, net_ctl, manifest, tor_keys).await?),
);
Ok(())
}
pub async fn remove(&self, id: &(PackageId, Version)) {
self.0.write().await.remove(id);
}
pub async fn get(&self, id: &(PackageId, Version)) -> Option<Arc<Manager>> {
self.0.read().await.get(id).cloned()
}
}
pub struct Manager {
on_stop: Sender<OnStop>,
thread: JoinHandle<()>,
}
#[derive(Clone, Copy)]
pub enum OnStop {
Restart,
Sleep,
Exit,
}
async fn run_main(
docker: &Docker,
net_ctl: &NetController,
manifest: &Manifest,
tor_keys: &HashMap<InterfaceId, TorSecretKeyV3>,
) -> Result<Result<(), (i32, String)>, Error> {
let rt_manifest = manifest.clone();
let mut runtime = tokio::spawn(async move {
rt_manifest
.main
.execute::<(), ()>(
&rt_manifest.id,
&rt_manifest.version,
None,
&rt_manifest.volumes,
None,
false,
)
.await
});
let mut ip = None::<Ipv4Addr>;
loop {
match docker
.inspect_container(&DockerAction::container_name(&manifest.id, None), None)
.await
{
Ok(res) => {
ip = res
.network_settings
.and_then(|ns| ns.networks)
.and_then(|mut n| n.remove("start9"))
.and_then(|es| es.ip_address)
.map(|ip| ip.parse())
.transpose()?;
break;
}
Err(bollard::errors::Error::DockerResponseNotFoundError { .. }) => (),
Err(e) => Err(e)?,
}
match futures::poll!(&mut runtime) {
Poll::Ready(res) => {
return res
.map_err(|e| {
Error::new(
anyhow!("Manager runtime panicked!"),
crate::ErrorKind::Docker,
)
})
.and_then(|a| a)
}
_ => (),
}
}
let ip = ip.ok_or_else(|| {
Error::new(
anyhow!("inspect did not return ip"),
crate::ErrorKind::Docker,
)
})?;
net_ctl
.add(
&manifest.id,
ip,
manifest
.interfaces
.0
.iter()
.map(|(id, info)| {
Ok((
id.clone(),
info,
tor_keys
.get(id)
.ok_or_else(|| {
Error::new(
anyhow!("interface {} missing key", id),
crate::ErrorKind::Tor,
)
})?
.clone(),
))
})
.collect::<Result<Vec<_>, Error>>()?,
)
.await?;
let res = runtime
.await
.map_err(|e| {
Error::new(
anyhow!("Manager runtime panicked!"),
crate::ErrorKind::Docker,
)
})
.and_then(|a| a);
net_ctl.remove(&manifest.id, manifest.interfaces.0.keys().cloned());
res
}
impl Manager {
async fn create(
docker: Docker,
net_ctl: Arc<NetController>,
manifest: Manifest,
tor_keys: HashMap<InterfaceId, TorSecretKeyV3>,
) -> Result<Self, Error> {
let (on_stop, mut recv) = channel(OnStop::Sleep);
let thread = tokio::spawn(async move {
loop {
fn handle_stop_action<'a>(
recv: &'a mut Receiver<OnStop>,
) -> (
OnStop,
Option<impl Future<Output = Result<(), RecvError>> + 'a>,
) {
let val = *recv.borrow_and_update();
match val {
OnStop::Sleep => (OnStop::Sleep, Some(recv.changed())),
a => (a, None),
}
}
let (stop_action, fut) = handle_stop_action(&mut recv);
match stop_action {
OnStop::Sleep => {
if let Some(fut) = fut {
fut.await.unwrap();
continue;
}
}
OnStop::Exit => {
break;
}
OnStop::Restart => (),
}
match run_main(&docker, &*net_ctl, &manifest, &tor_keys).await {
Ok(Ok(())) => break,
Ok(Err(e)) => {
todo!("application crashed")
}
Err(e) => {
todo!("failed to start application")
}
}
}
});
Ok(Manager { on_stop, thread })
}
}
impl Drop for Manager {
fn drop(&mut self) {
let _ = self.on_stop.send(OnStop::Exit);
}
}

View File

@@ -5,9 +5,7 @@ use patch_db::HasModel;
use serde::{Deserialize, Serialize};
use crate::action::ActionImplementation;
use crate::net::host::Hosts;
use crate::s9pk::manifest::PackageId;
use crate::status::health_check::HealthCheckId;
use crate::util::Version;
use crate::volume::Volumes;
use crate::Error;
@@ -25,7 +23,6 @@ impl Migrations {
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
) -> Result<Option<MigrationRes>, Error> {
Ok(
if let Some((_, migration)) = self
@@ -35,7 +32,14 @@ impl Migrations {
{
Some(
migration
.execute(pkg_id, pkg_version, volumes, hosts, Some(version), false)
.execute(
pkg_id,
pkg_version,
Some("Migration"), // Migrations cannot be executed concurrently
volumes,
Some(version),
false,
)
.await?
.map_err(|e| {
Error::new(anyhow!("{}", e.1), crate::ErrorKind::MigrationFailed)
@@ -52,7 +56,6 @@ impl Migrations {
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
) -> Result<Option<MigrationRes>, Error> {
Ok(
if let Some((_, migration)) =
@@ -60,7 +63,14 @@ impl Migrations {
{
Some(
migration
.execute(pkg_id, pkg_version, volumes, hosts, Some(version), false)
.execute(
pkg_id,
pkg_version,
Some("Migration"),
volumes,
Some(version),
false,
)
.await?
.map_err(|e| {
Error::new(anyhow!("{}", e.1), crate::ErrorKind::MigrationFailed)

View File

@@ -1,24 +0,0 @@
use std::ffi::{OsStr, OsString};
use std::net::Ipv4Addr;
use indexmap::IndexMap;
use patch_db::DbHandle;
use serde::{Deserialize, Serialize};
use crate::s9pk::manifest::PackageId;
use crate::{Error, HOST_IP};
pub const TLD: &'static str = "embassy";
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Hosts(pub IndexMap<PackageId, Ipv4Addr>);
impl Hosts {
pub fn docker_args(&self) -> Vec<OsString> {
let mut res = Vec::with_capacity(self.0.len() + 1);
res.push(format!("--add-host={}:{}", TLD, Ipv4Addr::from(HOST_IP)).into());
for (id, ip) in &self.0 {
res.push(format!("--add-host={}.{}:{}", id, TLD, ip).into());
}
res
}
}

View File

@@ -1,4 +1,3 @@
use std::net::Ipv4Addr;
use std::path::Path;
use indexmap::IndexMap;
@@ -6,7 +5,7 @@ use serde::{Deserialize, Deserializer, Serialize};
use sqlx::{Executor, Sqlite};
use torut::onion::TorSecretKeyV3;
use crate::db::model::{InterfaceAddressMap, InterfaceAddresses, InterfaceInfo};
use crate::db::model::{InterfaceAddressMap, InterfaceAddresses};
use crate::id::Id;
use crate::s9pk::manifest::PackageId;
use crate::util::Port;
@@ -20,15 +19,11 @@ impl Interfaces {
&self,
secrets: &mut Ex,
package_id: &PackageId,
ip: Ipv4Addr,
) -> Result<InterfaceInfo, Error>
) -> Result<InterfaceAddressMap, Error>
where
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
{
let mut interface_info = InterfaceInfo {
ip,
addresses: InterfaceAddressMap(IndexMap::new()),
};
let mut interface_addresses = InterfaceAddressMap(IndexMap::new());
for (id, iface) in &self.0 {
let mut addrs = InterfaceAddresses {
tor_address: None,
@@ -54,9 +49,9 @@ impl Interfaces {
Some(format!("{}.local", onion.get_address_without_dot_onion()));
}
}
interface_info.addresses.0.insert(id.clone(), addrs);
interface_addresses.0.insert(id.clone(), addrs);
}
Ok(interface_info)
Ok(interface_addresses)
}
}

View File

@@ -1,93 +1,77 @@
use std::collections::HashMap;
use avahi_sys::{
self, avahi_client_free, avahi_entry_group_commit, avahi_entry_group_free,
avahi_entry_group_reset, avahi_free, AvahiClient, AvahiEntryGroup,
self, avahi_entry_group_commit, avahi_entry_group_free, avahi_entry_group_reset, avahi_free,
AvahiEntryGroup,
};
use libc::c_void;
use patch_db::{DbHandle, OptionModel};
use tokio::sync::RwLock;
use tokio::sync::Mutex;
use torut::onion::TorSecretKeyV3;
use super::interface::InterfaceId;
use crate::s9pk::manifest::PackageId;
use crate::util::Apply;
use crate::Error;
pub struct MdnsController(RwLock<MdnsControllerInner>);
pub struct MdnsController(Mutex<MdnsControllerInner>);
impl MdnsController {
pub async fn init<Db: DbHandle>(db: &mut Db) -> Result<Self, Error> {
Ok(MdnsController(RwLock::new(
MdnsControllerInner::init(db).await?,
)))
pub fn init() -> Self {
MdnsController(Mutex::new(MdnsControllerInner::init()))
}
pub async fn sync<Db: DbHandle>(&self, db: &mut Db) -> Result<(), Error> {
self.0.write().await.sync(db).await
pub async fn add<'a, I: IntoIterator<Item = (InterfaceId, TorSecretKeyV3)>>(
&self,
pkg_id: &PackageId,
interfaces: I,
) {
self.0.lock().await.add(pkg_id, interfaces)
}
pub async fn remove<I: IntoIterator<Item = InterfaceId>>(
&self,
pkg_id: &PackageId,
interfaces: I,
) {
self.0.lock().await.remove(pkg_id, interfaces)
}
}
pub struct MdnsControllerInner {
hostname: Vec<u8>,
entry_group: *mut AvahiEntryGroup,
services: HashMap<(PackageId, InterfaceId), TorSecretKeyV3>,
}
unsafe impl Send for MdnsControllerInner {}
unsafe impl Sync for MdnsControllerInner {}
impl MdnsControllerInner {
async fn load_services<Db: DbHandle>(&mut self, db: &mut Db) -> Result<(), Error> {
fn load_services(&mut self) {
unsafe {
for app_id in crate::db::DatabaseModel::new()
.package_data()
.keys(db)
.await?
{
let iface_model = if let Some(model) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&app_id)
.expect(db)
.await?
.installed()
.map(|i| i.interface_info().addresses())
.apply(OptionModel::from)
.check(db)
.await?
{
model
} else {
continue;
};
for iface in iface_model.keys(db).await? {
let lan_address = if let Some(addr) = iface_model
.clone()
.idx_model(&iface)
.expect(db)
.await?
.lan_address()
.get(db)
.await?
.to_owned()
{
addr
} else {
continue;
};
let lan_address_ptr = std::ffi::CString::new(lan_address)
.expect("Could not cast lan address to c string");
let _ = avahi_sys::avahi_entry_group_add_record(
self.entry_group,
avahi_sys::AVAHI_IF_UNSPEC,
avahi_sys::AVAHI_PROTO_UNSPEC,
avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_USE_MULTICAST
| avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_ALLOW_MULTIPLE,
lan_address_ptr.as_ptr(),
avahi_sys::AVAHI_DNS_CLASS_IN as u16,
avahi_sys::AVAHI_DNS_TYPE_CNAME as u16,
avahi_sys::AVAHI_DEFAULT_TTL,
self.hostname.as_ptr().cast(),
self.hostname.len(),
);
log::info!("Published {:?}", lan_address_ptr);
}
for key in self.services.values() {
let lan_address = key
.public()
.get_onion_address()
.get_address_without_dot_onion()
+ ".local";
let lan_address_ptr = std::ffi::CString::new(lan_address)
.expect("Could not cast lan address to c string");
let _ = avahi_sys::avahi_entry_group_add_record(
self.entry_group,
avahi_sys::AVAHI_IF_UNSPEC,
avahi_sys::AVAHI_PROTO_UNSPEC,
avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_USE_MULTICAST
| avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_ALLOW_MULTIPLE,
lan_address_ptr.as_ptr(),
avahi_sys::AVAHI_DNS_CLASS_IN as u16,
avahi_sys::AVAHI_DNS_TYPE_CNAME as u16,
avahi_sys::AVAHI_DEFAULT_TTL,
self.hostname.as_ptr().cast(),
self.hostname.len(),
);
log::info!("Published {:?}", lan_address_ptr);
}
}
Ok(())
}
async fn init<Db: DbHandle>(db: &mut Db) -> Result<Self, Error> {
fn init() -> Self {
unsafe {
// let app_list = crate::apps::list_info().await?;
@@ -118,22 +102,39 @@ impl MdnsControllerInner {
hostname_buf[0] = (buflen - 8) as u8; // set the prefix length to len - 8 (leading byte, .local, nul) for the main address
hostname_buf[buflen - 7] = 5; // set the prefix length to 5 for "local"
let mut ctrl = MdnsControllerInner {
avahi_entry_group_commit(group);
MdnsControllerInner {
hostname: hostname_buf,
entry_group: group,
};
ctrl.load_services(db).await?;
avahi_entry_group_commit(group);
Ok(ctrl)
services: HashMap::new(),
}
}
}
async fn sync<Db: DbHandle>(&mut self, db: &mut Db) -> Result<(), Error> {
fn sync(&mut self) {
unsafe {
avahi_entry_group_reset(self.entry_group);
self.load_services(db).await?;
self.load_services();
avahi_entry_group_commit(self.entry_group);
}
Ok(())
}
fn add<'a, I: IntoIterator<Item = (InterfaceId, TorSecretKeyV3)>>(
&self,
pkg_id: &PackageId,
interfaces: I,
) {
self.services.extend(
interfaces
.into_iter()
.map(|(interface_id, key)| ((pkg_id.clone(), interface_id), key)),
);
self.sync();
}
fn remove<I: IntoIterator<Item = InterfaceId>>(&self, pkg_id: &PackageId, interfaces: I) {
for interface_id in interfaces {
self.services.remove(&(pkg_id.clone(), interface_id));
}
self.sync();
}
}
impl Drop for MdnsControllerInner {

View File

@@ -1,63 +1,72 @@
use std::net::Ipv4Addr;
use std::net::{Ipv4Addr, SocketAddr};
use anyhow::anyhow;
use id_pool::IdPool;
use patch_db::HasModel;
use serde::{Deserialize, Serialize};
use torut::onion::TorSecretKeyV3;
use self::host::Hosts;
use self::interface::{Interface, InterfaceId};
#[cfg(feature = "avahi")]
use self::mdns::MdnsController;
use self::tor::TorController;
use crate::s9pk::manifest::PackageId;
use crate::{Error, ResultExt};
pub mod host;
pub mod interface;
#[cfg(feature = "avahi")]
pub mod mdns;
pub mod tor;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IpPool(IdPool);
impl IpPool {
pub fn new() -> Self {
let pool = IdPool::new();
IpPool(pool)
pub struct NetController {
tor: TorController,
#[cfg(feature = "avahi")]
mdns: MdnsController,
// nginx: NginxController, // TODO
}
impl NetController {
pub async fn init(tor_control: SocketAddr) -> Result<Self, Error> {
Ok(Self {
tor: TorController::init(tor_control).await?,
#[cfg(feature = "avahi")]
mdns: MdnsController::init(),
})
}
pub fn get(&mut self) -> Option<Ipv4Addr> {
let id = self.0.request_id()?;
let ip = u32::from_be_bytes(crate::HOST_IP) + id as u32;
Some(ip.into())
pub async fn add<
'a,
I: IntoIterator<Item = (InterfaceId, &'a Interface, TorSecretKeyV3)> + Clone,
>(
&self,
pkg_id: &PackageId,
ip: Ipv4Addr,
interfaces: I,
) -> Result<(), Error> {
let (tor_res, _) = tokio::join!(self.tor.add(pkg_id, ip, interfaces.clone()), {
#[cfg(feature = "avahi")]
let mdns_fut = self.mdns.add(
pkg_id,
interfaces
.into_iter()
.map(|(interface_id, _, key)| (interface_id, key)),
);
#[cfg(not(feature = "avahi"))]
let mdns_fut = futures::future::ready(());
mdns_fut
},);
tor_res?;
Ok(())
}
pub fn put(&mut self, ip: Ipv4Addr) {
let ip = u32::from_be_bytes(ip.octets());
let id = ip - u32::from_be_bytes(crate::HOST_IP);
let _ = self.0.return_id(id as u16);
}
}
impl Default for IpPool {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
pub struct Network {
pub ip_pool: IpPool,
pub hosts: Hosts,
}
impl Network {
pub fn register_host(&mut self, id: &PackageId) -> Result<Ipv4Addr, Error> {
if let Some(exists) = self.hosts.0.get(id) {
Ok(*exists)
} else {
let ip = self
.ip_pool
.get()
.ok_or_else(|| anyhow!("No available IP addresses"))
.with_kind(crate::ErrorKind::Network)?;
self.hosts.0.insert(id.clone(), ip);
Ok(ip)
}
pub async fn remove<I: IntoIterator<Item = InterfaceId> + Clone>(
&self,
pkg_id: &PackageId,
interfaces: I,
) -> Result<(), Error> {
let (tor_res, _) = tokio::join!(self.tor.remove(pkg_id, interfaces.clone()), {
#[cfg(feature = "avahi")]
let mdns_fut = self.mdns.remove(pkg_id, interfaces);
#[cfg(not(feature = "avahi"))]
let mdns_fut = futures::future::ready(());
mdns_fut
});
tor_res?;
Ok(())
}
}

View File

@@ -1,48 +1,48 @@
use std::collections::HashMap;
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use anyhow::anyhow;
use futures::future::BoxFuture;
use futures::FutureExt;
use indexmap::IndexMap;
use patch_db::DbHandle;
use sqlx::{Executor, Sqlite};
use tokio::net::TcpStream;
use tokio::sync::RwLock;
use tokio::sync::Mutex;
use torut::control::{AsyncEvent, AuthenticatedConn, ConnError};
use torut::onion::TorSecretKeyV3;
use super::interface::TorConfig;
use super::interface::{Interface, InterfaceId, TorConfig};
use crate::s9pk::manifest::PackageId;
use crate::{Error, ResultExt as _};
fn event_handler(event: AsyncEvent<'static>) -> BoxFuture<'static, Result<(), ConnError>> {
async move { Ok(()) }.boxed()
}
pub struct TorController(RwLock<TorControllerInner>);
pub struct TorController(Mutex<TorControllerInner>);
impl TorController {
pub async fn init<Db: DbHandle, Ex>(
tor_cp: SocketAddr,
db: &mut Db,
secrets: &mut Ex,
) -> Result<Self, Error>
where
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
{
Ok(TorController(RwLock::new(
TorControllerInner::init(tor_cp, db, secrets).await?,
pub async fn init(tor_control: SocketAddr) -> Result<Self, Error> {
Ok(TorController(Mutex::new(
TorControllerInner::init(tor_control).await?,
)))
}
pub async fn sync<Db: DbHandle, Ex>(&self, db: &mut Db, secrets: &mut Ex) -> Result<(), Error>
where
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
{
let new = TorControllerInner::get_services(db, secrets).await?;
if &new != &self.0.read().await.services {
self.0.write().await.sync(new).await?;
}
Ok(())
pub async fn add<
'a,
I: IntoIterator<Item = (InterfaceId, &'a Interface, TorSecretKeyV3)> + Clone,
>(
&self,
pkg_id: &PackageId,
ip: Ipv4Addr,
interfaces: I,
) -> Result<(), Error> {
self.0.lock().await.add(pkg_id, ip, interfaces).await
}
pub async fn remove<I: IntoIterator<Item = InterfaceId> + Clone>(
&self,
pkg_id: &PackageId,
interfaces: I,
) -> Result<(), Error> {
self.0.lock().await.remove(pkg_id, interfaces).await
}
}
@@ -59,149 +59,70 @@ struct HiddenServiceConfig {
pub struct TorControllerInner {
connection: AuthenticatedConnection,
services: IndexMap<[u8; 64], HiddenServiceConfig>,
services: HashMap<(PackageId, InterfaceId), TorSecretKeyV3>,
}
impl TorControllerInner {
async fn get_services<Db: DbHandle, Ex>(
db: &mut Db,
secrets: &mut Ex,
) -> Result<IndexMap<[u8; 64], HiddenServiceConfig>, Error>
where
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
{
let pkg_ids = crate::db::DatabaseModel::new()
.package_data()
.keys(db)
.await?;
let mut services = IndexMap::new();
for pkg_id in pkg_ids {
if let Some(installed) = crate::db::DatabaseModel::new()
.package_data()
.idx_model(&pkg_id)
.expect(db)
.await?
.installed()
.check(db)
.await?
{
let ifaces = installed
.clone()
.manifest()
.interfaces()
.get(db)
.await?
.to_owned();
for (iface_id, cfgs) in ifaces.0 {
if let Some(tor_cfg) = cfgs.tor_config {
if let Some(key) = sqlx::query!(
"SELECT key FROM tor WHERE package = ? AND interface = ?",
*pkg_id,
*iface_id,
)
.fetch_optional(&mut *secrets)
.await?
{
if key.key.len() != 64 {
return Err(Error::new(
anyhow!("Invalid key length"),
crate::ErrorKind::Database,
));
}
let mut buf = [0; 64];
buf.clone_from_slice(&key.key);
services.insert(
buf,
HiddenServiceConfig {
ip: installed
.clone()
.interface_info()
.ip()
.get(db)
.await?
.to_owned(),
cfg: tor_cfg,
},
);
}
}
}
}
}
Ok(services)
}
async fn add_svc(
async fn add<'a, I: IntoIterator<Item = (InterfaceId, &'a Interface, TorSecretKeyV3)>>(
&mut self,
key: &TorSecretKeyV3,
config: &HiddenServiceConfig,
pkg_id: &PackageId,
ip: Ipv4Addr,
interfaces: I,
) -> Result<(), Error> {
self.connection
.add_onion_v3(
key,
false,
false,
false,
None,
&mut config
.cfg
.port_mapping
.iter()
.map(|(external, internal)| {
(external.0, SocketAddr::from((config.ip, internal.0)))
})
.collect::<Vec<_>>()
.iter(),
)
.await?;
for (interface_id, interface, key) in interfaces {
let id = (pkg_id.clone(), interface_id);
match self.services.get(&id) {
Some(k) if k != &key => {
self.remove(pkg_id, std::iter::once(id.1.clone())).await?;
}
Some(_) => return Ok(()),
None => (),
}
if let Some(tor_cfg) = &interface.tor_config {
self.connection
.add_onion_v3(
&key,
false,
false,
false,
None,
&mut tor_cfg
.port_mapping
.iter()
.map(|(external, internal)| {
(external.0, SocketAddr::from((ip, internal.0)))
})
.collect::<Vec<_>>()
.iter(),
)
.await?;
}
self.services.insert(id, key);
}
Ok(())
}
async fn sync(
async fn remove<I: IntoIterator<Item = InterfaceId>>(
&mut self,
services: IndexMap<[u8; 64], HiddenServiceConfig>,
pkg_id: &PackageId,
interfaces: I,
) -> Result<(), Error> {
for (key, new) in &services {
let tor_key = TorSecretKeyV3::from(key.clone());
if let Some(old) = self.services.remove(&key[..]) {
if new != &old {
self.connection
.del_onion(
&tor_key
.public()
.get_onion_address()
.get_address_without_dot_onion(),
)
.await?;
self.add_svc(&tor_key, new).await?;
}
} else {
self.add_svc(&tor_key, new).await?;
for interface_id in interfaces {
if let Some(key) = self.services.remove(&(pkg_id.clone(), interface_id)) {
self.connection
.del_onion(
&key.public()
.get_onion_address()
.get_address_without_dot_onion(),
)
.await?;
}
}
for (key, _) in self.services.drain(..) {
self.connection
.del_onion(
&TorSecretKeyV3::from(key)
.public()
.get_onion_address()
.get_address_without_dot_onion(),
)
.await?;
}
self.services = services;
Ok(())
}
async fn init<Db: DbHandle, Ex>(
tor_cp: SocketAddr,
db: &mut Db,
secrets: &mut Ex,
) -> Result<Self, Error>
where
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
{
async fn init(tor_control: SocketAddr) -> Result<Self, Error> {
let mut conn = torut::control::UnauthenticatedConn::new(
TcpStream::connect(tor_cp).await?, // TODO
TcpStream::connect(tor_control).await?, // TODO
);
let auth = conn
.load_protocol_info()
@@ -212,12 +133,10 @@ impl TorControllerInner {
conn.authenticate(&auth).await?;
let mut connection: AuthenticatedConnection = conn.into_authenticated().await;
connection.set_async_event_handler(Some(event_handler));
let mut res = TorControllerInner {
Ok(TorControllerInner {
connection,
services: IndexMap::new(),
};
res.sync(Self::get_services(db, secrets).await?).await?;
Ok(res)
services: HashMap::new(),
})
}
}

View File

@@ -12,11 +12,9 @@ use url::Url;
use crate::action::{ActionImplementation, Actions};
use crate::backup::BackupActions;
use crate::config::action::ConfigActions;
use crate::db::model::InterfaceInfo;
use crate::dependencies::Dependencies;
use crate::id::{Id, InvalidId, SYSTEM_ID};
use crate::migration::Migrations;
use crate::net::host::Hosts;
use crate::net::interface::Interfaces;
use crate::status::health_check::{HealthCheckResult, HealthChecks};
use crate::util::Version;
@@ -33,6 +31,11 @@ impl FromStr for PackageId {
Ok(PackageId(Id::try_from(s.to_owned())?))
}
}
impl<S: AsRef<str>> From<Id<S>> for PackageId<S> {
fn from(id: Id<S>) -> Self {
PackageId(id)
}
}
impl<S: AsRef<str>> std::ops::Deref for PackageId<S> {
type Target = S;
fn deref(&self) -> &Self::Target {

View File

@@ -6,7 +6,6 @@ use serde::{Deserialize, Deserializer, Serialize};
use crate::action::ActionImplementation;
use crate::id::Id;
use crate::net::host::Hosts;
use crate::s9pk::manifest::PackageId;
use crate::util::Version;
use crate::volume::Volumes;
@@ -51,13 +50,12 @@ impl HealthChecks {
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
) -> Result<IndexMap<HealthCheckId, HealthCheckResult>, Error> {
let res = futures::future::try_join_all(self.0.iter().map(|(id, check)| async move {
Ok::<_, Error>((
id.clone(),
check
.check(started, pkg_id, pkg_version, volumes, hosts)
.check(id, started, pkg_id, pkg_version, volumes)
.await?,
))
}))
@@ -75,15 +73,22 @@ pub struct HealthCheck {
impl HealthCheck {
pub async fn check(
&self,
id: &HealthCheckId,
started: &DateTime<Utc>,
pkg_id: &PackageId,
pkg_version: &Version,
volumes: &Volumes,
hosts: &Hosts,
) -> Result<HealthCheckResult, Error> {
let res = self
.implementation
.execute(pkg_id, pkg_version, volumes, hosts, Some(started), true)
.execute(
pkg_id,
pkg_version,
Some(&format!("{}Health", id)),
volumes,
Some(started),
true,
)
.await?;
Ok(HealthCheckResult {
time: Utc::now(),

View File

@@ -18,7 +18,6 @@ use crate::db::model::{
CurrentDependencyInfo, InstalledPackageDataEntryModel, PackageDataEntryModel,
};
use crate::dependencies::{Dependencies, DependencyError};
use crate::net::host::Hosts;
use crate::net::interface::InterfaceId;
use crate::s9pk::manifest::{Manifest, PackageId};
use crate::status::health_check::HealthCheckResultVariant;
@@ -46,7 +45,7 @@ pub async fn synchronize_all(ctx: &RpcContext) -> Result<(), Error> {
.get(&mut db)
.await?
{
container_names.push(DockerAction::container_name(id.as_ref(), version));
container_names.push(DockerAction::container_name(id.as_ref(), None));
} else {
pkg_ids.remove(&id);
}
@@ -168,12 +167,11 @@ pub async fn check_all(ctx: &RpcContext) -> Result<(), Error> {
async fn main_status<Db: DbHandle>(
status_model: StatusModel,
manifest: Arc<ModelData<Manifest>>,
hosts: Arc<Hosts>,
mut db: Db,
) -> Result<MainStatus, Error> {
let mut status = status_model.get_mut(&mut db).await?;
status.main.check(&*manifest, &*hosts).await?;
status.main.check(&*manifest).await?;
let res = status.main.clone();
@@ -192,7 +190,7 @@ pub async fn check_all(ctx: &RpcContext) -> Result<(), Error> {
.for_each_concurrent(None, move |(((status, manifest), id), hosts)| {
let status_sender = status_sender.clone();
async move {
match tokio::spawn(main_status(status, manifest, hosts, ctx.db.handle()))
match tokio::spawn(main_status(status, manifest, ctx.db.handle()))
.await
.unwrap()
{
@@ -292,7 +290,7 @@ impl MainStatus {
.and_then(|s| s.status)
== Some(ContainerStateStatusEnum::RUNNING))
}
let name = DockerAction::container_name(&manifest.id, &manifest.version);
let name = DockerAction::container_name(&manifest.id, None);
let state = summary.state.as_ref().map(|s| s.as_str());
match state {
Some("created") | Some("exited") => match self {
@@ -343,18 +341,12 @@ impl MainStatus {
}
Ok(false)
}
pub async fn check(&mut self, manifest: &Manifest, hosts: &Hosts) -> Result<(), Error> {
pub async fn check(&mut self, manifest: &Manifest) -> Result<(), Error> {
match self {
MainStatus::Running { started, health } => {
*health = manifest
.health_checks
.check_all(
started,
&manifest.id,
&manifest.version,
&manifest.volumes,
hosts,
)
.check_all(started, &manifest.id, &manifest.version, &manifest.volumes)
.await?;
for (check, res) in health {
if matches!(

View File

@@ -878,6 +878,7 @@ impl<'de> Deserialize<'de> for Port {
where
D: Deserializer<'de>,
{
//TODO: if number, be permissive
deserialize_from_str(deserializer).map(Port)
}
}

383
compat/Cargo.lock generated
View File

@@ -1,7 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.7.4"
@@ -37,12 +35,6 @@ version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
[[package]]
name = "array_tool"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
[[package]]
name = "arrayref"
version = "0.3.6"
@@ -57,13 +49,13 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "async-trait"
version = "0.1.50"
version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722"
checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -174,22 +166,21 @@ dependencies = [
[[package]]
name = "bollard"
version = "0.10.1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "699194c00f3a2effd3358d47f880646818e3d483190b17ebcdf598c654fb77e9"
checksum = "a4a3f238d4b66f33d9162893ade03cd8a485320f591b244ea5b7f236d3494e98"
dependencies = [
"base64 0.13.0",
"bollard-stubs",
"bytes 1.0.1",
"chrono",
"ct-logs",
"dirs-next",
"futures-core",
"futures-util",
"hex",
"http",
"hyper",
"hyper-unix-connector",
"hyperlocal",
"log",
"pin-project",
"serde",
@@ -197,7 +188,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"thiserror",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-util",
"url",
"winapi",
@@ -379,9 +370,9 @@ dependencies = [
[[package]]
name = "crossbeam-deque"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if",
"crossbeam-epoch",
@@ -453,25 +444,16 @@ dependencies = [
"memchr",
]
[[package]]
name = "ct-logs"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8"
dependencies = [
"sct",
]
[[package]]
name = "curve25519-dalek"
version = "3.1.0"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "639891fde0dbea823fc3d798a0fdf9d2f9440a42d64a78ab3488b0ca025117b3"
checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
dependencies = [
"byteorder",
"digest 0.9.0",
"rand_core 0.5.1",
"subtle 2.4.0",
"subtle 2.4.1",
"zeroize",
]
@@ -493,10 +475,10 @@ checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3"
dependencies = [
"fnv",
"ident_case",
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"strsim 0.10.0",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -507,7 +489,7 @@ checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc"
dependencies = [
"darling_core",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -588,9 +570,9 @@ checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
[[package]]
name = "ed25519"
version = "1.1.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d0860415b12243916284c67a9be413e044ee6668247b99ba26d94b2bc06c8f6"
checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc"
dependencies = [
"serde",
"signature",
@@ -636,7 +618,6 @@ dependencies = [
"futures",
"git-version",
"http",
"id-pool",
"indexmap",
"itertools 0.10.1",
"jsonpath_lib",
@@ -664,7 +645,7 @@ dependencies = [
"sqlx",
"tar",
"thiserror",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-compat-02",
"tokio-stream",
"tokio-tar",
@@ -702,19 +683,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
@@ -732,13 +700,13 @@ dependencies = [
[[package]]
name = "filetime"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.2.9",
"redox_syscall 0.2.10",
"winapi",
]
@@ -790,9 +758,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "futures"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27"
checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b"
dependencies = [
"futures-channel",
"futures-core",
@@ -805,9 +773,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2"
checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9"
dependencies = [
"futures-core",
"futures-sink",
@@ -815,15 +783,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1"
checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99"
[[package]]
name = "futures-executor"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79"
checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c"
dependencies = [
"futures-core",
"futures-task",
@@ -832,40 +800,40 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1"
checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582"
[[package]]
name = "futures-macro"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121"
checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57"
dependencies = [
"autocfg",
"proc-macro-hack",
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
name = "futures-sink"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282"
checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53"
[[package]]
name = "futures-task"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae"
checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2"
[[package]]
name = "futures-util"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967"
checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78"
dependencies = [
"autocfg",
"futures-channel",
@@ -925,9 +893,9 @@ dependencies = [
[[package]]
name = "git-version"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94918e83f1e01dedc2e361d00ce9487b14c58c7f40bab148026fa39d42cb41e2"
checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899"
dependencies = [
"git-version-macro",
"proc-macro-hack",
@@ -935,14 +903,14 @@ dependencies = [
[[package]]
name = "git-version-macro"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34a97a52fdee1870a34fa6e4b77570cba531b27d1838874fef4429a791a3d657"
checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f"
dependencies = [
"proc-macro-hack",
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -959,7 +927,7 @@ dependencies = [
"http",
"indexmap",
"slab",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-util",
"tracing",
]
@@ -1035,9 +1003,9 @@ dependencies = [
[[package]]
name = "http-body"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9"
checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5"
dependencies = [
"bytes 1.0.1",
"http",
@@ -1056,20 +1024,11 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "hyper"
version = "0.14.10"
version = "0.14.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7728a72c4c7d72665fde02204bcbd93b247721025b222ef78606f14513e0fd03"
checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11"
dependencies = [
"bytes 1.0.1",
"futures-channel",
@@ -1083,7 +1042,7 @@ dependencies = [
"itoa",
"pin-project-lite 0.2.7",
"socket2",
"tokio 1.8.1",
"tokio 1.9.0",
"tower-service",
"tracing",
"want",
@@ -1098,30 +1057,21 @@ dependencies = [
"bytes 1.0.1",
"hyper",
"native-tls",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-native-tls",
]
[[package]]
name = "hyper-unix-connector"
version = "0.2.2"
name = "hyperlocal"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ef1fd95d34b4ff007d3f0590727b5cf33572cace09b42032fc817dc8b16557"
checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"
dependencies = [
"anyhow",
"futures-util",
"hex",
"hyper",
"pin-project",
"tokio 1.8.1",
]
[[package]]
name = "id-pool"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e33832e3000c359e3f67781634a5e6d58bffa8c5247c1464bd2e483f1a79cb0"
dependencies = [
"serde",
"tokio 1.9.0",
]
[[package]]
@@ -1193,9 +1143,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
version = "0.3.51"
version = "0.3.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062"
checksum = "ce791b7ca6638aae45be056e068fc756d871eb3b3b10b8efa62d1c9cec616752"
dependencies = [
"wasm-bindgen",
]
@@ -1221,12 +1171,10 @@ dependencies = [
[[package]]
name = "jsonpath_lib"
version = "0.2.6"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61352ec23883402b7d30b3313c16cbabefb8907361c4eb669d990cbb87ceee5a"
checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f"
dependencies = [
"array_tool",
"env_logger",
"log",
"serde",
"serde_json",
@@ -1527,7 +1475,7 @@ dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall 0.2.9",
"redox_syscall 0.2.10",
"smallvec",
"winapi",
]
@@ -1550,7 +1498,7 @@ dependencies = [
"serde_cbor 0.11.1",
"serde_json",
"thiserror",
"tokio 1.8.1",
"tokio 1.9.0",
]
[[package]]
@@ -1558,8 +1506,8 @@ name = "patch-db-macro"
version = "0.1.0"
dependencies = [
"patch-db-macro-internals",
"proc-macro2 1.0.27",
"syn 1.0.73",
"proc-macro2 1.0.28",
"syn 1.0.74",
]
[[package]]
@@ -1567,9 +1515,9 @@ name = "patch-db-macro-internals"
version = "0.1.0"
dependencies = [
"heck",
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -1580,22 +1528,22 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pin-project"
version = "1.0.7"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4"
checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.7"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"
checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -1665,19 +1613,13 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.27"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
dependencies = [
"unicode-xid 0.2.2",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "0.6.13"
@@ -1693,7 +1635,7 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
]
[[package]]
@@ -1799,9 +1741,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "redox_syscall"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
@@ -1824,7 +1766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
dependencies = [
"getrandom 0.2.3",
"redox_syscall 0.2.9",
"redox_syscall 0.2.10",
]
[[package]]
@@ -1885,7 +1827,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-native-tls",
"url",
"wasm-bindgen",
@@ -1933,7 +1875,7 @@ dependencies = [
"serde_cbor 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json",
"thiserror",
"tokio 1.8.1",
"tokio 1.9.0",
"url",
"yajrc",
]
@@ -1942,18 +1884,18 @@ dependencies = [
name = "rpc-toolkit-macro"
version = "0.1.0"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"rpc-toolkit-macro-internals",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
name = "rpc-toolkit-macro-internals"
version = "0.1.0"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -2068,9 +2010,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.126"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
dependencies = [
"serde_derive",
]
@@ -2104,20 +2046,20 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.126"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
name = "serde_json"
version = "1.0.64"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
dependencies = [
"indexmap",
"itoa",
@@ -2155,9 +2097,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1569374bd54623ec8bd592cf22ba6e03c0f177ff55fbc8c29a49e296e7adecf"
dependencies = [
"darling",
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -2244,9 +2186,9 @@ dependencies = [
[[package]]
name = "slab"
version = "0.4.3"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
[[package]]
name = "smallvec"
@@ -2256,9 +2198,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "socket2"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad"
dependencies = [
"libc",
"winapi",
@@ -2349,14 +2291,14 @@ dependencies = [
"heck",
"hex",
"once_cell",
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"serde",
"serde_json",
"sha2 0.9.5",
"sqlx-core",
"sqlx-rt",
"syn 1.0.73",
"syn 1.0.74",
"url",
]
@@ -2367,7 +2309,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8199b421ecf3493ee9ef3e7bc90c904844cfb2ea7ea2f57347a93f52bfd3e057"
dependencies = [
"once_cell",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-rustls",
]
@@ -2407,9 +2349,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
[[package]]
name = "subtle"
version = "2.4.0"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
@@ -2424,11 +2366,11 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.73"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"unicode-xid 0.2.2",
]
@@ -2439,9 +2381,9 @@ version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
"unicode-xid 0.2.2",
]
@@ -2471,7 +2413,7 @@ dependencies = [
"cfg-if",
"libc",
"rand 0.8.4",
"redox_syscall 0.2.9",
"redox_syscall 0.2.10",
"remove_dir_all",
"winapi",
]
@@ -2487,15 +2429,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@@ -2520,9 +2453,9 @@ version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -2549,9 +2482,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.2.0"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338"
dependencies = [
"tinyvec_macros",
]
@@ -2576,9 +2509,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.8.1"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98c8b05dc14c75ea83d63dd391100353789f5f24b8b3866542a5e85c8be8e985"
checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c"
dependencies = [
"autocfg",
"bytes 1.0.1",
@@ -2604,7 +2537,7 @@ dependencies = [
"once_cell",
"pin-project-lite 0.2.7",
"tokio 0.2.25",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-stream",
]
@@ -2614,9 +2547,9 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -2626,7 +2559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
"tokio 1.8.1",
"tokio 1.9.0",
]
[[package]]
@@ -2636,7 +2569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
dependencies = [
"rustls",
"tokio 1.8.1",
"tokio 1.9.0",
"webpki",
]
@@ -2648,7 +2581,8 @@ checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
dependencies = [
"futures-core",
"pin-project-lite 0.2.7",
"tokio 1.8.1",
"tokio 1.9.0",
"tokio-util",
]
[[package]]
@@ -2660,8 +2594,8 @@ dependencies = [
"filetime",
"futures-core",
"libc",
"redox_syscall 0.2.9",
"tokio 1.8.1",
"redox_syscall 0.2.10",
"tokio 1.9.0",
"tokio-stream",
"xattr",
]
@@ -2677,7 +2611,7 @@ dependencies = [
"futures-sink",
"log",
"pin-project-lite 0.2.7",
"tokio 1.8.1",
"tokio 1.9.0",
]
[[package]]
@@ -2708,7 +2642,7 @@ dependencies = [
"sha1",
"sha2 0.8.2",
"sha3",
"tokio 1.8.1",
"tokio 1.9.0",
]
[[package]]
@@ -2758,9 +2692,9 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345426c7406aa355b60c5007c79a2d1f5b605540072795222f17f6443e6a9c6f"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
]
[[package]]
@@ -2878,9 +2812,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
version = "0.2.74"
version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586"
dependencies = [
"cfg-if",
"serde",
@@ -2890,24 +2824,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.74"
version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900"
checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.24"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1"
checksum = "16646b21c3add8e13fdb8f20172f8a28c3dbf62f45406bcff0233188226cfe0c"
dependencies = [
"cfg-if",
"js-sys",
@@ -2917,9 +2851,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.74"
version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4"
checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c"
dependencies = [
"quote 1.0.9",
"wasm-bindgen-macro-support",
@@ -2927,28 +2861,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.74"
version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97"
checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.74"
version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2"
[[package]]
name = "web-sys"
version = "0.3.51"
version = "0.3.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582"
checksum = "01c70a82d842c9979078c772d4a1344685045f1a5628f677c2b2eab4dd7d2696"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2999,15 +2933,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -3059,9 +2984,9 @@ dependencies = [
[[package]]
name = "zeroize"
version = "1.3.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd"
dependencies = [
"zeroize_derive",
]
@@ -3072,8 +2997,8 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1"
dependencies = [
"proc-macro2 1.0.27",
"proc-macro2 1.0.28",
"quote 1.0.9",
"syn 1.0.73",
"syn 1.0.74",
"synstructure",
]