diff --git a/.gitignore b/.gitignore index 7b926711e..3b0fb20d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ .DS_Store .idea +system-images/binfmt/binfmt.tar +system-images/compat/compat.tar +system-images/util/util.tar /*.img /*.img.gz /*.img.xz diff --git a/Makefile b/Makefile index a789c2d4e..3f9eeaf35 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ ARCH = $(shell uname -m) ENVIRONMENT_FILE = $(shell ./check-environment.sh) GIT_HASH_FILE = $(shell ./check-git-hash.sh) -EMBASSY_BINS := backend/target/$(ARCH)-unknown-linux-gnu/release/embassyd backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-init backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-cli backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-sdk backend/target/$(ARCH)-unknown-linux-gnu/release/avahi-alias +EMBASSY_BINS := backend/target/$(ARCH)-unknown-linux-gnu/release/embassyd backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-init backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-cli backend/target/$(ARCH)-unknown-linux-gnu/release/embassy-sdk backend/target/$(ARCH)-unknown-linux-gnu/release/avahi-alias libs/target/aarch64-unknown-linux-musl/release/embassy_container_init libs/target/x86_64-unknown-linux-musl/release/embassy_container_init EMBASSY_UIS := frontend/dist/ui frontend/dist/setup-wizard frontend/dist/diagnostic-ui EMBASSY_SRC := backend/embassyd.service backend/embassy-init.service $(EMBASSY_UIS) $(shell find build) COMPAT_SRC := $(shell find system-images/compat/ -not -path 'system-images/compat/target/*' -and -not -name *.tar -and -not -name target) @@ -75,6 +75,10 @@ install: all cp ENVIRONMENT.txt $(DESTDIR)/usr/lib/embassy/ cp GIT_HASH.txt $(DESTDIR)/usr/lib/embassy/ + mkdir -p $(DESTDIR)/usr/lib/embassy/container + cp libs/target/aarch64-unknown-linux-musl/release/embassy_container_init $(DESTDIR)/usr/lib/embassy/container/embassy_container_init.arm64 + cp libs/target/x86_64-unknown-linux-musl/release/embassy_container_init $(DESTDIR)/usr/lib/embassy/container/embassy_container_init.amd64 + mkdir -p $(DESTDIR)/usr/lib/embassy/system-images cp system-images/compat/docker-images/aarch64.tar $(DESTDIR)/usr/lib/embassy/system-images/compat.tar cp system-images/utils/docker-images/$(ARCH).tar $(DESTDIR)/usr/lib/embassy/system-images/utils.tar diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 9c80a7667..0a98836d9 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1142,6 +1142,7 @@ dependencies = [ "divrem", "ed25519", "ed25519-dalek", + "embassy_container_init", "emver", "fd-lock-rs", "futures", @@ -1213,6 +1214,23 @@ dependencies = [ "uuid", ] +[[package]] +name = "embassy_container_init" +version = "0.1.0" +dependencies = [ + "async-stream", + "color-eyre", + "futures", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tracing", + "tracing-error 0.2.0", + "tracing-futures", + "tracing-subscriber 0.3.15", +] + [[package]] name = "emver" version = "0.1.6" @@ -2020,10 +2038,12 @@ dependencies = [ name = "js_engine" version = "0.1.0" dependencies = [ + "async-trait", "dashmap", "deno_ast", "deno_core", "dprint-swc-ext", + "embassy_container_init", "helpers", "models", "reqwest", @@ -2344,11 +2364,13 @@ dependencies = [ name = "models" version = "0.1.0" dependencies = [ + "embassy_container_init", "emver", "patch-db", "rand 0.8.5", "serde", "thiserror", + "tokio", ] [[package]] @@ -4645,9 +4667,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 5f032d56f..7913e43c5 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -75,6 +75,7 @@ fd-lock-rs = "0.1.4" futures = "0.3.21" git-version = "0.3.5" helpers = { path = "../libs/helpers" } +embassy_container_init = { path = "../libs/embassy-container-init" } hex = "0.4.3" hmac = "0.12.1" http = "0.2.8" diff --git a/backend/build-prod.sh b/backend/build-prod.sh index 9c1aacf0c..f56663cf7 100755 --- a/backend/build-prod.sh +++ b/backend/build-prod.sh @@ -17,7 +17,8 @@ if tty -s; then USE_TTY="-it" fi -alias 'rust-arm64-builder'='docker run $USE_TTY --rm -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)":/home/rust/src -P start9/rust-arm-cross:aarch64' +alias 'rust-gnu-builder'='docker run $USE_TTY --rm -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)":/home/rust/src -P start9/rust-arm-cross:aarch64' +alias 'rust-musl-builder'='docker run $USE_TTY --rm -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)":/home/rust/src -P messense/rust-musl-cross:$ARCH-musl' cd .. FLAGS="" @@ -27,15 +28,44 @@ fi if [[ "$ENVIRONMENT" =~ (^|-)dev($|-) ]]; then FLAGS="dev,$FLAGS" fi + +set +e +fail= if [[ "$FLAGS" = "" ]]; then - rust-arm64-builder sh -c "(git config --global --add safe.directory '*'; cd backend && cargo build --release --locked --target=$ARCH-unknown-linux-gnu)" + rust-gnu-builder sh -c "(git config --global --add safe.directory '*'; cd backend && cargo build --release --locked --target=$ARCH-unknown-linux-gnu)" + if test $? -ne 0; then + fail=true + fi + for ARCH in x86_64 aarch64 + do + rust-musl-builder sh -c "(git config --global --add safe.directory '*'; cd libs && cargo build --release --locked --bin embassy_container_init )" + if test $? -ne 0; then + fail=true + fi + done else echo "FLAGS=$FLAGS" - rust-arm64-builder sh -c "(git config --global --add safe.directory '*'; cd backend && cargo build --release --features $FLAGS --locked --target=$ARCH-unknown-linux-gnu)" + rust-gnu-builder sh -c "(git config --global --add safe.directory '*'; cd backend && cargo build --release --features $FLAGS --locked --target=$ARCH-unknown-linux-gnu)" + if test $? -ne 0; then + fail=true + fi + for ARCH in x86_64 aarch64 + do + rust-musl-builder sh -c "(git config --global --add safe.directory '*'; cd libs && cargo build --release --features $FLAGS --locked --bin embassy_container_init)" + if test $? -ne 0; then + fail=true + fi + done fi +set -e cd backend sudo chown -R $USER target sudo chown -R $USER ~/.cargo +sudo chown -R $USER ../libs/target + +if [-n fail]; then + exit 1 +fi #rust-arm64-builder aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/embassyd diff --git a/backend/src/action.rs b/backend/src/action.rs index 8d0f4ddf3..a07d0a1fa 100644 --- a/backend/src/action.rs +++ b/backend/src/action.rs @@ -11,7 +11,7 @@ use tracing::instrument; use crate::config::{Config, ConfigSpec}; use crate::context::RpcContext; use crate::id::ImageId; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::procedure::{PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; use crate::util::serde::{display_serializable, parse_stdin_deserializable, IoFormat}; @@ -59,7 +59,7 @@ impl Action { #[instrument] pub fn validate( &self, - container: &Option, + container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, @@ -78,7 +78,6 @@ impl Action { pub async fn execute( &self, ctx: &RpcContext, - container: &Option, pkg_id: &PackageId, pkg_version: &Version, action_id: &ActionId, @@ -93,7 +92,6 @@ impl Action { self.implementation .execute( ctx, - container, pkg_id, pkg_version, ProcedureName::Action(action_id.clone()), @@ -145,23 +143,10 @@ pub async fn action( .await? .to_owned(); - let container = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&pkg_id) - .and_then(|p| p.installed()) - .expect(&mut db) - .await - .with_kind(crate::ErrorKind::NotFound)? - .manifest() - .container() - .get(&mut db, false) - .await? - .to_owned(); if let Some(action) = manifest.actions.0.get(&action_id) { action .execute( &ctx, - &container, &manifest.id, &manifest.version, &action_id, diff --git a/backend/src/backup/mod.rs b/backend/src/backup/mod.rs index d667bb33a..4105a801c 100644 --- a/backend/src/backup/mod.rs +++ b/backend/src/backup/mod.rs @@ -19,7 +19,7 @@ use crate::dependencies::reconfigure_dependents_with_live_pointers; use crate::id::ImageId; use crate::install::PKG_ARCHIVE_DIR; use crate::net::interface::{InterfaceId, Interfaces}; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::procedure::{NoOutput, PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; use crate::util::serde::IoFormat; @@ -74,7 +74,7 @@ pub struct BackupActions { impl BackupActions { pub fn validate( &self, - container: &Option, + container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, @@ -102,25 +102,12 @@ impl BackupActions { let mut volumes = volumes.to_readonly(); volumes.insert(VolumeId::Backup, Volume::Backup { readonly: false }); let backup_dir = backup_dir(pkg_id); - let container = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&pkg_id) - .and_then(|p| p.installed()) - .expect(db) - .await - .with_kind(crate::ErrorKind::NotFound)? - .manifest() - .container() - .get(db, false) - .await? - .to_owned(); if tokio::fs::metadata(&backup_dir).await.is_err() { tokio::fs::create_dir_all(&backup_dir).await? } self.create .execute::<(), NoOutput>( ctx, - &container, pkg_id, pkg_version, ProcedureName::CreateBackup, @@ -200,7 +187,6 @@ impl BackupActions { #[instrument(skip(ctx, db, secrets))] pub async fn restore( &self, - container: &Option, ctx: &RpcContext, db: &mut Db, secrets: &mut Ex, @@ -217,7 +203,6 @@ impl BackupActions { self.restore .execute::<(), NoOutput>( ctx, - container, pkg_id, pkg_version, ProcedureName::RestoreBackup, diff --git a/backend/src/config/action.rs b/backend/src/config/action.rs index b1e674731..4ee7d54f4 100644 --- a/backend/src/config/action.rs +++ b/backend/src/config/action.rs @@ -10,7 +10,7 @@ use super::{Config, ConfigSpec}; use crate::context::RpcContext; use crate::dependencies::Dependencies; use crate::id::ImageId; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::procedure::{PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; use crate::status::health_check::HealthCheckId; @@ -34,7 +34,7 @@ impl ConfigActions { #[instrument] pub fn validate( &self, - container: &Option, + container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, @@ -51,7 +51,6 @@ impl ConfigActions { pub async fn get( &self, ctx: &RpcContext, - container: &Option, pkg_id: &PackageId, pkg_version: &Version, volumes: &Volumes, @@ -59,7 +58,6 @@ impl ConfigActions { self.get .execute( ctx, - container, pkg_id, pkg_version, ProcedureName::GetConfig, @@ -77,7 +75,6 @@ impl ConfigActions { pub async fn set( &self, ctx: &RpcContext, - container: &Option, pkg_id: &PackageId, pkg_version: &Version, dependencies: &Dependencies, @@ -88,7 +85,6 @@ impl ConfigActions { .set .execute( ctx, - container, pkg_id, pkg_version, ProcedureName::SetConfig, diff --git a/backend/src/config/mod.rs b/backend/src/config/mod.rs index 94be02a59..66d5c52c2 100644 --- a/backend/src/config/mod.rs +++ b/backend/src/config/mod.rs @@ -21,7 +21,7 @@ use crate::dependencies::{ DependencyErrors, DependencyReceipt, TaggedDependencyError, TryHealReceipts, }; use crate::install::cleanup::{remove_from_current_dependents_lists, UpdateDependencyReceipts}; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::util::display_none; use crate::util::serde::{display_serializable, parse_stdin_deserializable, IoFormat}; @@ -168,7 +168,6 @@ pub struct ConfigGetReceipts { manifest_volumes: LockReceipt, manifest_version: LockReceipt, manifest_config: LockReceipt, ()>, - docker_container: LockReceipt, } impl ConfigGetReceipts { @@ -204,19 +203,11 @@ impl ConfigGetReceipts { .map(|x| x.manifest().config()) .make_locker(LockType::Write) .add_to_keys(locks); - let docker_container = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().container()) - .make_locker(LockType::Write) - .add_to_keys(locks); move |skeleton_key| { Ok(Self { manifest_volumes: manifest_volumes.verify(skeleton_key)?, manifest_version: manifest_version.verify(skeleton_key)?, manifest_config: manifest_config.verify(skeleton_key)?, - docker_container: docker_container.verify(skeleton_key)?, }) } } @@ -239,11 +230,9 @@ pub async fn get( .await? .ok_or_else(|| Error::new(eyre!("{} has no config", id), crate::ErrorKind::NotFound))?; - let container = receipts.docker_container.get(&mut db, &id).await?; - let volumes = receipts.manifest_volumes.get(&mut db).await?; let version = receipts.manifest_version.get(&mut db).await?; - action.get(&ctx, &container, &id, &version, &volumes).await + action.get(&ctx, &id, &version, &volumes).await } #[command( @@ -286,7 +275,7 @@ pub struct ConfigReceipts { pub current_dependencies: LockReceipt, dependency_errors: LockReceipt, manifest_dependencies_config: LockReceipt, - docker_container: LockReceipt, + docker_containers: LockReceipt, } impl ConfigReceipts { @@ -391,11 +380,11 @@ impl ConfigReceipts { .and_then(|x| x.manifest().dependencies().star().config()) .make_locker(LockType::Write) .add_to_keys(locks); - let docker_container = crate::db::DatabaseModel::new() + let docker_containers = crate::db::DatabaseModel::new() .package_data() .star() .installed() - .and_then(|x| x.manifest().container()) + .and_then(|x| x.manifest().containers()) .make_locker(LockType::Write) .add_to_keys(locks); @@ -417,7 +406,7 @@ impl ConfigReceipts { current_dependencies: current_dependencies.verify(skeleton_key)?, dependency_errors: dependency_errors.verify(skeleton_key)?, manifest_dependencies_config: manifest_dependencies_config.verify(skeleton_key)?, - docker_container: docker_container.verify(skeleton_key)?, + docker_containers: docker_containers.verify(skeleton_key)?, }) } } @@ -509,8 +498,6 @@ pub fn configure_rec<'a, Db: DbHandle>( receipts: &'a ConfigReceipts, ) -> BoxFuture<'a, Result<(), Error>> { async move { - let container = receipts.docker_container.get(db, &id).await?; - let container = &container; // fetch data from db let action = receipts .config_actions @@ -534,7 +521,7 @@ pub fn configure_rec<'a, Db: DbHandle>( let ConfigRes { config: old_config, spec, - } = action.get(ctx, container, id, &version, &volumes).await?; + } = action.get(ctx, id, &version, &volumes).await?; // determine new config to use let mut config = if let Some(config) = config.or_else(|| old_config.clone()) { @@ -602,15 +589,7 @@ pub fn configure_rec<'a, Db: DbHandle>( let signal = if !dry_run { // run config action let res = action - .set( - ctx, - container, - id, - &version, - &dependencies, - &volumes, - &config, - ) + .set(ctx, id, &version, &dependencies, &volumes, &config) .await?; // track dependencies with no pointers @@ -702,7 +681,7 @@ pub fn configure_rec<'a, Db: DbHandle>( .unwrap_or_default(); let next = Value::Object(config.clone()); for (dependent, dep_info) in dependents.0.iter().filter(|(dep_id, _)| dep_id != &id) { - let dependent_container = receipts.docker_container.get(db, &dependent).await?; + let dependent_container = receipts.docker_containers.get(db, &dependent).await?; let dependent_container = &dependent_container; // check if config passes dependent check if let Some(cfg) = receipts diff --git a/backend/src/config/spec.rs b/backend/src/config/spec.rs index cea9ce1ea..f8b2d37e3 100644 --- a/backend/src/config/spec.rs +++ b/backend/src/config/spec.rs @@ -25,7 +25,6 @@ use super::{Config, MatchError, NoMatchWithPath, TimeoutError, TypeOf}; use crate::config::ConfigurationError; use crate::context::RpcContext; use crate::net::interface::InterfaceId; -use crate::procedure::docker::DockerContainer; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::Error; @@ -1883,7 +1882,6 @@ pub struct ConfigPointerReceipts { manifest_volumes: LockReceipt, manifest_version: LockReceipt, config_actions: LockReceipt, - docker_container: LockReceipt, } impl ConfigPointerReceipts { @@ -1920,20 +1918,12 @@ impl ConfigPointerReceipts { .and_then(|x| x.manifest().config()) .make_locker(LockType::Read) .add_to_keys(locks); - let docker_container = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().container()) - .make_locker(LockType::Write) - .add_to_keys(locks); move |skeleton_key| { Ok(Self { interface_addresses_receipt: interface_addresses_receipt(skeleton_key)?, manifest_volumes: manifest_volumes.verify(skeleton_key)?, config_actions: config_actions.verify(skeleton_key)?, manifest_version: manifest_version.verify(skeleton_key)?, - docker_container: docker_container.verify(skeleton_key)?, }) } } @@ -1963,12 +1953,11 @@ impl ConfigPointer { let version = receipts.manifest_version.get(db, id).await.ok().flatten(); let cfg_actions = receipts.config_actions.get(db, id).await.ok().flatten(); let volumes = receipts.manifest_volumes.get(db, id).await.ok().flatten(); - let container = receipts.docker_container.get(db, id).await.ok().flatten(); if let (Some(version), Some(cfg_actions), Some(volumes)) = (&version, &cfg_actions, &volumes) { let cfg_res = cfg_actions - .get(ctx, &container, &self.package_id, version, volumes) + .get(ctx, &self.package_id, version, volumes) .await .map_err(|e| ConfigurationError::SystemError(e))?; if let Some(cfg) = cfg_res.config { diff --git a/backend/src/dependencies.rs b/backend/src/dependencies.rs index 34a8bdfae..29982bf58 100644 --- a/backend/src/dependencies.rs +++ b/backend/src/dependencies.rs @@ -19,7 +19,7 @@ use crate::config::spec::PackagePointerSpec; use crate::config::{not_found, Config, ConfigReceipts, ConfigSpec}; use crate::context::RpcContext; use crate::db::model::{CurrentDependencies, CurrentDependents, InstalledPackageDataEntry}; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::procedure::{NoOutput, PackageProcedure, ProcedureName}; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::status::health_check::{HealthCheckId, HealthCheckResult}; @@ -64,7 +64,7 @@ pub struct TryHealReceipts { manifest_version: LockReceipt, current_dependencies: LockReceipt, dependency_errors: LockReceipt, - docker_container: LockReceipt, + docker_containers: LockReceipt, } impl TryHealReceipts { @@ -112,11 +112,11 @@ impl TryHealReceipts { .map(|x| x.status().dependency_errors()) .make_locker(LockType::Write) .add_to_keys(locks); - let docker_container = crate::db::DatabaseModel::new() + let docker_containers = crate::db::DatabaseModel::new() .package_data() .star() .installed() - .and_then(|x| x.manifest().container()) + .and_then(|x| x.manifest().containers()) .make_locker(LockType::Write) .add_to_keys(locks); move |skeleton_key| { @@ -126,7 +126,7 @@ impl TryHealReceipts { current_dependencies: current_dependencies.verify(skeleton_key)?, manifest: manifest.verify(skeleton_key)?, dependency_errors: dependency_errors.verify(skeleton_key)?, - docker_container: docker_container.verify(skeleton_key)?, + docker_containers: docker_containers.verify(skeleton_key)?, }) } } @@ -203,7 +203,7 @@ impl DependencyError { receipts: &'a TryHealReceipts, ) -> BoxFuture<'a, Result, Error>> { async move { - let container = receipts.docker_container.get(db, id).await?; + let container = receipts.docker_containers.get(db, id).await?; Ok(match self { DependencyError::NotInstalled => { if receipts.status.get(db, dependency).await?.is_some() { @@ -251,7 +251,6 @@ impl DependencyError { cfg_info .get( ctx, - &container, dependency, &dependency_manifest.version, &dependency_manifest.volumes, @@ -507,7 +506,7 @@ impl DependencyConfig { pub async fn check( &self, ctx: &RpcContext, - container: &Option, + container: &Option, dependent_id: &PackageId, dependent_version: &Version, dependent_volumes: &Volumes, @@ -532,7 +531,7 @@ impl DependencyConfig { pub async fn auto_configure( &self, ctx: &RpcContext, - container: &Option, + container: &Option, dependent_id: &PackageId, dependent_version: &Version, dependent_volumes: &Volumes, @@ -562,7 +561,7 @@ pub struct DependencyConfigReceipts { dependency_config_action: LockReceipt, package_volumes: LockReceipt, package_version: LockReceipt, - docker_container: LockReceipt, + docker_containers: LockReceipt, } impl DependencyConfigReceipts { @@ -625,11 +624,11 @@ impl DependencyConfigReceipts { .map(|x| x.manifest().version()) .make_locker(LockType::Write) .add_to_keys(locks); - let docker_container = crate::db::DatabaseModel::new() + let docker_containers = crate::db::DatabaseModel::new() .package_data() .star() .installed() - .and_then(|x| x.manifest().container()) + .and_then(|x| x.manifest().containers()) .make_locker(LockType::Write) .add_to_keys(locks); move |skeleton_key| { @@ -641,7 +640,7 @@ impl DependencyConfigReceipts { dependency_config_action: dependency_config_action.verify(&skeleton_key)?, package_volumes: package_volumes.verify(&skeleton_key)?, package_version: package_version.verify(&skeleton_key)?, - docker_container: docker_container.verify(&skeleton_key)?, + docker_containers: docker_containers.verify(&skeleton_key)?, }) } } @@ -716,8 +715,7 @@ pub async fn configure_logic( let dependency_version = receipts.dependency_version.get(db).await?; let dependency_volumes = receipts.dependency_volumes.get(db).await?; let dependencies = receipts.dependencies.get(db).await?; - let dependency_docker_container = receipts.docker_container.get(db, &*dependency_id).await?; - let pkg_docker_container = receipts.docker_container.get(db, &*pkg_id).await?; + let pkg_docker_container = receipts.docker_containers.get(db, &*pkg_id).await?; let dependency = dependencies .0 @@ -750,7 +748,6 @@ pub async fn configure_logic( } = dependency_config_action .get( &ctx, - &dependency_docker_container, &dependency_id, &dependency_version, &dependency_volumes, diff --git a/backend/src/install/cleanup.rs b/backend/src/install/cleanup.rs index 72fbdf432..bb815a891 100644 --- a/backend/src/install/cleanup.rs +++ b/backend/src/install/cleanup.rs @@ -1,10 +1,6 @@ -use std::collections::HashMap; -use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::{collections::HashMap, path::PathBuf, sync::Arc}; use bollard::image::ListImagesOptions; -use color_eyre::Report; -use futures::FutureExt; use patch_db::{DbHandle, LockReceipt, LockTargetId, LockType, PatchDbHandle, Verifier}; use sqlx::{Executor, Postgres}; use tracing::instrument; @@ -422,7 +418,7 @@ pub fn cleanup_folder( Box::pin(async move { let meta_data = match tokio::fs::metadata(&path).await { Ok(a) => a, - Err(e) => { + Err(_e) => { return; } }; @@ -441,7 +437,7 @@ pub fn cleanup_folder( } let mut read_dir = match tokio::fs::read_dir(&path).await { Ok(a) => a, - Err(e) => { + Err(_e) => { return; } }; diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index 76bff5652..3df77ccca 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -1318,7 +1318,6 @@ pub async fn install_s9pk( .manifest .migrations .to( - &prev.manifest.container, ctx, version, pkg_id, @@ -1329,7 +1328,7 @@ pub async fn install_s9pk( let migration = manifest .migrations .from( - &manifest.container, + &manifest.containers, ctx, &prev.manifest.version, pkg_id, @@ -1413,7 +1412,6 @@ pub async fn install_s9pk( manifest .backup .restore( - &manifest.container, ctx, &mut tx, &mut sql_tx, @@ -1522,7 +1520,7 @@ async fn handle_recovered_package( receipts: &ConfigReceipts, ) -> Result<(), Error> { let configured = if let Some(migration) = manifest.migrations.from( - &manifest.container, + &manifest.containers, ctx, &recovered.version, pkg_id, diff --git a/backend/src/manager/health.rs b/backend/src/manager/health.rs index e070ad5a9..9322bdf24 100644 --- a/backend/src/manager/health.rs +++ b/backend/src/manager/health.rs @@ -115,7 +115,7 @@ pub async fn check( .health_checks .check_all( ctx, - &manifest.container, + &manifest.containers, started, id, &manifest.version, diff --git a/backend/src/manager/mod.rs b/backend/src/manager/mod.rs index c33fc579a..cee63477b 100644 --- a/backend/src/manager/mod.rs +++ b/backend/src/manager/mod.rs @@ -10,15 +10,17 @@ use std::time::Duration; use bollard::container::{KillContainerOptions, StopContainerOptions}; use chrono::Utc; use color_eyre::eyre::eyre; +use embassy_container_init::{InputJsonRpc, RpcId}; +use models::{ExecCommand, TermCommand}; use nix::sys::signal::Signal; use num_enum::TryFromPrimitive; use patch_db::DbHandle; use sqlx::{Executor, Postgres}; -use tokio::io::BufReader; use tokio::sync::watch::error::RecvError; use tokio::sync::watch::{channel, Receiver, Sender}; use tokio::sync::{Mutex, Notify, RwLock}; -use tokio::task::JoinHandle; +use tokio::{sync::mpsc::UnboundedSender, task::JoinHandle}; +use tokio_stream::wrappers::UnboundedReceiverStream; use torut::onion::TorSecretKeyV3; use tracing::instrument; @@ -27,7 +29,9 @@ use crate::manager::sync::synchronizer; use crate::net::interface::InterfaceId; use crate::net::GeneratedCertificateMountPoint; use crate::notifications::NotificationLevel; -use crate::procedure::docker::{DockerContainer, DockerInject, DockerProcedure}; +use crate::procedure::docker::{DockerContainer, DockerProcedure, LongRunning}; +#[cfg(feature = "js_engine")] +use crate::procedure::js_scripts::JsProcedure; use crate::procedure::{NoOutput, PackageProcedure, ProcedureName}; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::status::MainStatus; @@ -191,14 +195,15 @@ async fn run_main( let generated_certificate = generate_certificate(state, &interfaces).await?; persistant.wait_for_persistant().await; - let is_injectable_main = check_is_injectable_main(&state); - let mut runtime = match is_injectable_main { - true => { - tokio::spawn( - async move { start_up_inject_image(rt_state, generated_certificate).await }, - ) + let is_injectable_main = check_is_injectable_main(state); + let mut runtime = match injectable_main(state) { + InjectableMain::None => { + tokio::spawn(async move { start_up_image(rt_state, generated_certificate).await }) + } + #[cfg(feature = "js_engine")] + InjectableMain::Script(_) => { + tokio::spawn(async move { start_up_image(rt_state, generated_certificate).await }) } - false => tokio::spawn(async move { start_up_image(rt_state, generated_certificate).await }), }; let ip = match is_injectable_main { false => Some(match get_running_ip(state, &mut runtime).await { @@ -219,6 +224,7 @@ async fn run_main( let res = tokio::select! { a = runtime => a.map_err(|_| Error::new(eyre!("Manager runtime panicked!"), crate::ErrorKind::Docker)).and_then(|a| a), _ = health => Err(Error::new(eyre!("Health check daemon exited!"), crate::ErrorKind::Unknown)), + }; if let Some(ip) = ip { remove_network_for_main(state, ip).await?; @@ -237,29 +243,6 @@ async fn start_up_image( .main .execute::<(), NoOutput>( &rt_state.ctx, - &rt_state.manifest.container, - &rt_state.manifest.id, - &rt_state.manifest.version, - ProcedureName::Main, - &rt_state.manifest.volumes, - None, - None, - ) - .await -} - -/// We want to start up the manifest, but in this case we want to know that we have generated the certificates. -/// Note for _generated_certificate: Needed to know that before we start the state we have generated the certificate -async fn start_up_inject_image( - rt_state: Arc, - _generated_certificate: GeneratedCertificateMountPoint, -) -> Result, Error> { - rt_state - .manifest - .main - .inject::<(), NoOutput>( - &rt_state.ctx, - &rt_state.manifest.container, &rt_state.manifest.id, &rt_state.manifest.version, ProcedureName::Main, @@ -295,8 +278,8 @@ impl Manager { let managers_persistant = persistant_container.clone(); let thread = tokio::spawn(async move { tokio::select! { - _ = manager_thread_loop(recv, &thread_shared, managers_persistant) => (), - _ = synchronizer(&*thread_shared) => (), + _ = manager_thread_loop(recv, &thread_shared, managers_persistant.clone()) => (), + _ = synchronizer(&*thread_shared, managers_persistant) => (), } }); Ok(Manager { @@ -348,16 +331,21 @@ impl Manager { .commit_health_check_results .store(false, Ordering::SeqCst); let _ = self.shared.on_stop.send(OnStop::Exit); - let sigterm_timeout: Option = match &self.shared.manifest.main + let sigterm_timeout: Option = match self + .shared + .manifest + .containers + .as_ref() + .map(|x| x.main.sigterm_timeout) { - PackageProcedure::Docker(DockerProcedure { - sigterm_timeout, .. - }) - | PackageProcedure::DockerInject(DockerInject { - sigterm_timeout, .. - }) => sigterm_timeout.clone(), - #[cfg(feature = "js_engine")] - PackageProcedure::Script(_) => return Ok(()), + Some(a) => a, + None => match &self.shared.manifest.main { + PackageProcedure::Docker(DockerProcedure { + sigterm_timeout, .. + }) => *sigterm_timeout, + #[cfg(feature = "js_engine")] + PackageProcedure::Script(_) => return Ok(()), + }, }; self.persistant_container.stop().await; @@ -392,7 +380,11 @@ impl Manager { a => a?, }; } else { - stop_non_first(&*self.shared.container_name).await; + stop_long_running_processes( + &*self.shared.container_name, + self.persistant_container.command_inserter.clone(), + ) + .await; } self.shared.status.store( @@ -414,6 +406,13 @@ impl Manager { self.shared.synchronize_now.notify_waiters(); self.shared.synchronized.notified().await } + + pub fn exec_command(&self) -> ExecCommand { + self.persistant_container.exec_command() + } + pub fn term_command(&self) -> TermCommand { + self.persistant_container.term_command() + } } async fn manager_thread_loop( @@ -460,7 +459,7 @@ async fn manager_thread_loop( ); } } - match run_main(&thread_shared, persistant_container.clone()).await { + match run_main(thread_shared, persistant_container.clone()).await { Ok(Ok(NoOutput)) => (), // restart Ok(Err(e)) => { let mut db = thread_shared.ctx.db.handle(); @@ -489,12 +488,9 @@ async fn manager_thread_loop( Some(3600) // 1 hour ) .await; - match res { - Err(e) => { - tracing::error!("Failed to issue notification: {}", e); - tracing::debug!("{:?}", e); - } - Ok(()) => {} + if let Err(e) = res { + tracing::error!("Failed to issue notification: {}", e); + tracing::debug!("{:?}", e); } } _ => tracing::error!("service just started. not issuing crash notification"), @@ -510,12 +506,121 @@ async fn manager_thread_loop( } } -struct PersistantContainer { +struct LongRunningHandle(NonDetachingJoinHandle<()>); +pub struct CommandInserter { + command_counter: AtomicUsize, + input: UnboundedSender, + outputs: Arc>>>, +} +impl Drop for CommandInserter { + fn drop(&mut self) { + use embassy_container_init::{Input, JsonRpc}; + let CommandInserter { + command_counter, + input, + outputs: _, + } = self; + let upper: usize = command_counter.load(Ordering::Relaxed); + for i in 0..upper { + let _ignored_result = input.send(JsonRpc::new(RpcId::UInt(i as u32), Input::Term())); + } + } +} +impl CommandInserter { + fn new( + long_running: LongRunning, + input: UnboundedSender, + ) -> (Self, LongRunningHandle) { + let LongRunning { + mut output, + running_output, + } = long_running; + let command_counter = AtomicUsize::new(0); + let outputs: Arc>>> = + Default::default(); + let handle = LongRunningHandle(running_output); + tokio::spawn({ + let outputs = outputs.clone(); + async move { + while let Some(output) = output.recv().await { + let (id, output) = output.into_pair(); + let mut outputs = outputs.lock().await; + let output_sender = outputs.get_mut(&id); + if let Some(output_sender) = output_sender { + if let Err(err) = output_sender.send(output) { + tracing::warn!("Could no longer send an output"); + tracing::debug!("{err:?}"); + outputs.remove(&id); + } + } + } + } + }); + + ( + Self { + command_counter, + input, + outputs, + }, + handle, + ) + } + + pub async fn exec_command( + &self, + command: String, + args: Vec, + sender: UnboundedSender, + timeout: Option, + ) -> Option { + use embassy_container_init::{Input, JsonRpc}; + let mut outputs = self.outputs.lock().await; + let command_counter = self.command_counter.fetch_add(1, Ordering::SeqCst) as u32; + let command_id = RpcId::UInt(command_counter); + outputs.insert(command_id.clone(), sender); + if let Some(timeout) = timeout { + tokio::spawn({ + let input = self.input.clone(); + let command_id = command_id.clone(); + async move { + tokio::time::sleep(timeout).await; + let _ignored_output = input.send(JsonRpc::new(command_id, Input::Kill())); + } + }); + } + if let Err(err) = self.input.send(JsonRpc::new( + command_id.clone(), + Input::Command { command, args }, + )) { + tracing::warn!("Trying to send to input but can't"); + tracing::debug!("{err:?}"); + return None; + } + + Some(command_id) + } + pub async fn term(&self, id: RpcId) { + use embassy_container_init::{Input, JsonRpc}; + self.outputs.lock().await.remove(&id); + let _ignored_term = self.input.send(JsonRpc::new(id, Input::Term())); + } + + pub async fn term_all(&self) { + for i in 0..self.command_counter.load(Ordering::Relaxed) { + self.term(RpcId::UInt(i as u32)).await; + } + } +} + +type RunningDocker = + Arc, Error>>>>>; +pub struct PersistantContainer { container_name: String, - running_docker: - Arc, Error>>>>>, + running_docker: RunningDocker, should_stop_running: Arc, wait_for_start: (Sender, Receiver), + command_inserter: Arc>>, } impl PersistantContainer { @@ -526,7 +631,8 @@ impl PersistantContainer { container_name: thread_shared.container_name.clone(), running_docker: Arc::new(Mutex::new(None)), should_stop_running: Arc::new(AtomicBool::new(false)), - wait_for_start: wait_for_start, + wait_for_start, + command_inserter: Default::default(), }); tokio::spawn(persistant_container( thread_shared.clone(), @@ -542,12 +648,7 @@ impl PersistantContainer { *running_docker = None; use tokio::process::Command; if let Err(_err) = Command::new("docker") - .args(["stop", "-t", "0", &*container_name]) - .output() - .await - {} - if let Err(_err) = Command::new("docker") - .args(["kill", &*container_name]) + .args(["stop", "-t", "30", container_name]) .output() .await {} @@ -569,22 +670,83 @@ impl PersistantContainer { async fn done_waiting(&self) { self.wait_for_start.0.send(false).unwrap(); } + fn term_command(&self) -> TermCommand { + let cloned = self.command_inserter.clone(); + Arc::new(move |id| { + let cloned = cloned.clone(); + Box::pin(async move { + let lock = cloned.lock().await; + let _id = match &*lock { + Some(command_inserter) => command_inserter.term(id).await, + None => { + return Err("Couldn't get a command inserter in current service".to_string()) + } + }; + Ok::<(), String>(()) + }) + }) + } + + fn exec_command(&self) -> ExecCommand { + let cloned = self.command_inserter.clone(); + + /// A handle that on drop will clean all the ids that are inserter in the fn. + struct Cleaner { + command_inserter: Arc>>, + ids: ::std::collections::BTreeSet, + } + impl Drop for Cleaner { + fn drop(&mut self) { + let command_inserter = self.command_inserter.clone(); + let ids = ::std::mem::take(&mut self.ids); + tokio::spawn(async move { + let command_inserter_lock = command_inserter.lock().await; + let command_inserter = match &*command_inserter_lock { + Some(a) => a, + None => { + return; + } + }; + for id in ids { + command_inserter.term(id).await; + } + }); + } + } + let cleaner = Arc::new(Mutex::new(Cleaner { + command_inserter: cloned.clone(), + ids: Default::default(), + })); + Arc::new(move |command, args, sender, timeout| { + let cloned = cloned.clone(); + let cleaner = cleaner.clone(); + Box::pin(async move { + let lock = cloned.lock().await; + let id = match &*lock { + Some(command_inserter) => { + if let Some(id) = command_inserter + .exec_command(command.clone(), args.clone(), sender, timeout) + .await + { + let mut cleaner = cleaner.lock().await; + cleaner.ids.insert(id.clone()); + id + } else { + return Err("Couldn't get command started ".to_string()); + } + } + None => { + return Err("Couldn't get a command inserter in current service".to_string()) + } + }; + Ok::(id) + }) + }) + } } impl Drop for PersistantContainer { fn drop(&mut self) { self.should_stop_running.store(true, Ordering::SeqCst); - let container_name = self.container_name.clone(); - let running_docker = self.running_docker.clone(); - tokio::spawn(async move { - let mut running_docker = running_docker.lock().await; - *running_docker = None; - - use std::process::Command; - if let Err(_err) = Command::new("docker") - .args(["kill", &*container_name]) - .output() - {} - }); } } @@ -594,12 +756,15 @@ async fn persistant_container( ) { let main_docker_procedure_for_long = injectable_main(&thread_shared); match main_docker_procedure_for_long { - Some(main) => loop { + InjectableMain::None => futures::future::pending().await, + #[cfg(feature = "js_engine")] + InjectableMain::Script((container_inject, procedure)) => loop { + let main = DockerProcedure::main_docker_procedure_js(container_inject, procedure); if container.should_stop_running.load(Ordering::SeqCst) { return; } container.start_wait().await; - match run_persistant_container(&thread_shared, container.clone(), main.clone()).await { + match run_persistant_container(&thread_shared, container.clone(), main).await { Ok(_) => (), Err(e) => { tracing::error!("failed to start persistant container: {}", e); @@ -607,60 +772,50 @@ async fn persistant_container( } } }, - None => futures::future::pending().await, } } -fn injectable_main(thread_shared: &Arc) -> Option> { - if let ( - PackageProcedure::DockerInject(DockerInject { - system, - entrypoint, - args, - io_format, - sigterm_timeout, - }), - Some(DockerContainer { - image, - mounts, - shm_size_mb, - }), - ) = ( +#[cfg(not(feature = "js_engine"))] +enum InjectableMain { + None, +} + +#[cfg(feature = "js_engine")] +enum InjectableMain<'a> { + None, + Script((&'a DockerContainer, &'a JsProcedure)), +} + +fn injectable_main(thread_shared: &Arc) -> InjectableMain { + match ( &thread_shared.manifest.main, - &thread_shared.manifest.container, + &thread_shared.manifest.containers.as_ref().map(|x| &x.main), ) { - Some(Arc::new(DockerProcedure { - image: image.clone(), - mounts: mounts.clone(), - io_format: *io_format, - shm_size_mb: *shm_size_mb, - sigterm_timeout: *sigterm_timeout, - system: *system, - entrypoint: "sleep".to_string(), - args: vec!["infinity".to_string()], - })) - } else { - None + #[cfg(feature = "js_engine")] + (PackageProcedure::Script(inject), Some(container)) => { + InjectableMain::Script((container, inject)) + } + _ => InjectableMain::None, } } fn check_is_injectable_main(thread_shared: &ManagerSharedState) -> bool { match &thread_shared.manifest.main { PackageProcedure::Docker(_a) => false, - PackageProcedure::DockerInject(a) => true, #[cfg(feature = "js_engine")] - PackageProcedure::Script(_) => false, + PackageProcedure::Script(_) => true, } } async fn run_persistant_container( state: &Arc, persistant: Arc, - docker_procedure: Arc, + docker_procedure: DockerProcedure, ) -> Result<(), Error> { let interfaces = states_main_interfaces(state)?; let generated_certificate = generate_certificate(state, &interfaces).await?; - let mut runtime = tokio::spawn(long_running_docker(state.clone(), docker_procedure)); + let mut runtime = + long_running_docker(state.clone(), docker_procedure, persistant.clone()).await?; - let ip = match get_running_ip(state, &mut runtime).await { + let ip = match get_long_running_ip(state, &mut runtime).await { GetRunninIp::Ip(x) => x, GetRunninIp::Error(e) => return Err(e), GetRunninIp::EarlyExit(e) => { @@ -674,7 +829,7 @@ async fn run_persistant_container( fetch_starting_to_running(state); let res = tokio::select! { - a = runtime => a.map_err(|_| Error::new(eyre!("Manager runtime panicked!"), crate::ErrorKind::Docker)).map(|_| ()), + a = runtime.0 => a.map_err(|_| Error::new(eyre!("Manager runtime panicked!"), crate::ErrorKind::Docker)).map(|_| ()), }; remove_network_for_main(state, ip).await?; res @@ -682,19 +837,23 @@ async fn run_persistant_container( async fn long_running_docker( rt_state: Arc, - main_status: Arc, -) -> Result, Error> { - main_status - .execute::<(), NoOutput>( + main_status: DockerProcedure, + container: Arc, +) -> Result { + let (sender, receiver) = tokio::sync::mpsc::unbounded_channel(); + let long_running = main_status + .long_running_execute( &rt_state.ctx, &rt_state.manifest.id, &rt_state.manifest.version, ProcedureName::LongRunning, &rt_state.manifest.volumes, - None, - None, + UnboundedReceiverStream::new(receiver), ) - .await + .await?; + let (command_inserter, long_running_handle) = CommandInserter::new(long_running, sender); + *container.command_inserter.lock().await = Some(command_inserter); + Ok(long_running_handle) } async fn remove_network_for_main( @@ -778,9 +937,11 @@ enum GetRunninIp { EarlyExit(Result), } +type RuntimeOfCommand = JoinHandle, Error>>; + async fn get_running_ip( state: &Arc, - mut runtime: &mut tokio::task::JoinHandle, Error>>, + mut runtime: &mut RuntimeOfCommand, ) -> GetRunninIp { loop { match container_inspect(state).await { @@ -805,8 +966,8 @@ async fn get_running_ip( }) => (), Err(e) => return GetRunninIp::Error(e.into()), } - match futures::poll!(&mut runtime) { - Poll::Ready(res) => match res { + if let Poll::Ready(res) = futures::poll!(&mut runtime) { + match res { Ok(Ok(response)) => return GetRunninIp::EarlyExit(response), Err(_) | Ok(Err(_)) => { return GetRunninIp::Error(Error::new( @@ -814,8 +975,48 @@ async fn get_running_ip( crate::ErrorKind::Docker, )) } - }, - _ => (), + } + } + } +} + +async fn get_long_running_ip( + state: &Arc, + runtime: &mut LongRunningHandle, +) -> GetRunninIp { + loop { + match container_inspect(state).await { + Ok(res) => { + match res + .network_settings + .and_then(|ns| ns.networks) + .and_then(|mut n| n.remove("start9")) + .and_then(|es| es.ip_address) + .filter(|ip| !ip.is_empty()) + .map(|ip| ip.parse()) + .transpose() + { + Ok(Some(ip_addr)) => return GetRunninIp::Ip(ip_addr), + Ok(None) => (), + Err(e) => return GetRunninIp::Error(e.into()), + } + } + Err(bollard::errors::Error::DockerResponseServerError { + status_code: 404, // NOT FOUND + .. + }) => (), + Err(e) => return GetRunninIp::Error(e.into()), + } + if let Poll::Ready(res) = futures::poll!(&mut runtime.0) { + match res { + Ok(_) => return GetRunninIp::EarlyExit(Ok(NoOutput)), + Err(_e) => { + return GetRunninIp::Error(Error::new( + eyre!("Manager runtime panicked!"), + crate::ErrorKind::Docker, + )) + } + } } } } @@ -838,11 +1039,11 @@ async fn generate_certificate( TorSecretKeyV3, )>, ) -> Result { - Ok(state + state .ctx .net_controller .generate_certificate_mountpoint(&state.manifest.id, interfaces) - .await?) + .await } fn states_main_interfaces( @@ -855,7 +1056,7 @@ fn states_main_interfaces( )>, Error, > { - Ok(state + state .manifest .interfaces .0 @@ -873,11 +1074,14 @@ fn states_main_interfaces( .clone(), )) }) - .collect::, Error>>()?) + .collect::, Error>>() } -#[instrument(skip(shared))] -async fn stop(shared: &ManagerSharedState) -> Result<(), Error> { +#[instrument(skip(shared, persistant_container))] +async fn stop( + shared: &ManagerSharedState, + persistant_container: Arc, +) -> Result<(), Error> { shared .commit_health_check_results .store(false, Ordering::SeqCst); @@ -896,9 +1100,6 @@ async fn stop(shared: &ManagerSharedState) -> Result<(), Error> { match &shared.manifest.main { PackageProcedure::Docker(DockerProcedure { sigterm_timeout, .. - }) - | PackageProcedure::DockerInject(DockerInject { - sigterm_timeout, .. }) => { if !check_is_injectable_main(shared) { match shared @@ -930,11 +1131,23 @@ async fn stop(shared: &ManagerSharedState) -> Result<(), Error> { a => a?, }; } else { - stop_non_first(&shared.container_name).await; + stop_long_running_processes( + &shared.container_name, + persistant_container.command_inserter.clone(), + ) + .await; } } #[cfg(feature = "js_engine")] - PackageProcedure::Script(_) => return Ok(()), + PackageProcedure::Script(_) => { + if check_is_injectable_main(shared) { + stop_long_running_processes( + &shared.container_name, + persistant_container.command_inserter.clone(), + ) + .await; + } + } }; tracing::debug!("Stopping a docker"); shared.status.store( @@ -945,11 +1158,13 @@ async fn stop(shared: &ManagerSharedState) -> Result<(), Error> { } /// So the sleep infinity, which is the long running, is pid 1. So we kill the others -async fn stop_non_first(container_name: &str) { - // tracing::error!("BLUJ TODO: sudo docker exec {} sh -c \"ps ax | awk '\\$1 ~ /^[:0-9:]/ && \\$1 > 1 {{print \\$1}}' | xargs kill\"", container_name); - - // (sleep infinity) & export RUNNING=$! && echo $! && (wait $RUNNING && echo "DONE FOR $RUNNING") & - // (RUNNING=$(sleep infinity & echo $!); echo "running $RUNNING"; wait $RUNNING; echo "DONE FOR ?") & +async fn stop_long_running_processes( + container_name: &str, + command_inserter: Arc>>, +) { + if let Some(command_inserter) = &*command_inserter.lock().await { + command_inserter.term_all().await; + } let _ = tokio::process::Command::new("docker") .args([ @@ -964,24 +1179,6 @@ async fn stop_non_first(container_name: &str) { .await; } -// #[test] -// fn test_stop_non_first() { -// assert_eq!( -// &format!( -// "{}", -// tokio::process::Command::new("docker").args([ -// "container", -// "exec", -// "container_name", -// "sh", -// "-c", -// "ps ax | awk \"\\$1 ~ /^[:0-9:]/ && \\$1 > 1 {print \\$1}\"| xargs kill", -// ]) -// ), -// "" -// ); -// } - #[instrument(skip(shared))] async fn start(shared: &ManagerSharedState) -> Result<(), Error> { shared.on_stop.send(OnStop::Restart).map_err(|_| { @@ -1002,8 +1199,11 @@ async fn start(shared: &ManagerSharedState) -> Result<(), Error> { Ok(()) } -#[instrument(skip(shared))] -async fn pause(shared: &ManagerSharedState) -> Result<(), Error> { +#[instrument(skip(shared, persistant_container))] +async fn pause( + shared: &ManagerSharedState, + persistant_container: Arc, +) -> Result<(), Error> { if let Err(e) = shared .ctx .docker @@ -1012,7 +1212,7 @@ async fn pause(shared: &ManagerSharedState) -> Result<(), Error> { { tracing::error!("failed to pause container. stopping instead. {}", e); tracing::debug!("{:?}", e); - return stop(shared).await; + return stop(shared, persistant_container).await; } shared .status diff --git a/backend/src/manager/sync.rs b/backend/src/manager/sync.rs index 5cb17aeb4..1e6927eee 100644 --- a/backend/src/manager/sync.rs +++ b/backend/src/manager/sync.rs @@ -1,16 +1,19 @@ -use std::collections::BTreeMap; use std::convert::TryInto; use std::sync::atomic::Ordering; use std::time::Duration; +use std::{collections::BTreeMap, sync::Arc}; use chrono::Utc; -use super::{pause, resume, start, stop, ManagerSharedState, Status}; +use super::{pause, resume, start, stop, ManagerSharedState, PersistantContainer, Status}; use crate::status::MainStatus; use crate::Error; /// Allocates a db handle. DO NOT CALL with a db handle already in scope -async fn synchronize_once(shared: &ManagerSharedState) -> Result { +async fn synchronize_once( + shared: &ManagerSharedState, + persistant_container: Arc, +) -> Result { let mut db = shared.ctx.db.handle(); let mut status = crate::db::DatabaseModel::new() .package_data() @@ -45,16 +48,16 @@ async fn synchronize_once(shared: &ManagerSharedState) -> Result }, Status::Starting => match *status { MainStatus::Stopped | MainStatus::Stopping | MainStatus::Restarting => { - stop(shared).await?; + stop(shared, persistant_container).await?; } MainStatus::Starting { .. } | MainStatus::Running { .. } => (), MainStatus::BackingUp { .. } => { - pause(shared).await?; + pause(shared, persistant_container).await?; } }, Status::Running => match *status { MainStatus::Stopped | MainStatus::Stopping | MainStatus::Restarting => { - stop(shared).await?; + stop(shared, persistant_container).await?; } MainStatus::Starting { .. } => { *status = MainStatus::Running { @@ -64,12 +67,12 @@ async fn synchronize_once(shared: &ManagerSharedState) -> Result } MainStatus::Running { .. } => (), MainStatus::BackingUp { .. } => { - pause(shared).await?; + pause(shared, persistant_container).await?; } }, Status::Paused => match *status { MainStatus::Stopped | MainStatus::Stopping | MainStatus::Restarting => { - stop(shared).await?; + stop(shared, persistant_container).await?; } MainStatus::Starting { .. } | MainStatus::Running { .. } => { resume(shared).await?; @@ -82,13 +85,16 @@ async fn synchronize_once(shared: &ManagerSharedState) -> Result Ok(manager_status) } -pub async fn synchronizer(shared: &ManagerSharedState) { +pub async fn synchronizer( + shared: &ManagerSharedState, + persistant_container: Arc, +) { loop { tokio::select! { _ = tokio::time::sleep(Duration::from_secs(5)) => (), _ = shared.synchronize_now.notified() => (), } - let status = match synchronize_once(shared).await { + let status = match synchronize_once(shared, persistant_container.clone()).await { Err(e) => { tracing::error!( "Synchronizer for {}@{} failed: {}", diff --git a/backend/src/middleware/encrypt.rs b/backend/src/middleware/encrypt.rs index 54064db23..e79ceea92 100644 --- a/backend/src/middleware/encrypt.rs +++ b/backend/src/middleware/encrypt.rs @@ -1,11 +1,7 @@ -use std::sync::Arc; - use aes::cipher::{CipherKey, NewCipher, Nonce, StreamCipher}; use aes::Aes256Ctr; -use futures::Stream; use hmac::Hmac; use josekit::jwk::Jwk; -use rpc_toolkit::hyper::{self, Body}; use serde::{Deserialize, Serialize}; use sha2::Sha256; use tracing::instrument; @@ -113,6 +109,6 @@ fn test_gen_awk() { }"#).unwrap(); assert_eq!( "testing12345", - &encrypted.decrypt(Arc::new(private_key)).unwrap() + &encrypted.decrypt(std::sync::Arc::new(private_key)).unwrap() ); } diff --git a/backend/src/migration.rs b/backend/src/migration.rs index 03e8fde0b..dae7138a3 100644 --- a/backend/src/migration.rs +++ b/backend/src/migration.rs @@ -10,7 +10,7 @@ use tracing::instrument; use crate::context::RpcContext; use crate::id::ImageId; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::procedure::{PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; use crate::util::Version; @@ -27,7 +27,7 @@ impl Migrations { #[instrument] pub fn validate( &self, - container: &Option, + container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, @@ -58,7 +58,7 @@ impl Migrations { #[instrument(skip(ctx))] pub fn from<'a>( &'a self, - container: &'a Option, + container: &'a Option, ctx: &'a RpcContext, version: &'a Version, pkg_id: &'a PackageId, @@ -70,11 +70,10 @@ impl Migrations { .iter() .find(|(range, _)| version.satisfies(*range)) { - Some( + Some(async move { migration .execute( ctx, - container, pkg_id, pkg_version, ProcedureName::Migration, // Migrations cannot be executed concurrently @@ -88,8 +87,9 @@ impl Migrations { Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed) }) }) - }), - ) + }) + .await + }) } else { None } @@ -98,7 +98,6 @@ impl Migrations { #[instrument(skip(ctx))] pub fn to<'a>( &'a self, - container: &'a Option, ctx: &'a RpcContext, version: &'a Version, pkg_id: &'a PackageId, @@ -106,11 +105,10 @@ impl Migrations { volumes: &'a Volumes, ) -> Option> + 'a> { if let Some((_, migration)) = self.to.iter().find(|(range, _)| version.satisfies(*range)) { - Some( + Some(async move { migration .execute( ctx, - container, pkg_id, pkg_version, ProcedureName::Migration, @@ -124,8 +122,9 @@ impl Migrations { Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed) }) }) - }), - ) + }) + .await + }) } else { None } diff --git a/backend/src/procedure/docker.rs b/backend/src/procedure/docker.rs index e9460fc1b..663ebb7c0 100644 --- a/backend/src/procedure/docker.rs +++ b/backend/src/procedure/docker.rs @@ -9,14 +9,19 @@ use async_stream::stream; use bollard::container::RemoveContainerOptions; use color_eyre::eyre::eyre; use color_eyre::Report; +use embassy_container_init::{InputJsonRpc, OutputJsonRpc}; use futures::future::Either as EitherFuture; -use futures::TryStreamExt; +use futures::{Stream, StreamExt, TryFutureExt, TryStreamExt}; use helpers::NonDetachingJoinHandle; use nix::sys::signal; use nix::unistd::Pid; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Value; -use tokio::io::{AsyncBufRead, AsyncBufReadExt, BufReader}; +use tokio::{ + io::{AsyncBufRead, AsyncBufReadExt, BufReader}, + process::Child, + sync::mpsc::UnboundedReceiver, +}; use tracing::instrument; use super::ProcedureName; @@ -41,6 +46,17 @@ lazy_static::lazy_static! { }; } +#[derive(Clone, Debug, Deserialize, Serialize, patch_db::HasModel)] +#[serde(rename_all = "kebab-case")] +pub struct DockerContainers { + pub main: DockerContainer, + // #[serde(default)] + // pub aux: BTreeMap, +} + +/// This is like the docker procedures of the past designs, +/// but this time all the entrypoints and args are not +/// part of this struct by choice. Used for the times that we are creating our own entry points #[derive(Clone, Debug, Deserialize, Serialize, patch_db::HasModel)] #[serde(rename_all = "kebab-case")] pub struct DockerContainer { @@ -49,6 +65,10 @@ pub struct DockerContainer { pub mounts: BTreeMap, #[serde(default)] pub shm_size_mb: Option, // TODO: use postfix sizing? like 1k vs 1m vs 1g + #[serde(default)] + pub sigterm_timeout: Option, + #[serde(default)] + pub system: bool, } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -70,7 +90,7 @@ pub struct DockerProcedure { pub shm_size_mb: Option, // TODO: use postfix sizing? like 1k vs 1m vs 1g } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, Default)] #[serde(rename_all = "kebab-case")] pub struct DockerInject { #[serde(default)] @@ -83,26 +103,42 @@ pub struct DockerInject { #[serde(default)] pub sigterm_timeout: Option, } - -impl From<(&DockerContainer, &DockerInject)> for DockerProcedure { - fn from((container, injectable): (&DockerContainer, &DockerInject)) -> Self { +impl DockerProcedure { + pub fn main_docker_procedure( + container: &DockerContainer, + injectable: &DockerInject, + ) -> DockerProcedure { DockerProcedure { image: container.image.clone(), - system: injectable.system.clone(), + system: injectable.system, entrypoint: injectable.entrypoint.clone(), args: injectable.args.clone(), mounts: container.mounts.clone(), - io_format: injectable.io_format.clone(), - sigterm_timeout: injectable.sigterm_timeout.clone(), - shm_size_mb: container.shm_size_mb.clone(), + io_format: injectable.io_format, + sigterm_timeout: injectable.sigterm_timeout, + shm_size_mb: container.shm_size_mb, + } + } + #[cfg(feature = "js_engine")] + pub fn main_docker_procedure_js( + container: &DockerContainer, + _procedure: &super::js_scripts::JsProcedure, + ) -> DockerProcedure { + DockerProcedure { + image: container.image.clone(), + system: container.system, + entrypoint: "sleep".to_string(), + args: Vec::new(), + mounts: container.mounts.clone(), + io_format: None, + sigterm_timeout: container.sigterm_timeout, + shm_size_mb: container.shm_size_mb, } } -} -impl DockerProcedure { pub fn validate( &self, - eos_version: &Version, + _eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, expected_io: bool, @@ -116,10 +152,8 @@ impl DockerProcedure { if !SYSTEM_IMAGES.contains(&self.image) { color_eyre::eyre::bail!("unknown system image: {}", self.image); } - } else { - if !image_ids.contains(&self.image) { - color_eyre::eyre::bail!("image for {} not contained in package", self.image); - } + } else if !image_ids.contains(&self.image) { + color_eyre::eyre::bail!("image for {} not contained in package", self.image); } if expected_io && self.io_format.is_none() { color_eyre::eyre::bail!("expected io-format"); @@ -128,7 +162,7 @@ impl DockerProcedure { } #[instrument(skip(ctx, input))] - pub async fn execute Deserialize<'de>>( + pub async fn execute( &self, ctx: &RpcContext, pkg_id: &PackageId, @@ -217,7 +251,7 @@ impl DockerProcedure { handle .stdout .take() - .ok_or_else(|| eyre!("Can't takeout stout")) + .ok_or_else(|| eyre!("Can't takeout stdout in execute")) .with_kind(crate::ErrorKind::Docker)?, ); let output = NonDetachingJoinHandle::from(tokio::spawn(async move { @@ -307,25 +341,83 @@ impl DockerProcedure { ) } + /// We created a new exec runner, where we are going to be passing the commands for it to run. + /// Idea is that we are going to send it command and get the inputs be filtered back from the manager. + /// Then we could in theory run commands without the cost of running the docker exec which is known to have + /// a dely of > 200ms which is not acceptable. #[instrument(skip(ctx, input))] - pub async fn inject Deserialize<'de>>( + pub async fn long_running_execute( &self, ctx: &RpcContext, pkg_id: &PackageId, pkg_version: &Version, name: ProcedureName, volumes: &Volumes, + input: S, + ) -> Result + where + S: Stream + Send + 'static, + { + let name = name.docker_name(); + let name: Option<&str> = name.as_deref(); + let container_name = Self::container_name(pkg_id, name); + + let mut cmd = LongRunning::setup_long_running_docker_cmd( + self, + ctx, + &container_name, + volumes, + pkg_id, + pkg_version, + ) + .await?; + + let mut handle = cmd.spawn().with_kind(crate::ErrorKind::Docker)?; + let input_handle = LongRunning::spawn_input_handle(&mut handle, input)? + .map_err(|e| eyre!("Input Handle Error: {e:?}")); + + let (output, output_handle) = LongRunning::spawn_output_handle(&mut handle)?; + let output_handle = output_handle.map_err(|e| eyre!("Output Handle Error: {e:?}")); + let err_handle = LongRunning::spawn_error_handle(&mut handle)? + .map_err(|e| eyre!("Err Handle Error: {e:?}")); + + let running_output = NonDetachingJoinHandle::from(tokio::spawn(async move { + if let Err(err) = tokio::select!( + x = handle.wait().map_err(|e| eyre!("Runtime error: {e:?}")) => x.map(|_| ()), + x = err_handle => x.map(|_| ()), + x = output_handle => x.map(|_| ()), + x = input_handle => x.map(|_| ()) + ) { + tracing::debug!("{:?}", err); + tracing::error!("Join error"); + } + })); + + Ok(LongRunning { + output, + running_output, + }) + } + + #[instrument(skip(_ctx, input))] + pub async fn inject( + &self, + _ctx: &RpcContext, + pkg_id: &PackageId, + pkg_version: &Version, + name: ProcedureName, + volumes: &Volumes, input: Option, timeout: Option, ) -> Result, Error> { let name = name.docker_name(); - let name: Option<&str> = name.as_ref().map(|x| &**x); + let name: Option<&str> = name.as_deref(); let mut cmd = tokio::process::Command::new("docker"); tracing::debug!("{:?} is exec", name); cmd.arg("exec"); - cmd.args(self.docker_args_inject(ctx, pkg_id, pkg_version).await?); + cmd.args(self.docker_args_inject(pkg_id).await?); let input_buf = if let (Some(input), Some(format)) = (&input, &self.io_format) { cmd.stdin(std::process::Stdio::piped()); Some(format.to_vec(input)?) @@ -372,7 +464,7 @@ impl DockerProcedure { handle .stdout .take() - .ok_or_else(|| eyre!("Can't takeout stout")) + .ok_or_else(|| eyre!("Can't takeout stdout in inject")) .with_kind(crate::ErrorKind::Docker)?, ); let output = NonDetachingJoinHandle::from(tokio::spawn(async move { @@ -463,7 +555,7 @@ impl DockerProcedure { } #[instrument(skip(ctx, input))] - pub async fn sandboxed Deserialize<'de>>( + pub async fn sandboxed( &self, ctx: &RpcContext, pkg_id: &PackageId, @@ -513,7 +605,7 @@ impl DockerProcedure { handle .stdout .take() - .ok_or_else(|| eyre!("Can't takeout stout")) + .ok_or_else(|| eyre!("Can't takeout stdout in sandboxed")) .with_kind(crate::ErrorKind::Docker)?, ); let output = NonDetachingJoinHandle::from(tokio::spawn(async move { @@ -607,7 +699,7 @@ impl DockerProcedure { continue; }; let src = volume.path_for(&ctx.datadir, pkg_id, pkg_version, volume_id); - if let Err(e) = tokio::fs::metadata(&src).await { + if let Err(_e) = tokio::fs::metadata(&src).await { tokio::fs::create_dir_all(&src).await?; } res.push(OsStr::new("--mount").into()); @@ -626,7 +718,6 @@ impl DockerProcedure { res.push(OsString::from(format!("{}m", shm_size_mb)).into()); } res.push(OsStr::new("--interactive").into()); - res.push(OsStr::new("--log-driver=journald").into()); res.push(OsStr::new("--entrypoint").into()); res.push(OsStr::new(&self.entrypoint).into()); @@ -649,12 +740,7 @@ impl DockerProcedure { + self.args.len(), // [ARG...] ) } - async fn docker_args_inject( - &self, - ctx: &RpcContext, - pkg_id: &PackageId, - pkg_version: &Version, - ) -> Result>, Error> { + async fn docker_args_inject(&self, pkg_id: &PackageId) -> Result>, Error> { let mut res = self.new_docker_args(); if let Some(shm_size_mb) = self.shm_size_mb { res.push(OsStr::new("--shm-size").into()); @@ -693,6 +779,215 @@ impl RingVec { } } +/// This is created when we wanted a long running docker executor that we could send commands to and get the responses back. +/// We wanted a long running since we want to be able to have the equivelent to the docker execute without the heavy costs of 400 + ms time lag. +/// Also the long running let's us have the ability to start/ end the services quicker. +pub struct LongRunning { + pub output: UnboundedReceiver, + pub running_output: NonDetachingJoinHandle<()>, +} + +impl LongRunning { + async fn setup_long_running_docker_cmd( + docker: &DockerProcedure, + ctx: &RpcContext, + container_name: &str, + volumes: &Volumes, + pkg_id: &PackageId, + pkg_version: &Version, + ) -> Result { + tracing::error!("BLUJ setup_long_running_docker_cmd {container_name}"); + const INIT_EXEC: &str = "/start9/embassy_container_init"; + const BIND_LOCATION: &str = "/usr/lib/embassy/container"; + tracing::trace!("setup_long_running_docker_cmd"); + + LongRunning::cleanup_previous_container(ctx, container_name).await?; + + let image_architecture = { + let mut cmd = tokio::process::Command::new("docker"); + cmd.arg("image") + .arg("inspect") + .arg("--format") + .arg("'{{.Architecture}}'"); + + if docker.system { + cmd.arg(docker.image.for_package(SYSTEM_PACKAGE_ID, None)); + } else { + cmd.arg(docker.image.for_package(pkg_id, Some(pkg_version))); + } + let arch = String::from_utf8(cmd.output().await?.stdout)?; + arch.replace('\'', "").trim().to_string() + }; + + let mut cmd = tokio::process::Command::new("docker"); + cmd.arg("run") + .arg("--network=start9") + .arg(format!("--add-host=embassy:{}", Ipv4Addr::from(HOST_IP))) + .arg("--mount") + .arg(format!("type=bind,src={BIND_LOCATION},dst=/start9")) + .arg("--name") + .arg(&container_name) + .arg(format!("--hostname={}", &container_name)) + .arg("--entrypoint") + .arg(format!("{INIT_EXEC}.{image_architecture}")) + .arg("-i") + .arg("--rm"); + + for (volume_id, dst) in &docker.mounts { + let volume = if let Some(v) = volumes.get(volume_id) { + v + } else { + continue; + }; + let src = volume.path_for(&ctx.datadir, pkg_id, pkg_version, volume_id); + if let Err(_e) = tokio::fs::metadata(&src).await { + tokio::fs::create_dir_all(&src).await?; + } + cmd.arg("--mount").arg(format!( + "type=bind,src={},dst={}{}", + src.display(), + dst.display(), + if volume.readonly() { ",readonly" } else { "" } + )); + } + if let Some(shm_size_mb) = docker.shm_size_mb { + cmd.arg("--shm-size").arg(format!("{}m", shm_size_mb)); + } + cmd.arg("--log-driver=journald"); + if docker.system { + cmd.arg(docker.image.for_package(SYSTEM_PACKAGE_ID, None)); + } else { + cmd.arg(docker.image.for_package(pkg_id, Some(pkg_version))); + } + cmd.stdout(std::process::Stdio::piped()); + cmd.stderr(std::process::Stdio::piped()); + cmd.stdin(std::process::Stdio::piped()); + Ok(cmd) + } + + async fn cleanup_previous_container( + ctx: &RpcContext, + container_name: &str, + ) -> Result<(), Error> { + match ctx + .docker + .remove_container( + container_name, + Some(RemoveContainerOptions { + v: false, + force: true, + link: false, + }), + ) + .await + { + Ok(()) + | Err(bollard::errors::Error::DockerResponseServerError { + status_code: 404, // NOT FOUND + .. + }) => Ok(()), + Err(e) => Err(e)?, + } + } + fn spawn_input_handle( + handle: &mut Child, + input: S, + ) -> Result, Error> + where + S: Stream + Send + 'static, + { + use tokio::io::AsyncWriteExt; + let mut stdin = handle + .stdin + .take() + .ok_or_else(|| eyre!("Can't takeout stdin")) + .with_kind(crate::ErrorKind::Docker)?; + let handle = NonDetachingJoinHandle::from(tokio::spawn(async move { + let input = input; + tokio::pin!(input); + while let Some(input) = input.next().await { + let input = match serde_json::to_string(&input) { + Ok(a) => a, + Err(e) => { + tracing::debug!("{:?}", e); + tracing::error!("Docker Input Serialization issue"); + continue; + } + }; + if let Err(e) = stdin.write_all(format!("{input}\n").as_bytes()).await { + tracing::debug!("{:?}", e); + tracing::error!("Docker Input issue"); + return; + } + } + })); + Ok(handle) + } + fn spawn_error_handle(handle: &mut Child) -> Result, Error> { + let id = handle.id(); + let mut output = tokio::io::BufReader::new( + handle + .stderr + .take() + .ok_or_else(|| eyre!("Can't takeout stderr")) + .with_kind(crate::ErrorKind::Docker)?, + ) + .lines(); + Ok(NonDetachingJoinHandle::from(tokio::spawn(async move { + while let Ok(Some(line)) = output.next_line().await { + tracing::debug!("{:?}", id); + tracing::error!("Error from long running container"); + tracing::error!("{}", line); + } + }))) + } + + fn spawn_output_handle( + handle: &mut Child, + ) -> Result<(UnboundedReceiver, NonDetachingJoinHandle<()>), Error> { + let mut output = tokio::io::BufReader::new( + handle + .stdout + .take() + .ok_or_else(|| eyre!("Can't takeout stdout for long running")) + .with_kind(crate::ErrorKind::Docker)?, + ) + .lines(); + let (sender, receiver) = tokio::sync::mpsc::unbounded_channel::(); + Ok(( + receiver, + NonDetachingJoinHandle::from(tokio::spawn(async move { + loop { + let next = output.next_line().await; + let next = match next { + Ok(Some(a)) => a, + Ok(None) => { + tracing::error!("The docker pipe is closed?"); + break; + } + Err(e) => { + tracing::debug!("{:?}", e); + tracing::error!("Output from docker, killing"); + break; + } + }; + let next = match serde_json::from_str(&next) { + Ok(a) => a, + Err(_e) => { + tracing::trace!("Could not decode output from long running binary"); + continue; + } + }; + if let Err(e) = sender.send(next) { + tracing::debug!("{:?}", e); + tracing::error!("Could no longer send output"); + break; + } + } + })), + )) + } +} async fn buf_reader_to_lines( reader: impl AsyncBufRead + Unpin, limit: impl Into>, @@ -756,6 +1051,7 @@ async fn max_by_lines( } MaxByLines::Done(answer) } + #[cfg(test)] mod tests { use super::*; diff --git a/backend/src/procedure/js_scripts.rs b/backend/src/procedure/js_scripts.rs index a840d02e4..70a1a7b77 100644 --- a/backend/src/procedure/js_scripts.rs +++ b/backend/src/procedure/js_scripts.rs @@ -1,10 +1,12 @@ use std::path::{Path, PathBuf}; +use std::sync::Arc; use std::time::Duration; pub use js_engine::JsError; use js_engine::{JsExecutionEnvironment, PathForVolumeId}; use models::VolumeId; -use serde::{Deserialize, Serialize}; +use models::{ExecCommand, TermCommand}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use tracing::instrument; use super::ProcedureName; @@ -52,8 +54,8 @@ impl JsProcedure { Ok(()) } - #[instrument(skip(directory, input))] - pub async fn execute Deserialize<'de>>( + #[instrument(skip(directory, input, exec_command, term_command))] + pub async fn execute( &self, directory: &PathBuf, pkg_id: &PackageId, @@ -62,6 +64,8 @@ impl JsProcedure { volumes: &Volumes, input: Option, timeout: Option, + exec_command: ExecCommand, + term_command: TermCommand, ) -> Result, Error> { Ok(async move { let running_action = JsExecutionEnvironment::load_from_package( @@ -69,6 +73,8 @@ impl JsProcedure { pkg_id, pkg_version, Box::new(volumes.clone()), + exec_command, + term_command, ) .await? .run_action(name, input, self.args.clone()); @@ -86,7 +92,7 @@ impl JsProcedure { } #[instrument(skip(ctx, input))] - pub async fn sandboxed Deserialize<'de>>( + pub async fn sandboxed( &self, ctx: &RpcContext, pkg_id: &PackageId, @@ -102,6 +108,12 @@ impl JsProcedure { pkg_id, pkg_version, Box::new(volumes.clone()), + Arc::new(|_, _, _, _| { + Box::pin(async { Err("Can't run commands in sandox mode".to_string()) }) + }), + Arc::new(|_| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), ) .await? .read_only_effects() @@ -120,7 +132,7 @@ impl JsProcedure { } } -fn unwrap_known_error Deserialize<'de>>( +fn unwrap_known_error( error_value: ErrorValue, ) -> Result { match error_value { @@ -181,6 +193,10 @@ async fn js_action_execute() { &volumes, input, timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), ) .await .unwrap() @@ -236,6 +252,10 @@ async fn js_action_execute_error() { &volumes, input, timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), ) .await .unwrap(); @@ -280,11 +300,70 @@ async fn js_action_fetch() { &volumes, input, timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), ) .await .unwrap() .unwrap(); } + +#[tokio::test] +async fn js_test_slow() { + let js_action = JsProcedure { args: vec![] }; + let path: PathBuf = "test/js_action_execute/" + .parse::() + .unwrap() + .canonicalize() + .unwrap(); + let package_id = "test-package".parse().unwrap(); + let package_version: Version = "0.3.0.3".parse().unwrap(); + let name = ProcedureName::Action("slow".parse().unwrap()); + let volumes: Volumes = serde_json::from_value(serde_json::json!({ + "main": { + "type": "data" + }, + "compat": { + "type": "assets" + }, + "filebrowser" :{ + "package-id": "filebrowser", + "path": "data", + "readonly": true, + "type": "pointer", + "volume-id": "main", + } + })) + .unwrap(); + let input: Option = None; + let timeout = Some(Duration::from_secs(10)); + tracing::debug!("testing start"); + tokio::select! { + a = js_action + .execute::( + &path, + &package_id, + &package_version, + name, + &volumes, + input, + timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), + ) + => {a + .unwrap() + .unwrap();}, + _ = tokio::time::sleep(Duration::from_secs(1)) => () + } + tracing::debug!("testing end should"); + tokio::time::sleep(Duration::from_secs(2)).await; + tracing::debug!("Done"); +} #[tokio::test] async fn js_action_var_arg() { let js_action = JsProcedure { @@ -325,6 +404,10 @@ async fn js_action_var_arg() { &volumes, input, timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), ) .await .unwrap() @@ -369,6 +452,10 @@ async fn js_action_test_rename() { &volumes, input, timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), ) .await .unwrap() @@ -413,6 +500,10 @@ async fn js_action_test_deep_dir() { &volumes, input, timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), ) .await .unwrap() @@ -456,6 +547,10 @@ async fn js_action_test_deep_dir_escape() { &volumes, input, timeout, + Arc::new(|_, _, _, _| { + Box::pin(async move { Err("Can't run commands in test".to_string()) }) + }), + Arc::new(|_| Box::pin(async move { Err("Can't run commands in test".to_string()) })), ) .await .unwrap() diff --git a/backend/src/procedure/mod.rs b/backend/src/procedure/mod.rs index bbdfaedb2..1cee646fc 100644 --- a/backend/src/procedure/mod.rs +++ b/backend/src/procedure/mod.rs @@ -1,18 +1,18 @@ use std::collections::BTreeSet; use std::time::Duration; -use color_eyre::eyre::{bail, eyre}; +use color_eyre::eyre::eyre; use patch_db::HasModel; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use tracing::instrument; -use self::docker::{DockerContainer, DockerInject, DockerProcedure}; +use self::docker::{DockerContainers, DockerProcedure}; use crate::context::RpcContext; use crate::id::ImageId; use crate::s9pk::manifest::PackageId; use crate::util::Version; use crate::volume::Volumes; -use crate::Error; +use crate::{Error, ErrorKind}; pub mod docker; #[cfg(feature = "js_engine")] @@ -26,7 +26,6 @@ pub use models::ProcedureName; #[serde(tag = "type")] pub enum PackageProcedure { Docker(DockerProcedure), - DockerInject(DockerInject), #[cfg(feature = "js_engine")] Script(js_scripts::JsProcedure), @@ -43,7 +42,7 @@ impl PackageProcedure { #[instrument] pub fn validate( &self, - container: &Option, + container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, @@ -53,25 +52,15 @@ impl PackageProcedure { PackageProcedure::Docker(action) => { action.validate(eos_version, volumes, image_ids, expected_io) } - PackageProcedure::DockerInject(injectable) => { - let container = match container { - None => bail!("For the docker injectable procedure, a container must be exist on the config"), - Some(container) => container, - } ; - let docker_procedure: DockerProcedure = (container, injectable).into(); - docker_procedure.validate(eos_version, volumes, image_ids, expected_io) - } - #[cfg(feature = "js_engine")] PackageProcedure::Script(action) => action.validate(volumes), } } - #[instrument(skip(ctx, input, container))] - pub async fn execute Deserialize<'de>>( + #[instrument(skip(ctx, input))] + pub async fn execute( &self, ctx: &RpcContext, - container: &Option, pkg_id: &PackageId, pkg_version: &Version, name: ProcedureName, @@ -86,18 +75,36 @@ impl PackageProcedure { .execute(ctx, pkg_id, pkg_version, name, volumes, input, timeout) .await } - PackageProcedure::DockerInject(injectable) => { - let container = match container { - None => return Err(Error::new(eyre!("For the docker injectable procedure, a container must be exist on the config"), crate::ErrorKind::Action)), - Some(container) => container, - } ; - let docker_procedure: DockerProcedure = (container, injectable).into(); - docker_procedure - .inject(ctx, pkg_id, pkg_version, name, volumes, input, timeout) - .await - } #[cfg(feature = "js_engine")] PackageProcedure::Script(procedure) => { + let exec_command = match ctx + .managers + .get(&(pkg_id.clone(), pkg_version.clone())) + .await + { + None => { + return Err(Error::new( + eyre!("No manager found for {}", pkg_id), + ErrorKind::NotFound, + )) + } + Some(x) => x, + } + .exec_command(); + let term_command = match ctx + .managers + .get(&(pkg_id.clone(), pkg_version.clone())) + .await + { + None => { + return Err(Error::new( + eyre!("No manager found for {}", pkg_id), + ErrorKind::NotFound, + )) + } + Some(x) => x, + } + .term_command(); procedure .execute( &ctx.datadir, @@ -107,17 +114,18 @@ impl PackageProcedure { volumes, input, timeout, + exec_command, + term_command, ) .await } } } - #[instrument(skip(ctx, input, container))] - pub async fn inject Deserialize<'de>>( + #[instrument(skip(ctx, input))] + pub async fn inject( &self, ctx: &RpcContext, - container: &Option, pkg_id: &PackageId, pkg_version: &Version, name: ProcedureName, @@ -125,25 +133,42 @@ impl PackageProcedure { input: Option, timeout: Option, ) -> Result, Error> { - tracing::trace!("Procedure inject {} {} - {:?}", self, pkg_id, name); match self { PackageProcedure::Docker(procedure) => { procedure .inject(ctx, pkg_id, pkg_version, name, volumes, input, timeout) .await } - PackageProcedure::DockerInject(injectable) => { - let container = match container { - None => return Err(Error::new(eyre!("For the docker injectable procedure, a container must be exist on the config"), crate::ErrorKind::Action)), - Some(container) => container, - } ; - let docker_procedure: DockerProcedure = (container, injectable).into(); - docker_procedure - .inject(ctx, pkg_id, pkg_version, name, volumes, input, timeout) - .await - } #[cfg(feature = "js_engine")] PackageProcedure::Script(procedure) => { + let exec_command = match ctx + .managers + .get(&(pkg_id.clone(), pkg_version.clone())) + .await + { + None => { + return Err(Error::new( + eyre!("No manager found for {}", pkg_id), + ErrorKind::NotFound, + )) + } + Some(x) => x, + } + .exec_command(); + let term_command = match ctx + .managers + .get(&(pkg_id.clone(), pkg_version.clone())) + .await + { + None => { + return Err(Error::new( + eyre!("No manager found for {}", pkg_id), + ErrorKind::NotFound, + )) + } + Some(x) => x, + } + .term_command(); procedure .execute( &ctx.datadir, @@ -153,15 +178,17 @@ impl PackageProcedure { volumes, input, timeout, + exec_command, + term_command, ) .await } } } #[instrument(skip(ctx, input))] - pub async fn sandboxed Deserialize<'de>>( + pub async fn sandboxed( &self, - container: &Option, + container: &Option, ctx: &RpcContext, pkg_id: &PackageId, pkg_version: &Version, @@ -177,16 +204,6 @@ impl PackageProcedure { .sandboxed(ctx, pkg_id, pkg_version, volumes, input, timeout) .await } - PackageProcedure::DockerInject(injectable) => { - let container = match container { - None => return Err(Error::new(eyre!("For the docker injectable procedure, a container must be exist on the config"), crate::ErrorKind::Action)), - Some(container) => container, - } ; - let docker_procedure: DockerProcedure = (container, injectable).into(); - docker_procedure - .sandboxed(ctx, pkg_id, pkg_version, volumes, input, timeout) - .await - } #[cfg(feature = "js_engine")] PackageProcedure::Script(procedure) => { procedure @@ -200,7 +217,6 @@ impl PackageProcedure { impl std::fmt::Display for PackageProcedure { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - PackageProcedure::DockerInject(_) => write!(f, "Docker Injectable")?, PackageProcedure::Docker(_) => write!(f, "Docker")?, #[cfg(feature = "js_engine")] PackageProcedure::Script(_) => write!(f, "JS")?, @@ -208,6 +224,7 @@ impl std::fmt::Display for PackageProcedure { Ok(()) } } + #[derive(Debug)] pub struct NoOutput; impl<'de> Deserialize<'de> for NoOutput { diff --git a/backend/src/properties.rs b/backend/src/properties.rs index 72a977063..782f7e783 100644 --- a/backend/src/properties.rs +++ b/backend/src/properties.rs @@ -21,6 +21,7 @@ pub async fn properties(#[context] ctx: RpcContext, #[arg] id: PackageId) -> Res #[instrument(skip(ctx))] pub async fn fetch_properties(ctx: RpcContext, id: PackageId) -> Result { let mut db = ctx.db.handle(); + let manifest: Manifest = crate::db::DatabaseModel::new() .package_data() .idx_model(&id) @@ -34,7 +35,6 @@ pub async fn fetch_properties(ctx: RpcContext, id: PackageId) -> Result( &ctx, - &manifest.container, &manifest.id, &manifest.version, ProcedureName::Properties, diff --git a/backend/src/s9pk/manifest.rs b/backend/src/s9pk/manifest.rs index f836b2348..311b4f2a0 100644 --- a/backend/src/s9pk/manifest.rs +++ b/backend/src/s9pk/manifest.rs @@ -12,7 +12,7 @@ use crate::config::action::ConfigActions; use crate::dependencies::Dependencies; use crate::migration::Migrations; use crate::net::interface::Interfaces; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::procedure::PackageProcedure; use crate::status::health_check::HealthChecks; use crate::util::Version; @@ -72,7 +72,7 @@ pub struct Manifest { #[model] pub dependencies: Dependencies, #[model] - pub container: Option, + pub containers: Option, } impl Manifest { diff --git a/backend/src/s9pk/reader.rs b/backend/src/s9pk/reader.rs index 9c7d60e7b..b6dcd3dda 100644 --- a/backend/src/s9pk/reader.rs +++ b/backend/src/s9pk/reader.rs @@ -176,7 +176,7 @@ impl S9pkReader { } let image_tags = self.image_tags().await?; let man = self.manifest().await?; - let container = &man.container; + let containers = &man.containers; let validated_image_ids = image_tags .into_iter() .map(|i| i.validate(&man.id, &man.version).map(|_| i.image_id)) @@ -187,7 +187,7 @@ impl S9pkReader { .iter() .map(|(_, action)| { action.validate( - container, + containers, &man.eos_version, &man.volumes, &validated_image_ids, @@ -195,21 +195,21 @@ impl S9pkReader { }) .collect::>()?; man.backup.validate( - container, + containers, &man.eos_version, &man.volumes, &validated_image_ids, )?; if let Some(cfg) = &man.config { cfg.validate( - container, + containers, &man.eos_version, &man.volumes, &validated_image_ids, )?; } man.health_checks.validate( - container, + containers, &man.eos_version, &man.volumes, &validated_image_ids, @@ -217,7 +217,7 @@ impl S9pkReader { man.interfaces.validate()?; man.main .validate( - container, + containers, &man.eos_version, &man.volumes, &validated_image_ids, @@ -225,7 +225,7 @@ impl S9pkReader { ) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, "Main"))?; man.migrations.validate( - container, + containers, &man.eos_version, &man.volumes, &validated_image_ids, @@ -233,7 +233,7 @@ impl S9pkReader { if let Some(props) = &man.properties { props .validate( - container, + containers, &man.eos_version, &man.volumes, &validated_image_ids, diff --git a/backend/src/status/health_check.rs b/backend/src/status/health_check.rs index 9b1a27b85..d94debf9f 100644 --- a/backend/src/status/health_check.rs +++ b/backend/src/status/health_check.rs @@ -7,7 +7,7 @@ use tracing::instrument; use crate::context::RpcContext; use crate::id::ImageId; -use crate::procedure::docker::DockerContainer; +use crate::procedure::docker::DockerContainers; use crate::procedure::{NoOutput, PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; use crate::util::serde::Duration; @@ -21,7 +21,7 @@ impl HealthChecks { #[instrument] pub fn validate( &self, - container: &Option, + container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, @@ -42,7 +42,7 @@ impl HealthChecks { pub async fn check_all( &self, ctx: &RpcContext, - container: &Option, + container: &Option, started: DateTime, pkg_id: &PackageId, pkg_version: &Version, @@ -75,7 +75,7 @@ impl HealthCheck { pub async fn check( &self, ctx: &RpcContext, - container: &Option, + container: &Option, id: &HealthCheckId, started: DateTime, pkg_id: &PackageId, @@ -86,7 +86,6 @@ impl HealthCheck { .implementation .execute( ctx, - container, pkg_id, pkg_version, ProcedureName::Health(id.clone()), diff --git a/backend/src/util/http_reader.rs b/backend/src/util/http_reader.rs index 425517761..534624118 100644 --- a/backend/src/util/http_reader.rs +++ b/backend/src/util/http_reader.rs @@ -7,7 +7,7 @@ use std::pin::Pin; use std::task::{Context, Poll}; use color_eyre::eyre::eyre; -use futures::{FutureExt, Stream}; +use futures::Stream; use http::header::{ACCEPT_RANGES, CONTENT_LENGTH, RANGE}; use hyper::body::Bytes; use pin_project::pin_project; @@ -26,29 +26,29 @@ pub struct HttpReader { read_in_progress: ReadInProgress, } +type InProgress = Pin< + Box< + dyn Future< + Output = Result< + Pin< + Box< + dyn Stream> + + Send + + Sync + + 'static, + >, + >, + Error, + >, + > + Send + + Sync + + 'static, + >, +>; + enum ReadInProgress { None, - InProgress( - Pin< - Box< - dyn Future< - Output = Result< - Pin< - Box< - dyn Stream> - + Send - + Sync - + 'static, - >, - >, - Error, - >, - > + Send - + Sync - + 'static, - >, - >, - ), + InProgress(InProgress), Complete(Pin> + Send + Sync + 'static>>), } impl ReadInProgress { diff --git a/backend/src/version/v0_3_0_1.rs b/backend/src/version/v0_3_0_1.rs index 23cc9bc58..932678281 100644 --- a/backend/src/version/v0_3_0_1.rs +++ b/backend/src/version/v0_3_0_1.rs @@ -1,11 +1,6 @@ -use std::path::Path; - use emver::VersionRange; -use tokio::process::Command; use super::*; -use crate::disk::BOOT_RW_PATH; -use crate::util::Invoke; const V0_3_0_1: emver::Version = emver::Version::new(0, 3, 0, 1); diff --git a/backend/src/version/v0_3_2_1.rs b/backend/src/version/v0_3_2_1.rs index 36e15a43e..d82d7f973 100644 --- a/backend/src/version/v0_3_2_1.rs +++ b/backend/src/version/v0_3_2_1.rs @@ -17,7 +17,7 @@ impl VersionT for Version { fn compat(&self) -> &'static emver::VersionRange { &*V0_3_0_COMPAT } - async fn up(&self, db: &mut Db) -> Result<(), Error> { + async fn up(&self, _db: &mut Db) -> Result<(), Error> { Ok(()) } async fn down(&self, _db: &mut Db) -> Result<(), Error> { diff --git a/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js b/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js index aeca5a832..4e0c2cbff 100644 --- a/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js +++ b/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js @@ -733,8 +733,28 @@ const assert = (condition, message) => { throw new Error(message); } }; +const ackermann = (m, n) => { + if (m === 0) { + return n+1 + } + if (n === 0) { + return ackermann((m - 1), 1); + } + if (m !== 0 && n !== 0) { + return ackermann((m-1), ackermann(m, (n-1))) + } +} export const action = { + async slow(effects, _input) { + while(true) { + effects.error("A"); + // await ackermann(3,10); + await effects.sleep(100); + + } + }, + async fetch(effects, _input) { const example = await effects.fetch( "https://postman-echo.com/get?foo1=bar1&foo2=bar2" diff --git a/build/lib/scripts/firefox-trust-cert b/build/lib/scripts/firefox-trust-cert new file mode 100755 index 000000000..545b1722b --- /dev/null +++ b/build/lib/scripts/firefox-trust-cert @@ -0,0 +1,8 @@ +#!/bin/bash + +for mozilladir in $(find /home -name ".mozilla"); do + for certDB in $(find ${mozilladir} -name "cert9.db"); do + certDir=$(dirname ${certDB}); + certutil -A -n "Embassy Local Root CA" -t "TCu,Cuw,Tuw" -i /usr/local/share/ca-certificates/embassy-root-ca.crt -d ${certDir} + done +done \ No newline at end of file diff --git a/frontend/projects/ui/src/app/app.component.scss b/frontend/projects/ui/src/app/app.component.scss index 8f5b949ff..a40f38a8c 100644 --- a/frontend/projects/ui/src/app/app.component.scss +++ b/frontend/projects/ui/src/app/app.component.scss @@ -12,4 +12,4 @@ ion-split-pane { &_offline { filter: saturate(0.75) contrast(0.85); } -} +} \ No newline at end of file diff --git a/libs/Cargo.lock b/libs/Cargo.lock index 0810bc976..8f59d6f2b 100644 --- a/libs/Cargo.lock +++ b/libs/Cargo.lock @@ -47,6 +47,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" version = "1.0.58" @@ -73,6 +82,27 @@ dependencies = [ "syn", ] +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-trait" version = "0.1.56" @@ -414,6 +444,23 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +[[package]] +name = "embassy_container_init" +version = "0.1.0" +dependencies = [ + "async-stream", + "color-eyre", + "futures", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tracing", + "tracing-error 0.2.0", + "tracing-futures", + "tracing-subscriber 0.3.11", +] + [[package]] name = "emver" version = "0.1.6" @@ -899,10 +946,12 @@ dependencies = [ name = "js_engine" version = "0.1.0" dependencies = [ + "async-trait", "dashmap", "deno_ast", "deno_core", "dprint-swc-ext", + "embassy_container_init", "helpers", "models", "reqwest", @@ -1071,6 +1120,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.9" @@ -1123,11 +1181,13 @@ dependencies = [ name = "models" version = "0.1.0" dependencies = [ + "embassy_container_init", "emver", "patch-db", "rand", "serde", "thiserror", + "tokio", ] [[package]] @@ -1573,6 +1633,15 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.6.27" @@ -2421,6 +2490,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.3" @@ -2503,6 +2583,27 @@ dependencies = [ "tracing-subscriber 0.3.11", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.2.25" @@ -2520,9 +2621,16 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] diff --git a/libs/Cargo.toml b/libs/Cargo.toml index f36eaa470..650a2c5b1 100644 --- a/libs/Cargo.toml +++ b/libs/Cargo.toml @@ -4,5 +4,6 @@ members = [ "snapshot-creator", "models", "js_engine", - "helpers" + "helpers", + "embassy-container-init", ] diff --git a/libs/build-arm-v8-snapshot.sh b/libs/build-arm-v8-snapshot.sh index 896a0dccf..71c9ea901 100755 --- a/libs/build-arm-v8-snapshot.sh +++ b/libs/build-arm-v8-snapshot.sh @@ -19,7 +19,7 @@ docker run --rm $USE_TTY -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$( cd - echo "Creating Arm v8 Snapshot" -docker run --platform linux/arm64/v8 --mount type=bind,src=$(pwd),dst=/mnt arm64v8/ubuntu:20.04 /bin/sh -c "cd /mnt && /mnt/target/aarch64-unknown-linux-gnu/release/snapshot-creator" +docker run $USE_TTY --platform linux/arm64/v8 --mount type=bind,src=$(pwd),dst=/mnt arm64v8/ubuntu:20.04 /bin/sh -c "cd /mnt && /mnt/target/aarch64-unknown-linux-gnu/release/snapshot-creator" sudo chown -R $USER target sudo chown -R $USER ~/.cargo sudo chown $USER JS_SNAPSHOT.bin diff --git a/libs/embassy-container-init/Cargo.toml b/libs/embassy-container-init/Cargo.toml new file mode 100644 index 000000000..6c9d59227 --- /dev/null +++ b/libs/embassy-container-init/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "embassy_container_init" +version = "0.1.0" +edition = "2021" + +[features] +dev = [] +metal = [] +sound = [] +unstable = [] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +async-stream = "0.3.*" +color-eyre = "0.6.*" +futures = "0.3.*" +serde = { version = "1.*", features = ["derive", "rc"] } +serde_json = "1.*" +tokio = { version = "1.*", features = ["full"] } +tokio-stream = { version = "0.1.11" } +tracing = "0.1.*" +tracing-error = "0.2.*" +tracing-futures = "0.2.*" +tracing-subscriber = { version = "0.3.*", features = ["env-filter"] } + +[profile.test] +opt-level = 3 + +[profile.dev.package.backtrace] +opt-level = 3 diff --git a/libs/embassy-container-init/src/lib.rs b/libs/embassy-container-init/src/lib.rs new file mode 100644 index 000000000..e49c20778 --- /dev/null +++ b/libs/embassy-container-init/src/lib.rs @@ -0,0 +1,117 @@ +use serde::{Deserialize, Serialize}; +use tracing::instrument; + +/// The inputs that the executable is expecting +pub type InputJsonRpc = JsonRpc; +/// The outputs that the executable is expected to output +pub type OutputJsonRpc = JsonRpc; + +/// Based on the jsonrpc spec, but we are limiting the rpc to a subset +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[serde(untagged)] +pub enum RpcId { + UInt(u32), +} + +/// We use the JSON rpc as the format to share between the stdin and stdout for the executable. +/// Note: We are not allowing the id to not exist, used to ensure all pairs of messages are tracked +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +pub struct JsonRpc { + id: RpcId, + #[serde(flatten)] + pub version_rpc: VersionRpc, +} + +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +#[serde(tag = "jsonrpc", rename_all = "camelCase")] +pub enum VersionRpc { + #[serde(rename = "2.0")] + Two(T), +} + +impl JsonRpc +where + T: Serialize + for<'de> serde::Deserialize<'de> + std::fmt::Debug, +{ + /// Using this to simplify creating this nested struct. Used for creating input mostly for executable stdin + pub fn new(id: RpcId, body: T) -> Self { + JsonRpc { + id, + version_rpc: VersionRpc::Two(body), + } + } + /// Use this to get the data out of the probably destructed output + pub fn into_pair(self) -> (RpcId, T) { + let Self { id, version_rpc } = self; + let VersionRpc::Two(body) = version_rpc; + (id, body) + } + /// Used during the execution. + #[instrument] + pub fn maybe_serialize(&self) -> Option { + match serde_json::to_string(self) { + Ok(x) => Some(x), + Err(e) => { + tracing::warn!("Could not stringify and skipping"); + tracing::debug!("{:?}", e); + None + } + } + } + /// Used during the execution + #[instrument] + pub fn maybe_parse(s: &str) -> Option { + match serde_json::from_str::(s) { + Ok(a) => Some(a), + Err(e) => { + tracing::warn!("Could not parse and skipping: {}", s); + tracing::debug!("{:?}", e); + None + } + } + } +} + +/// Outputs embedded in the JSONRpc output of the executable. +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[serde(tag = "method", content = "params", rename_all = "camelCase")] +pub enum Output { + /// This is the line buffered output of the command + Line(String), + /// This is some kind of error with the program + Error(String), + /// Indication that the command is done + Done(Option), +} + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[serde(tag = "method", content = "params", rename_all = "camelCase")] +pub enum Input { + /// Create a new command, with the args + Command { command: String, args: Vec }, + /// Send the sigkill to the process + Kill(), + /// Send the sigterm to the process + Term(), +} + +#[test] +fn example_echo_line() { + let input = r#"{"id":0,"jsonrpc":"2.0","method":"command","params":{"command":"echo","args":["world I am here"]}}"#; + let new_input = JsonRpc::::maybe_parse(input); + assert!(new_input.is_some()); + assert_eq!(input, &serde_json::to_string(&new_input.unwrap()).unwrap()); +} + +#[test] +fn example_input_line() { + let output = JsonRpc::new(RpcId::UInt(0), Output::Line("world I am here".to_string())); + let output_str = output.maybe_serialize(); + assert!(output_str.is_some()); + let output_str = output_str.unwrap(); + assert_eq!( + &output_str, + r#"{"id":0,"jsonrpc":"2.0","method":"line","params":"world I am here"}"# + ); + assert_eq!(output, serde_json::from_str(&output_str).unwrap()); +} diff --git a/libs/embassy-container-init/src/main.rs b/libs/embassy-container-init/src/main.rs new file mode 100644 index 000000000..5f83b58fc --- /dev/null +++ b/libs/embassy-container-init/src/main.rs @@ -0,0 +1,296 @@ +use std::{collections::BTreeMap, process::Stdio, sync::Arc}; + +use async_stream::stream; +use futures::{pin_mut, Stream, StreamExt}; +use tokio::{ + io::AsyncBufReadExt, + process::Child, + select, + sync::{oneshot, Mutex}, +}; +use tokio::{io::BufReader, process::Command}; +use tracing::instrument; + +use embassy_container_init::{Input, InputJsonRpc, JsonRpc, Output, OutputJsonRpc, RpcId}; + +const MAX_COMMANDS: usize = 10; + +enum DoneProgramStatus { + Wait(Result), + Killed, +} +/// Created from the child and rpc, to prove that the cmd was the one who died +struct DoneProgram { + id: RpcId, + status: DoneProgramStatus, +} + +/// Used to attach the running command with the rpc +struct ChildAndRpc { + id: RpcId, + child: Child, +} + +impl ChildAndRpc { + fn new(id: RpcId, mut command: tokio::process::Command) -> ::std::io::Result { + Ok(Self { + id, + child: command.spawn()?, + }) + } + async fn wait(&mut self) -> DoneProgram { + let status = DoneProgramStatus::Wait(self.child.wait().await); + DoneProgram { + id: self.id.clone(), + status, + } + } + async fn kill(mut self) -> DoneProgram { + if let Err(err) = self.child.kill().await { + let id = &self.id; + tracing::error!("Error while trying to kill a process {id:?}"); + tracing::debug!("{err:?}"); + } + DoneProgram { + id: self.id.clone(), + status: DoneProgramStatus::Killed, + } + } +} + +/// Controlls the tracing + other io events +/// Can get the inputs from stdin +/// Can start a command from an intputrpc returning stream of outputs +/// Can output to stdout +#[derive(Debug, Clone)] +struct Io { + commands: Arc>>>, + ids: Arc>>, +} + +impl Io { + fn start() -> Self { + use tracing_error::ErrorLayer; + use tracing_subscriber::prelude::*; + use tracing_subscriber::{fmt, EnvFilter}; + + let filter_layer = EnvFilter::new("embassy_container_init=trace"); + let fmt_layer = fmt::layer().with_target(true); + + tracing_subscriber::registry() + .with(filter_layer) + .with(fmt_layer) + .with(ErrorLayer::default()) + .init(); + color_eyre::install().unwrap(); + Self { + commands: Default::default(), + ids: Default::default(), + } + } + + #[instrument] + fn command(&self, input: InputJsonRpc) -> impl Stream { + let io = self.clone(); + stream! { + let (id, command) = input.into_pair(); + match command { + Input::Command { + ref command, + ref args, + } => { + let mut cmd = Command::new(command); + cmd.args(args); + + cmd.stdout(Stdio::piped()); + cmd.stderr(Stdio::piped()); + let mut child_and_rpc = match ChildAndRpc::new(id.clone(), cmd) { + Err(_e) => return, + Ok(a) => a, + }; + + if let Some(child_id) = child_and_rpc.child.id() { + io.ids.lock().await.insert(id.clone(), child_id); + } + + let stdout = child_and_rpc.child + .stdout + .take() + .expect("child did not have a handle to stdout"); + let stderr = child_and_rpc.child + .stderr + .take() + .expect("child did not have a handle to stderr"); + + let mut buff_out = BufReader::new(stdout).lines(); + let mut buff_err = BufReader::new(stderr).lines(); + + let spawned = tokio::spawn({ + let id = id.clone(); + async move { + let end_command_receiver = io.create_end_command(id.clone()).await; + tokio::select!{ + waited = child_and_rpc + .wait() => { + io.clean_id(&waited).await; + match &waited.status { + DoneProgramStatus::Wait(Ok(st)) => return st.code(), + DoneProgramStatus::Wait(Err(err)) => tracing::debug!("Child {id:?} got error: {err:?}"), + DoneProgramStatus::Killed => tracing::debug!("Child {id:?} already killed?"), + } + + }, + _ = end_command_receiver => { + let status = child_and_rpc.kill().await; + io.clean_id(&status).await; + }, + } + None + } + + }); + while let Ok(Some(line)) = buff_out.next_line().await { + let output = Output::Line(line); + let output = JsonRpc::new(id.clone(), output); + tracing::trace!("OutputJsonRpc {{ id, output_rpc }} = {:?}", output); + yield output; + } + while let Ok(Some(line)) = buff_err.next_line().await { + yield JsonRpc::new(id.clone(), Output::Error(line)); + } + let code = spawned.await.ok().flatten(); + yield JsonRpc::new(id, Output::Done(code)); + }, + Input::Kill() => { + io.trigger_end_command(id).await; + } + Input::Term() => { + io.term_by_rpc(&id).await; + } + } + } + } + /// Used to get the string lines from the stdin + fn inputs(&self) -> impl Stream { + use std::io::BufRead; + let (sender, receiver) = tokio::sync::mpsc::channel(100); + tokio::task::spawn_blocking(move || { + let stdin = std::io::stdin(); + for line in stdin.lock().lines().flatten() { + tracing::trace!("Line = {}", line); + sender.blocking_send(line).unwrap(); + } + }); + tokio_stream::wrappers::ReceiverStream::new(receiver) + } + + ///Convert a stream of string to stdout + async fn output(&self, outputs: impl Stream) { + pin_mut!(outputs); + while let Some(output) = outputs.next().await { + tracing::info!("{}", output); + println!("{}", output); + } + } + + /// Helper for the command fn + /// Part of a pair for the signal map, that indicates that we should kill the command + async fn trigger_end_command(&self, id: RpcId) { + if let Some(command) = self.commands.lock().await.remove(&id) { + if command.send(()).is_err() { + tracing::trace!("Command {id:?} could not be ended, possible error or was done"); + } + } + } + + /// Helper for the command fn + /// Part of a pair for the signal map, that indicates that we should kill the command + async fn create_end_command(&self, id: RpcId) -> oneshot::Receiver<()> { + let (send, receiver) = oneshot::channel(); + if let Some(other_command) = self.commands.lock().await.insert(id.clone(), send) { + if other_command.send(()).is_err() { + tracing::trace!( + "Found other command {id:?} could not be ended, possible error or was done" + ); + } + } + receiver + } + + /// Used during cleaning up a procress + async fn clean_id( + &self, + done_program: &DoneProgram, + ) -> (Option, Option>) { + ( + self.ids.lock().await.remove(&done_program.id), + self.commands.lock().await.remove(&done_program.id), + ) + } + + /// Given the rpcid, will try and term the running command + async fn term_by_rpc(&self, rpc: &RpcId) { + let output = match self.remove_cmd_id(rpc).await { + Some(id) => { + let mut cmd = tokio::process::Command::new("kill"); + cmd.arg(format!("{id}")); + cmd.output().await + } + None => return, + }; + match output { + Ok(_) => (), + Err(err) => { + tracing::error!("Could not kill rpc {rpc:?}"); + tracing::debug!("{err}"); + } + } + } + + /// Used as a cleanup + async fn term_all(self) { + let ids: Vec<_> = self.ids.lock().await.keys().cloned().collect(); + for id in ids { + self.term_by_rpc(&id).await; + } + } + + async fn remove_cmd_id(&self, rpc: &RpcId) -> Option { + self.ids.lock().await.remove(rpc) + } +} +#[tokio::main] +async fn main() { + use futures::StreamExt; + use tokio::signal::unix::{signal, SignalKind}; + let mut sigint = signal(SignalKind::interrupt()).unwrap(); + let mut sigterm = signal(SignalKind::terminate()).unwrap(); + let mut sigquit = signal(SignalKind::quit()).unwrap(); + let mut sighangup = signal(SignalKind::hangup()).unwrap(); + let io = Io::start(); + let outputs = io + .inputs() + .filter_map(|x| async move { InputJsonRpc::maybe_parse(&x) }) + .flat_map_unordered(MAX_COMMANDS, |x| io.command(x).boxed()) + .filter_map(|x| async move { x.maybe_serialize() }); + + select! { + _ = io.output(outputs) => { + tracing::debug!("Done with inputs/outputs") + }, + _ = sigint.recv() => { + tracing::debug!("Sigint") + }, + _ = sigterm.recv() => { + tracing::debug!("Sig Term") + }, + _ = sigquit.recv() => { + tracing::debug!("Sigquit") + }, + _ = sighangup.recv() => { + tracing::debug!("Sighangup") + } + } + io.term_all().await; + ::std::process::exit(0); +} diff --git a/libs/helpers/src/lib.rs b/libs/helpers/src/lib.rs index 348d78c12..d70017592 100644 --- a/libs/helpers/src/lib.rs +++ b/libs/helpers/src/lib.rs @@ -1,9 +1,10 @@ use std::future::Future; use std::path::{Path, PathBuf}; +use std::pin::Pin; use std::time::Duration; use color_eyre::eyre::{eyre, Context, Error}; -use futures::future::BoxFuture; +use futures::future::{pending, BoxFuture}; use futures::FutureExt; use tokio::fs::File; use tokio::sync::oneshot; @@ -208,3 +209,80 @@ impl TimedResource { self.ready.is_closed() } } + +type SingThreadTask = futures::future::Select< + futures::future::Then< + oneshot::Receiver, + futures::future::Either, futures::future::Pending>, + fn( + Result, + ) + -> futures::future::Either, futures::future::Pending>, + >, + futures::future::Then< + JoinHandle<()>, + futures::future::Pending, + fn(Result<(), JoinError>) -> futures::future::Pending, + >, +>; + +#[pin_project::pin_project(PinnedDrop)] +pub struct SingleThreadJoinHandle { + abort: Option>, + #[pin] + task: SingThreadTask, +} +impl SingleThreadJoinHandle { + pub fn new>(fut: impl FnOnce() -> Fut + Send + 'static) -> Self { + let (abort, abort_recv) = oneshot::channel(); + let (return_val_send, return_val) = oneshot::channel(); + fn unwrap_recv_or_pending( + res: Result, + ) -> futures::future::Either, futures::future::Pending> + { + match res { + Ok(a) => futures::future::Either::Left(futures::future::ready(a)), + _ => futures::future::Either::Right(pending()), + } + } + fn make_pending(_: Result<(), JoinError>) -> futures::future::Pending { + pending() + } + Self { + abort: Some(abort), + task: futures::future::select( + return_val.then(unwrap_recv_or_pending), + tokio::task::spawn_blocking(move || { + tokio::runtime::Handle::current().block_on(async move { + tokio::select! { + _ = abort_recv.fuse() => (), + res = fut().fuse() => {let _error = return_val_send.send(res);}, + } + }) + }) + .then(make_pending), + ), + } + } +} + +impl Future for SingleThreadJoinHandle { + type Output = T; + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.task.poll(cx).map(|t| t.factor_first().0) + } +} + +#[pin_project::pinned_drop] +impl PinnedDrop for SingleThreadJoinHandle { + fn drop(self: Pin<&mut Self>) { + let this = self.project(); + if let Some(abort) = this.abort.take() { + let _error = abort.send(()); + } + } +} diff --git a/libs/js_engine/Cargo.toml b/libs/js_engine/Cargo.toml index b62a79761..b7c8fbb2d 100644 --- a/libs/js_engine/Cargo.toml +++ b/libs/js_engine/Cargo.toml @@ -6,10 +6,12 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-trait = "0.1.56" dashmap = "5.3.4" deno_core = "=0.136.0" deno_ast = { version = "=0.15.0", features = ["transpiling"] } dprint-swc-ext = "=0.1.1" +embassy_container_init = { path = "../embassy-container-init" } reqwest = { version = "0.11.11" } swc_atoms = "=0.2.11" swc_common = "=0.18.7" diff --git a/libs/js_engine/src/artifacts/loadModule.js b/libs/js_engine/src/artifacts/loadModule.js index 3f4432231..5db8a1a1c 100644 --- a/libs/js_engine/src/artifacts/loadModule.js +++ b/libs/js_engine/src/artifacts/loadModule.js @@ -37,10 +37,37 @@ const writeFile = ( const readFile = ( { volumeId = requireParam("volumeId"), path = requireParam("path") } = requireParam("options"), ) => Deno.core.opAsync("read_file", volumeId, path); + + + +const runDaemon = ( + { command = requireParam("command"), args = [] } = requireParam("options"), +) => { + let id = Deno.core.opAsync("start_command", command, args); + let waitPromise = null; + return { + async wait() { + waitPromise = waitPromise || Deno.core.opAsync("wait_command", await id) + return waitPromise + }, + async term() { + return Deno.core.opAsync("term_command", await id) + } + } +}; +const runCommand = async ( + { command = requireParam("command"), args = [], timeoutMillis = 30000 } = requireParam("options"), +) => { + let id = Deno.core.opAsync("start_command", command, args, timeoutMillis); + return Deno.core.opAsync("wait_command", await id) +}; +const sleep = (timeMs = requireParam("timeMs"), +) => Deno.core.opAsync("sleep", timeMs); + const rename = ( { srcVolume = requireParam("srcVolume"), - dstVolume = requireParam("dstVolume"), + dstVolume = requirePapram("dstVolume"), srcPath = requireParam("srcPath"), dstPath = requireParam("dstPath"), } = requireParam("options"), @@ -122,6 +149,9 @@ const effects = { removeDir, metadata, rename, + runCommand, + sleep, + runDaemon }; const runFunction = jsonPointerValue(mainModule, currentFunction); diff --git a/libs/js_engine/src/lib.rs b/libs/js_engine/src/lib.rs index 887e21fed..a1c104094 100644 --- a/libs/js_engine/src/lib.rs +++ b/libs/js_engine/src/lib.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; +use std::future::Future; use std::path::{Path, PathBuf}; use std::pin::Pin; use std::sync::Arc; @@ -9,11 +11,12 @@ use deno_core::{ resolve_import, Extension, JsRuntime, ModuleLoader, ModuleSource, ModuleSourceFuture, ModuleSpecifier, ModuleType, OpDecl, RuntimeOptions, Snapshot, }; -use helpers::{script_dir, NonDetachingJoinHandle}; -use models::{PackageId, ProcedureName, Version, VolumeId}; +use helpers::{script_dir, SingleThreadJoinHandle}; +use models::{ExecCommand, PackageId, ProcedureName, TermCommand, Version, VolumeId}; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::io::AsyncReadExt; +use tokio::sync::Mutex; pub trait PathForVolumeId: Send + Sync { fn path_for( @@ -80,6 +83,8 @@ const SNAPSHOT_BYTES: &[u8] = include_bytes!("./artifacts/JS_SNAPSHOT.bin"); #[cfg(target_arch = "aarch64")] const SNAPSHOT_BYTES: &[u8] = include_bytes!("./artifacts/ARM_JS_SNAPSHOT.bin"); +type WaitFns = Arc>>>>>; + #[derive(Clone)] struct JsContext { sandboxed: bool, @@ -90,8 +95,17 @@ struct JsContext { volumes: Arc, input: Value, variable_args: Vec, + command_inserter: ExecCommand, + term_command: TermCommand, + wait_fns: WaitFns, +} +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "kebab-case")] +enum ResultType { + Error(String), + ErrorCode(i32, String), + Result(serde_json::Value), } - #[derive(Clone, Default)] struct AnswerState(std::sync::Arc>); @@ -162,6 +176,7 @@ impl ModuleLoader for ModsLoader { }) } } + pub struct JsExecutionEnvironment { sandboxed: bool, base_directory: PathBuf, @@ -169,6 +184,8 @@ pub struct JsExecutionEnvironment { package_id: PackageId, version: Version, volumes: Arc, + command_inserter: ExecCommand, + term_command: TermCommand, } impl JsExecutionEnvironment { @@ -177,7 +194,9 @@ impl JsExecutionEnvironment { package_id: &PackageId, version: &Version, volumes: Box, - ) -> Result { + command_inserter: ExecCommand, + term_command: TermCommand, + ) -> Result { let data_dir = data_directory.as_ref(); let base_directory = data_dir; let js_code = JsCode({ @@ -203,13 +222,15 @@ impl JsExecutionEnvironment { }; buffer }); - Ok(Self { + Ok(JsExecutionEnvironment { base_directory: base_directory.to_owned(), module_loader: ModsLoader { code: js_code }, package_id: package_id.clone(), version: version.clone(), volumes: volumes.into(), sandboxed: false, + command_inserter, + term_command, }) } pub fn read_only_effects(mut self) -> Self { @@ -234,12 +255,9 @@ impl JsExecutionEnvironment { )); } }; - let safer_handle: NonDetachingJoinHandle<_> = - tokio::task::spawn_blocking(move || self.execute(procedure_name, input, variable_args)) - .into(); - let output = safer_handle - .await - .map_err(|err| (JsError::Tokio, format!("Tokio gave us the error: {}", err)))??; + let safer_handle = + SingleThreadJoinHandle::new(move || self.execute(procedure_name, input, variable_args)); + let output = safer_handle.await?; match serde_json::from_value(output.clone()) { Ok(x) => Ok(x), Err(err) => { @@ -275,11 +293,15 @@ impl JsExecutionEnvironment { fns::get_variable_args::decl(), fns::set_value::decl(), fns::is_sandboxed::decl(), + fns::start_command::decl(), + fns::wait_command::decl(), + fns::sleep::decl(), + fns::term_command::decl(), ] } - fn execute( - &self, + async fn execute( + self, procedure_name: ProcedureName, input: Value, variable_args: Vec, @@ -304,6 +326,9 @@ impl JsExecutionEnvironment { sandboxed: self.sandboxed, input, variable_args, + command_inserter: self.command_inserter.clone(), + term_command: self.term_command.clone(), + wait_fns: Default::default(), }; let ext = Extension::builder() .ops(Self::declarations()) @@ -321,25 +346,25 @@ impl JsExecutionEnvironment { startup_snapshot: Some(Snapshot::Static(SNAPSHOT_BYTES)), ..Default::default() }; - let mut runtime = JsRuntime::new(runtime_options); + let runtime = Arc::new(Mutex::new(JsRuntime::new(runtime_options))); let future = async move { let mod_id = runtime + .lock() + .await .load_main_module(&"file:///loadModule.js".parse().unwrap(), None) .await?; - let evaluated = runtime.mod_evaluate(mod_id); - let res = runtime.run_event_loop(false).await; + let evaluated = runtime.lock().await.mod_evaluate(mod_id); + let res = runtime.lock().await.run_event_loop(false).await; res?; evaluated.await??; Ok::<_, AnyError>(()) }; - tokio::runtime::Handle::current() - .block_on(future) - .map_err(|e| { - tracing::debug!("{:?}", e); - (JsError::Javascript, format!("{}", e)) - })?; + future.await.map_err(|e| { + tracing::debug!("{:?}", e); + (JsError::Javascript, format!("{}", e)) + })?; let answer = answer_state.0.lock().clone(); Ok(answer) @@ -348,23 +373,24 @@ impl JsExecutionEnvironment { /// Note: Make sure that we have the assumption that all these methods are callable at any time, and all call restrictions should be in rust mod fns { - use std::cell::RefCell; use std::collections::BTreeMap; use std::convert::TryFrom; use std::os::unix::fs::MetadataExt; use std::path::{Path, PathBuf}; use std::rc::Rc; + use std::{cell::RefCell, time::Duration}; use deno_core::anyhow::{anyhow, bail}; use deno_core::error::AnyError; use deno_core::*; + use embassy_container_init::RpcId; use helpers::{to_tmp_path, AtomicFile}; - use models::VolumeId; + use models::{TermCommand, VolumeId}; use serde_json::Value; use tokio::io::AsyncWriteExt; use super::{AnswerState, JsContext}; - use crate::{system_time_as_unix_ms, MetadataJs}; + use crate::{system_time_as_unix_ms, MetadataJs, ResultType}; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)] struct FetchOptions { @@ -386,10 +412,13 @@ mod fns { url: url::Url, options: Option, ) -> Result { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); + let sandboxed = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + ctx.sandboxed + }; - if ctx.sandboxed { + if sandboxed { bail!("Will not run fetch in sandboxed mode"); } @@ -432,7 +461,7 @@ mod fns { body: response.text().await.ok(), }; - return Ok(fetch_response); + Ok(fetch_response) } #[op] @@ -441,12 +470,13 @@ mod fns { volume_id: VolumeId, path_in: PathBuf, ) -> Result { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) - .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; + let volume_path = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + ctx.volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) + .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))? + }; //get_path_for in volume.rs let new_file = volume_path.join(path_in); if !is_subset(&volume_path, &new_file).await? { @@ -465,12 +495,13 @@ mod fns { volume_id: VolumeId, path_in: PathBuf, ) -> Result { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) - .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; + let volume_path = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + ctx.volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) + .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))? + }; //get_path_for in volume.rs let new_file = volume_path.join(path_in); if !is_subset(&volume_path, &new_file).await? { @@ -517,13 +548,16 @@ mod fns { path_in: PathBuf, write: String, ) -> Result<(), AnyError> { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) - .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; - if ctx.volumes.readonly(&volume_id) { + let (volumes, volume_path) = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + let volume_path = ctx + .volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) + .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; + (ctx.volumes.clone(), volume_path) + }; + if volumes.readonly(&volume_id) { bail!("Volume {} is readonly", volume_id); } @@ -566,17 +600,20 @@ mod fns { dst_volume: VolumeId, dst_path: PathBuf, ) -> Result<(), AnyError> { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &src_volume) - .ok_or_else(|| anyhow!("There is no {} in volumes", src_volume))?; - let volume_path_out = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &dst_volume) - .ok_or_else(|| anyhow!("There is no {} in volumes", dst_volume))?; - if ctx.volumes.readonly(&dst_volume) { + let (volumes, volume_path, volume_path_out) = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + let volume_path = ctx + .volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &src_volume) + .ok_or_else(|| anyhow!("There is no {} in volumes", src_volume))?; + let volume_path_out = ctx + .volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &dst_volume) + .ok_or_else(|| anyhow!("There is no {} in volumes", dst_volume))?; + (ctx.volumes.clone(), volume_path, volume_path_out) + }; + if volumes.readonly(&dst_volume) { bail!("Volume {} is readonly", dst_volume); } @@ -614,13 +651,16 @@ mod fns { volume_id: VolumeId, path_in: PathBuf, ) -> Result<(), AnyError> { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) - .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; - if ctx.volumes.readonly(&volume_id) { + let (volumes, volume_path) = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + let volume_path = ctx + .volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) + .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; + (ctx.volumes.clone(), volume_path) + }; + if volumes.readonly(&volume_id) { bail!("Volume {} is readonly", volume_id); } let new_file = volume_path.join(path_in); @@ -641,13 +681,16 @@ mod fns { volume_id: VolumeId, path_in: PathBuf, ) -> Result<(), AnyError> { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) - .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; - if ctx.volumes.readonly(&volume_id) { + let (volumes, volume_path) = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + let volume_path = ctx + .volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) + .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; + (ctx.volumes.clone(), volume_path) + }; + if volumes.readonly(&volume_id) { bail!("Volume {} is readonly", volume_id); } let new_file = volume_path.join(path_in); @@ -668,13 +711,16 @@ mod fns { volume_id: VolumeId, path_in: PathBuf, ) -> Result<(), AnyError> { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes - .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) - .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; - if ctx.volumes.readonly(&volume_id) { + let (volumes, volume_path) = { + let state = state.borrow(); + let ctx: &JsContext = state.borrow(); + let volume_path = ctx + .volumes + .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) + .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; + (ctx.volumes.clone(), volume_path) + }; + if volumes.readonly(&volume_id) { bail!("Volume {} is readonly", volume_id); } let new_file = volume_path.join(path_in); @@ -777,6 +823,102 @@ mod fns { Ok(ctx.sandboxed) } + #[op] + async fn term_command(state: Rc>, id: u32) -> Result<(), AnyError> { + let term_command_impl: TermCommand = { + let state = state.borrow(); + let ctx = state.borrow::(); + ctx.term_command.clone() + }; + if let Err(err) = term_command_impl(embassy_container_init::RpcId::UInt(id)).await { + bail!("{}", err); + } + Ok(()) + } + + #[op] + async fn start_command( + state: Rc>, + command: String, + args: Vec, + timeout: Option, + ) -> Result { + use embassy_container_init::Output; + let (command_inserter, wait_fns) = { + let state = state.borrow(); + let ctx = state.borrow::(); + (ctx.command_inserter.clone(), ctx.wait_fns.clone()) + }; + + let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel::(); + let id = match command_inserter( + command, + args.into_iter().collect(), + sender, + timeout.map(std::time::Duration::from_millis), + ) + .await + { + Err(err) => bail!(err), + Ok(RpcId::UInt(a)) => a, + }; + + let wait = async move { + let mut answer = String::new(); + let mut command_error = String::new(); + let mut status: Option = None; + while let Some(output) = receiver.recv().await { + match output { + Output::Line(value) => { + answer.push_str(&value); + answer.push('\n'); + } + Output::Error(error) => { + command_error.push_str(&error); + command_error.push('\n'); + } + Output::Done(error_code) => { + status = error_code; + break; + } + } + } + if !command_error.is_empty() { + if let Some(status) = status { + return ResultType::ErrorCode(status, command_error); + } + + return ResultType::Error(command_error); + } + + ResultType::Result(serde_json::Value::String(answer)) + }; + wait_fns.lock().await.insert(id, Box::pin(wait)); + Ok(id) + } + + #[op] + async fn wait_command(state: Rc>, id: u32) -> Result { + let wait_fns = { + let state = state.borrow(); + let ctx = state.borrow::(); + ctx.wait_fns.clone() + }; + + let found_future = match wait_fns.lock().await.remove(&id) { + Some(a) => a, + None => bail!("No future for id {id}, could have been removed already"), + }; + + Ok(found_future.await) + } + #[op] + async fn sleep(time_ms: u64) -> Result<(), AnyError> { + tokio::time::sleep(Duration::from_millis(time_ms)).await; + + Ok(()) + } + /// We need to make sure that during the file accessing, we don't reach beyond our scope of control async fn is_subset( parent: impl AsRef, diff --git a/libs/models/Cargo.toml b/libs/models/Cargo.toml index 60d46db16..552d05f9d 100644 --- a/libs/models/Cargo.toml +++ b/libs/models/Cargo.toml @@ -6,10 +6,12 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +embassy_container_init = { path = "../embassy-container-init" } +emver = { version = "0.1", features = ["serde"] } patch-db = { version = "*", path = "../../patch-db/patch-db", features = [ "trace", ] } serde = { version = "1.0", features = ["derive", "rc"] } -thiserror = "1.0" -emver = { version = "0.1", features = ["serde"] } rand = "0.8" +tokio = { version = "1", features = ["full"] } +thiserror = "1.0" \ No newline at end of file diff --git a/libs/models/src/lib.rs b/libs/models/src/lib.rs index 7d088ec62..0de5d6abb 100644 --- a/libs/models/src/lib.rs +++ b/libs/models/src/lib.rs @@ -6,6 +6,7 @@ mod interface_id; mod invalid_id; mod package_id; mod procedure_name; +mod type_aliases; mod version; mod volume_id; @@ -17,5 +18,6 @@ pub use interface_id::*; pub use invalid_id::*; pub use package_id::*; pub use procedure_name::*; +pub use type_aliases::*; pub use version::*; pub use volume_id::*; diff --git a/libs/models/src/procedure_name.rs b/libs/models/src/procedure_name.rs index ebe3b6ba1..1e1d242b1 100644 --- a/libs/models/src/procedure_name.rs +++ b/libs/models/src/procedure_name.rs @@ -35,7 +35,7 @@ impl ProcedureName { } pub fn js_function_name(&self) -> Option { match self { - ProcedureName::Main => None, + ProcedureName::Main => Some("/main".to_string()), ProcedureName::LongRunning => None, ProcedureName::CreateBackup => Some("/createBackup".to_string()), ProcedureName::RestoreBackup => Some("/restoreBackup".to_string()), diff --git a/libs/models/src/type_aliases.rs b/libs/models/src/type_aliases.rs new file mode 100644 index 000000000..0fdb79093 --- /dev/null +++ b/libs/models/src/type_aliases.rs @@ -0,0 +1,25 @@ +use std::{future::Future, pin::Pin, sync::Arc, time::Duration}; + +use embassy_container_init::RpcId; +use tokio::sync::mpsc::UnboundedSender; + +/// Used by the js-executor, it is the ability to just create a command in an already running exec +pub type ExecCommand = Arc< + dyn Fn( + String, + Vec, + UnboundedSender, + Option, + ) -> Pin> + 'static>> + + Send + + Sync + + 'static, +>; + +/// Used by the js-executor, it is the ability to just create a command in an already running exec +pub type TermCommand = Arc< + dyn Fn(RpcId) -> Pin> + 'static>> + + Send + + Sync + + 'static, +>; diff --git a/system-images/compat/Cargo.lock b/system-images/compat/Cargo.lock index e9a8ffccd..581e7b9e2 100644 --- a/system-images/compat/Cargo.lock +++ b/system-images/compat/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ "cipher", "cpufeatures", "ctr", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -36,16 +36,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.57" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" dependencies = [ "backtrace", ] @@ -120,20 +120,20 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "async-trait" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -164,9 +164,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.65" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", @@ -191,9 +191,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "base64ct" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdca834647821e0b13d9539a8634eb62d3501b6b6c2cec1722786ee6671b851" +checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474" [[package]] name = "basic-cookies" @@ -218,9 +218,9 @@ dependencies = [ [[package]] name = "bit-set" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] @@ -275,44 +275,23 @@ dependencies = [ "constant_time_eq", ] -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding 0.1.5", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", - "generic-array 0.14.5", + "block-padding", + "generic-array", ] [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -373,15 +352,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byteorder" @@ -391,9 +364,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cc" @@ -456,7 +429,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -476,9 +449,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.10" +version = "3.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69c5a7f9997be616e47f0577ee38c91decb33392c5be4866494f34cdf329a9aa" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" dependencies = [ "atty", "bitflags", @@ -486,7 +459,7 @@ dependencies = [ "indexmap", "strsim 0.10.0", "termcolor", - "textwrap 0.15.0", + "textwrap 0.15.1", ] [[package]] @@ -537,7 +510,7 @@ dependencies = [ "emver", "failure", "indexmap", - "itertools 0.10.3", + "itertools 0.10.5", "lazy_static", "linear-map", "log", @@ -549,7 +522,7 @@ dependencies = [ "rust-argon2", "serde", "serde_json", - "serde_yaml 0.8.25", + "serde_yaml 0.8.26", ] [[package]] @@ -572,12 +545,12 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cookie" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" dependencies = [ "percent-encoding", - "time 0.3.11", + "time 0.3.14", "version_check", ] @@ -588,12 +561,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" dependencies = [ "cookie", - "idna", + "idna 0.2.3", "log", "publicsuffix", "serde", "serde_json", - "time 0.3.11", + "time 0.3.14", "url", ] @@ -615,9 +588,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -648,9 +621,9 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" dependencies = [ "cfg-if", "crossbeam-utils", @@ -658,12 +631,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] @@ -674,11 +647,11 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array", "typenum", ] @@ -688,7 +661,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.5", + "generic-array", "subtle", ] @@ -770,10 +743,10 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.44", + "quote 1.0.21", "strsim 0.10.0", - "syn 1.0.98", + "syn 1.0.100", ] [[package]] @@ -784,10 +757,10 @@ checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.44", + "quote 1.0.21", "strsim 0.10.0", - "syn 1.0.98", + "syn 1.0.100", ] [[package]] @@ -797,8 +770,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", - "quote 1.0.18", - "syn 1.0.98", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -808,19 +781,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" dependencies = [ "darling_core 0.14.1", - "quote 1.0.18", - "syn 1.0.98", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "dashmap" -version = "5.3.3" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391b56fbd302e585b7a9494fb70e40949567b1cf9003a8e4a6041a1687c26573" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if", - "hashbrown 0.12.1", + "hashbrown", "lock_api", + "once_cell", + "parking_lot_core 0.9.3", ] [[package]] @@ -847,26 +822,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.44", + "quote 1.0.21", "rustc_version", - "syn 1.0.98", + "syn 1.0.100", ] [[package]] name = "diff" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" @@ -874,16 +840,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] name = "digest" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ - "block-buffer 0.10.2", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -936,10 +902,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82" [[package]] -name = "dotenv" -version = "0.15.0" +name = "dotenvy" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +checksum = "ed9155c8f4dc55c7470ae9da3f63c6785245093b3f6aeb0f5bf2e968efbba314" +dependencies = [ + "dirs", +] [[package]] name = "ed25519" @@ -969,9 +938,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" dependencies = [ "serde", ] @@ -990,15 +959,16 @@ dependencies = [ "bollard", "chrono", "ciborium", - "clap 3.2.10", + "clap 3.2.22", "color-eyre", "cookie_store", "current_platform", - "digest 0.10.3", + "digest 0.10.5", "digest 0.9.0", "divrem", "ed25519", "ed25519-dalek", + "embassy_container_init", "emver", "fd-lock-rs", "futures", @@ -1012,7 +982,7 @@ dependencies = [ "imbl 2.0.0", "indexmap", "isocountry", - "itertools 0.10.3", + "itertools 0.10.5", "josekit", "jsonpath_lib", "lazy_static", @@ -1045,7 +1015,7 @@ dependencies = [ "serde_json", "serde_with 2.0.1", "serde_yaml 0.9.13", - "sha2 0.10.2", + "sha2 0.10.6", "sha2 0.9.9", "simple-logging", "sqlx", @@ -1062,13 +1032,30 @@ dependencies = [ "tracing", "tracing-error 0.2.0", "tracing-futures", - "tracing-subscriber 0.3.14", + "tracing-subscriber 0.3.15", "trust-dns-server", "typed-builder", "url", "uuid", ] +[[package]] +name = "embassy_container_init" +version = "0.1.0" +dependencies = [ + "async-stream", + "color-eyre", + "futures", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tracing", + "tracing-error 0.2.0", + "tracing-futures", + "tracing-subscriber 0.3.15", +] + [[package]] name = "emver" version = "0.1.6" @@ -1118,16 +1105,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ "heck 0.4.0", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "atty", "humantime", @@ -1138,9 +1125,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "eyre" @@ -1168,23 +1155,17 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", "synstructure", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -1200,21 +1181,21 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" +checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.13", - "winapi", + "redox_syscall 0.2.16", + "windows-sys", ] [[package]] name = "fixedbitset" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" @@ -1249,11 +1230,10 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] @@ -1274,9 +1254,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -1289,9 +1269,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -1299,15 +1279,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -1327,38 +1307,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -1374,18 +1354,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.4" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -1404,20 +1375,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "git-version" @@ -1436,16 +1407,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "h2" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ "bytes", "fnv", @@ -1468,26 +1439,20 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "hashbrown" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] [[package]] name = "hashlink" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452c155cb93fecdfb02a73dd57b5d8e442c2063bd7aac72f1bc5e4263a43086" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" dependencies = [ - "hashbrown 0.12.1", + "hashbrown", ] [[package]] @@ -1559,7 +1524,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -1570,7 +1535,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.2", + "itoa 1.0.3", ] [[package]] @@ -1586,9 +1551,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -1617,7 +1582,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.2", + "itoa 1.0.3", "pin-project-lite", "socket2", "tokio", @@ -1651,7 +1616,7 @@ dependencies = [ "futures", "hyper", "log", - "sha-1 0.10.0", + "sha-1", "tokio", "tokio-tungstenite", ] @@ -1671,14 +1636,13 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.48" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" dependencies = [ "android_system_properties", "core-foundation-sys", "js-sys", - "once_cell", "wasm-bindgen", "winapi", ] @@ -1700,6 +1664,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "imbl" version = "1.0.1" @@ -1707,7 +1681,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "543682c9082b25e63d03b5acbd65ad111fd49dd93e70843e5175db4ff81d606b" dependencies = [ "bitmaps 2.1.0", - "rand_core 0.6.3", + "rand_core 0.6.4", "rand_xoshiro", "sized-chunks", "typenum", @@ -1722,7 +1696,7 @@ checksum = "c2806b69cd9f4664844027b64465eacb444c67c1db9c778e341adff0c25cdb0d" dependencies = [ "bitmaps 3.2.0", "imbl-sized-chunks", - "rand_core 0.6.3", + "rand_core 0.6.4", "rand_xoshiro", "version_check", ] @@ -1749,7 +1723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", - "hashbrown 0.12.1", + "hashbrown", "serde", ] @@ -1798,9 +1772,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -1813,9 +1787,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "josekit" @@ -1832,14 +1806,14 @@ dependencies = [ "serde", "serde_json", "thiserror", - "time 0.3.11", + "time 0.3.14", ] [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1891,7 +1865,7 @@ dependencies = [ "bit-set", "diff", "ena", - "itertools 0.10.3", + "itertools 0.10.5", "lalrpop-util", "petgraph", "pico-args", @@ -1900,7 +1874,7 @@ dependencies = [ "string_cache", "term", "tiny-keccak", - "unicode-xid 0.2.3", + "unicode-xid 0.2.4", ] [[package]] @@ -1949,15 +1923,15 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -1972,12 +1946,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matchers" version = "0.1.0" @@ -2001,16 +1969,16 @@ checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] name = "md-5" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b48670c893079d3c2ed79114e3644b7004df1c361a4e0ad52e2e6940d07c3d" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -2042,9 +2010,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -2065,11 +2033,13 @@ dependencies = [ name = "models" version = "0.1.0" dependencies = [ + "embassy_container_init", "emver", "patch-db", "rand 0.8.5", "serde", "thiserror", + "tokio", ] [[package]] @@ -2194,9 +2164,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" +checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ "num-traits", ] @@ -2224,9 +2194,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-bigint", @@ -2269,9 +2239,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -2285,9 +2255,9 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "memchr", ] @@ -2298,12 +2268,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "opaque-debug" version = "0.3.0" @@ -2344,9 +2308,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -2357,9 +2321,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.20.0+1.1.1o" +version = "111.22.0+1.1.1q" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92892c4f87d56e376e469ace79f1128fdaded07646ddf73aa0be4706ff712dec" +checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853" dependencies = [ "cc", ] @@ -2380,15 +2344,15 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" [[package]] name = "owo-colors" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking_lot" @@ -2403,9 +2367,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core 0.9.3", @@ -2420,7 +2384,7 @@ dependencies = [ "cfg-if", "instant", "libc", - "redox_syscall 0.2.13", + "redox_syscall 0.2.16", "smallvec", "winapi", ] @@ -2433,27 +2397,27 @@ checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.13", + "redox_syscall 0.2.16", "smallvec", "windows-sys", ] [[package]] name = "password-hash" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e029e94abc8fb0065241c308f1ac6bc8d20f450e8f7c5f0b25cd9b8d526ba294" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core 0.6.3", + "rand_core 0.6.4", "subtle", ] [[package]] name = "paste" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "patch-db" @@ -2482,8 +2446,8 @@ name = "patch-db-macro" version = "0.1.0" dependencies = [ "patch-db-macro-internals", - "proc-macro2 1.0.39", - "syn 1.0.98", + "proc-macro2 1.0.44", + "syn 1.0.100", ] [[package]] @@ -2491,9 +2455,9 @@ name = "patch-db-macro-internals" version = "0.1.0" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -2502,10 +2466,10 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", "hmac 0.12.1", "password-hash", - "sha2 0.10.2", + "sha2 0.10.6", ] [[package]] @@ -2519,24 +2483,25 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.1.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1" dependencies = [ "pest", "pest_generator", @@ -2544,33 +2509,33 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1 0.8.2", + "sha1", ] [[package]] name = "petgraph" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", "indexmap", @@ -2593,22 +2558,22 @@ checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" [[package]] name = "pin-project" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -2667,10 +2632,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ + "once_cell", "thiserror", "toml", ] @@ -2692,9 +2658,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" dependencies = [ "unicode-ident", ] @@ -2732,19 +2698,17 @@ dependencies = [ [[package]] name = "psl-types" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8eda7c62d9ecaafdf8b62374c006de0adf61666ae96a96ba74a37134aa4e470" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "publicsuffix" -version = "2.1.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292972edad6bbecc137ab84c5e36421a4a6c979ea31d3cc73540dd04315b33e1" +checksum = "aeeedb0b429dc462f30ad27ef3de97058b060016f47790c066757be38ef792b4" dependencies = [ - "byteorder", - "hashbrown 0.11.2", - "idna", + "idna 0.2.3", "psl-types", ] @@ -2771,11 +2735,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2 1.0.39", + "proc-macro2 1.0.44", ] [[package]] @@ -2815,7 +2779,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -2835,7 +2799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -2849,11 +2813,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", ] [[package]] @@ -2871,7 +2835,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -2880,7 +2844,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -2891,9 +2855,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -2904,8 +2868,8 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.6", - "redox_syscall 0.2.13", + "getrandom 0.2.7", + "redox_syscall 0.2.16", "thiserror", ] @@ -2946,9 +2910,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ "base64", "bytes", @@ -2964,10 +2928,10 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", "proc-macro-hack", @@ -3030,7 +2994,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5bfeb75c188f3af65774d5fe92f97dac2cede5e313c643c7a1b82a8e53b0e6" dependencies = [ - "clap 3.2.10", + "clap 3.2.22", "futures", "hyper", "lazy_static", @@ -3052,9 +3016,9 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecb48bdaace41cfbb514b3e541ae0fc1ac0fb8283498215ad8a3d22ca2ea5ae5" dependencies = [ - "proc-macro2 1.0.39", + "proc-macro2 1.0.44", "rpc-toolkit-macro-internals", - "syn 1.0.98", + "syn 1.0.100", ] [[package]] @@ -3063,9 +3027,9 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2a9e2bae02a2beecad48d87255e51cab941d0c89a2bcee05a03a77803a0a282" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -3109,18 +3073,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" dependencies = [ "base64", ] [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "rusty-fork" @@ -3136,9 +3100,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "schannel" @@ -3168,9 +3132,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -3191,24 +3155,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.9" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "serde" -version = "1.0.139" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] @@ -3233,32 +3197,32 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.139" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "indexmap", - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", ] [[package]] name = "serde_test" -version = "1.0.137" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe196827aea34242c314d2f0dd49ed00a129225e80dda71b0dbf65d54d25628d" +checksum = "9c17d2112159132660b4c5399e274f676fb75a2f8d70b7468f18f045b71138ed" dependencies = [ "serde", ] @@ -3270,7 +3234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", ] @@ -3298,7 +3262,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros 2.0.1", - "time 0.3.11", + "time 0.3.14", ] [[package]] @@ -3308,9 +3272,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ "darling 0.13.4", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -3320,16 +3284,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ccadfacf6cf10faad22bbadf55986bdd0856edfb5d9210aa1dcf1f516e84e93" dependencies = [ "darling 0.14.1", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "serde_yaml" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec0091e1f5aa338283ce049bd9dfefd55e1f168ac233e85c1ffe0038fb48cbe" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", @@ -3344,24 +3308,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1" dependencies = [ "indexmap", - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", "unsafe-libyaml", ] -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha-1" version = "0.10.0" @@ -3370,7 +3322,18 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest 0.10.5", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.5", ] [[package]] @@ -3383,18 +3346,18 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -3406,7 +3369,7 @@ dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", "keccak", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -3429,9 +3392,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "deb766570a2825fa972bceff0d195727876a9cdf2460ab2e52d455dc2de47fd9" [[package]] name = "simple-logging" @@ -3462,21 +3425,24 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -3500,20 +3466,20 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.1.8" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" dependencies = [ - "itertools 0.10.3", + "itertools 0.10.5", "nom 7.1.1", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f82cbe94f41641d6c410ded25bbf5097c240cefdf8e3b06d04198d0a96af6a4" +checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" dependencies = [ "sqlx-core", "sqlx-macros", @@ -3521,9 +3487,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b69bf218860335ddda60d6ce85ee39f6cf6e5630e300e19757d1de15886a093" +checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" dependencies = [ "ahash", "atoi", @@ -3535,6 +3501,7 @@ dependencies = [ "crc", "crossbeam-queue", "dirs", + "dotenvy", "either", "event-listener", "futures-channel", @@ -3546,10 +3513,10 @@ dependencies = [ "hkdf", "hmac 0.12.1", "indexmap", - "itoa 1.0.2", + "itoa 1.0.3", "libc", "log", - "md-5 0.10.4", + "md-5 0.10.5", "memchr", "once_cell", "paste", @@ -3559,8 +3526,8 @@ dependencies = [ "rustls-pemfile", "serde", "serde_json", - "sha-1 0.10.0", - "sha2 0.10.2", + "sha1", + "sha2 0.10.6", "smallvec", "sqlformat", "sqlx-rt", @@ -3574,31 +3541,31 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40c63177cf23d356b159b60acd27c54af7423f1736988502e36bae9a712118f" +checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" dependencies = [ - "dotenv", + "dotenvy", "either", "heck 0.4.0", "hex", "once_cell", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.44", + "quote 1.0.21", "serde", "serde_json", - "sha2 0.10.2", + "sha2 0.10.6", "sqlx-core", "sqlx-rt", - "syn 1.0.98", + "syn 1.0.100", "url", ] [[package]] name = "sqlx-rt" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874e93a365a598dc3dadb197565952cb143ae4aa716f7bcc933a8d836f6bf89f" +checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" dependencies = [ "once_cell", "tokio", @@ -3632,7 +3599,7 @@ checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "phf_shared", "precomputed-hash", ] @@ -3678,12 +3645,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.44", + "quote 1.0.21", "unicode-ident", ] @@ -3693,10 +3660,10 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", - "unicode-xid 0.2.3", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", + "unicode-xid 0.2.4", ] [[package]] @@ -3725,7 +3692,7 @@ dependencies = [ "cfg-if", "fastrand", "libc", - "redox_syscall 0.2.13", + "redox_syscall 0.2.16", "remove_dir_all", "winapi", ] @@ -3761,28 +3728,28 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -3818,11 +3785,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.11" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" dependencies = [ - "itoa 1.0.2", + "itoa 1.0.3", "libc", "num_threads", "serde", @@ -3861,17 +3828,18 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", "once_cell", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", @@ -3881,13 +3849,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -3925,9 +3893,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -3943,7 +3911,7 @@ dependencies = [ "filetime", "futures-core", "libc", - "redox_syscall 0.2.13", + "redox_syscall 0.2.16", "tokio", "tokio-stream", "xattr", @@ -3951,9 +3919,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06cda1232a49558c46f8a504d5b93101d42c0bf7f911f12a105ba48168f821ae" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" dependencies = [ "futures-util", "log", @@ -3965,9 +3933,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -4008,15 +3976,15 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "pin-project-lite", @@ -4026,20 +3994,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", "valuable", @@ -4062,7 +4030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" dependencies = [ "tracing", - "tracing-subscriber 0.3.14", + "tracing-subscriber 0.3.15", ] [[package]] @@ -4099,9 +4067,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a713421342a5a666b7577783721d3117f1b69a393df803ee17bb73b1e122a59" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" dependencies = [ "ansi_term", "matchers", @@ -4138,7 +4106,7 @@ dependencies = [ "radix_trie", "rand 0.8.5", "thiserror", - "time 0.3.11", + "time 0.3.14", "tokio", "tracing", "trust-dns-proto", @@ -4157,7 +4125,7 @@ dependencies = [ "futures-channel", "futures-io", "futures-util", - "idna", + "idna 0.2.3", "ipnet", "lazy_static", "rand 0.8.5", @@ -4183,7 +4151,7 @@ dependencies = [ "futures-util", "serde", "thiserror", - "time 0.3.11", + "time 0.3.14", "tokio", "toml", "tracing", @@ -4199,9 +4167,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "tungstenite" -version = "0.17.2" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" dependencies = [ "base64", "byteorder", @@ -4211,7 +4179,7 @@ dependencies = [ "log", "native-tls", "rand 0.8.5", - "sha-1 0.10.0", + "sha-1", "thiserror", "url", "utf-8", @@ -4223,9 +4191,9 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", ] [[package]] @@ -4236,9 +4204,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicode-bidi" @@ -4248,30 +4216,30 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -4281,9 +4249,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unicode_categories" @@ -4305,13 +4273,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna", - "matches", + "idna 0.3.0", "percent-encoding", "serde", ] @@ -4328,7 +4295,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", ] [[package]] @@ -4394,9 +4361,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4404,24 +4371,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "once_cell", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if", "js-sys", @@ -4431,38 +4398,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.18", + "quote 1.0.21", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -4480,9 +4447,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.4" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" dependencies = [ "webpki", ] @@ -4619,9 +4586,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.5" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" dependencies = [ "zeroize_derive", ] @@ -4632,8 +4599,8 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn 1.0.98", + "proc-macro2 1.0.44", + "quote 1.0.21", + "syn 1.0.100", "synstructure", ]