From 9e63f3f7c619df338b341888cf8ea62e2f22107f Mon Sep 17 00:00:00 2001 From: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:54:05 -0600 Subject: [PATCH] add callback for getContainerIp (#2851) * add callback for getContainerIp * register callback before retrieving info * version bump; only use backports for linux --- .../src/Adapters/EffectCreator.ts | 4 +- core/Cargo.lock | 2 +- core/startos/Cargo.toml | 2 +- core/startos/src/auth.rs | 2 + core/startos/src/backup/backup_bulk.rs | 13 +- core/startos/src/backup/target/cifs.rs | 9 +- core/startos/src/context/rpc.rs | 10 +- core/startos/src/db/mod.rs | 4 +- core/startos/src/db/prelude.rs | 2 +- core/startos/src/init.rs | 9 +- core/startos/src/install/mod.rs | 3 +- core/startos/src/middleware/auth.rs | 6 +- core/startos/src/net/acme.rs | 12 +- core/startos/src/net/host/address.rs | 11 +- core/startos/src/net/host/binding.rs | 3 +- core/startos/src/net/net_controller.rs | 12 +- core/startos/src/net/network_interface.rs | 3 +- core/startos/src/net/tor.rs | 4 +- core/startos/src/net/vhost.rs | 3 +- core/startos/src/net/wifi.rs | 10 +- core/startos/src/notifications.rs | 4 + core/startos/src/progress.rs | 3 +- core/startos/src/registry/admin.rs | 7 +- core/startos/src/registry/db.rs | 4 +- core/startos/src/registry/info.rs | 2 + core/startos/src/registry/os/asset/add.rs | 3 +- core/startos/src/registry/os/asset/sign.rs | 1 + core/startos/src/registry/os/version/mod.rs | 2 + .../startos/src/registry/os/version/signer.rs | 2 + core/startos/src/registry/package/add.rs | 1 + core/startos/src/registry/package/category.rs | 6 +- core/startos/src/registry/package/signer.rs | 2 + core/startos/src/s9pk/v2/pack.rs | 38 +++--- core/startos/src/service/action.rs | 3 +- core/startos/src/service/effects/action.rs | 12 +- core/startos/src/service/effects/callbacks.rs | 32 ++++- core/startos/src/service/effects/control.rs | 17 +-- .../startos/src/service/effects/dependency.rs | 1 + core/startos/src/service/effects/health.rs | 3 +- core/startos/src/service/effects/mod.rs | 2 - core/startos/src/service/effects/net/host.rs | 18 +-- core/startos/src/service/effects/net/info.rs | 52 +++++++- .../src/service/effects/net/interface.rs | 121 ++++++++++++------ core/startos/src/service/effects/net/ssl.rs | 6 +- core/startos/src/service/effects/store.rs | 14 +- core/startos/src/service/effects/system.rs | 19 +-- core/startos/src/service/mod.rs | 14 +- .../src/service/persistent_container.rs | 10 +- core/startos/src/service/service_actor.rs | 3 +- core/startos/src/service/service_map.rs | 110 ++++++++-------- core/startos/src/setup.rs | 3 +- core/startos/src/shutdown.rs | 6 +- core/startos/src/ssh.rs | 6 +- core/startos/src/system.rs | 12 +- core/startos/src/update/mod.rs | 34 ++--- core/startos/src/version/mod.rs | 21 ++- core/startos/src/version/v0_3_6_alpha_17.rs | 36 ++++++ core/startos/src/version/v0_3_6_alpha_6.rs | 3 +- image-recipe/build.sh | 2 +- patch-db | 2 +- sdk/base/lib/Effects.ts | 5 +- .../lib/osBindings/GetContainerIpParams.ts | 8 ++ sdk/base/lib/osBindings/index.ts | 1 + .../lib/test/startosTypeValidation.test.ts | 3 +- sdk/package/lib/StartSdk.ts | 64 ++++++++- sdk/package/package-lock.json | 4 +- sdk/package/package.json | 2 +- web/package-lock.json | 4 +- web/package.json | 2 +- 69 files changed, 592 insertions(+), 262 deletions(-) create mode 100644 core/startos/src/version/v0_3_6_alpha_17.rs create mode 100644 sdk/base/lib/osBindings/GetContainerIpParams.ts diff --git a/container-runtime/src/Adapters/EffectCreator.ts b/container-runtime/src/Adapters/EffectCreator.ts index ed975f25e..e11cd9d43 100644 --- a/container-runtime/src/Adapters/EffectCreator.ts +++ b/container-runtime/src/Adapters/EffectCreator.ts @@ -193,8 +193,8 @@ export function makeEffects(context: EffectContext): Effects { T.Effects["exposeForDependents"] > }, - getContainerIp(...[]: Parameters) { - return rpcRound("get-container-ip", {}) as ReturnType< + getContainerIp(...[options]: Parameters) { + return rpcRound("get-container-ip", options) as ReturnType< T.Effects["getContainerIp"] > }, diff --git a/core/Cargo.lock b/core/Cargo.lock index a68b20515..7ec339ded 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -5952,7 +5952,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "start-os" -version = "0.3.6-alpha.16" +version = "0.3.6-alpha.17" dependencies = [ "aes 0.7.5", "async-acme", diff --git a/core/startos/Cargo.toml b/core/startos/Cargo.toml index a04df93fd..e0bace2af 100644 --- a/core/startos/Cargo.toml +++ b/core/startos/Cargo.toml @@ -14,7 +14,7 @@ keywords = [ name = "start-os" readme = "README.md" repository = "https://github.com/Start9Labs/start-os" -version = "0.3.6-alpha.16" # VERSION_BUMP +version = "0.3.6-alpha.17" # VERSION_BUMP license = "MIT" [lib] diff --git a/core/startos/src/auth.rs b/core/startos/src/auth.rs index 9085709ab..2bc85b7db 100644 --- a/core/startos/src/auth.rs +++ b/core/startos/src/auth.rs @@ -247,6 +247,7 @@ pub async fn login_impl( Ok(hash_token.to_login_res()) }) .await + .result } } @@ -476,6 +477,7 @@ pub async fn reset_password_impl( Ok(()) }) .await + .result } #[instrument(skip_all)] diff --git a/core/startos/src/backup/backup_bulk.rs b/core/startos/src/backup/backup_bulk.rs index 136595b67..28aee82c1 100644 --- a/core/startos/src/backup/backup_bulk.rs +++ b/core/startos/src/backup/backup_bulk.rs @@ -59,7 +59,8 @@ impl BackupStatusGuard { .as_backup_progress_mut() .ser(&None) }) - .await?; + .await + .result?; } if let Some(db) = self.0.take() { match result { @@ -124,7 +125,8 @@ impl BackupStatusGuard { }) .await } - }?; + } + .result?; } Ok(()) } @@ -141,6 +143,7 @@ impl Drop for BackupStatusGuard { .ser(&None) }) .await + .result .log_err() }); } @@ -187,7 +190,8 @@ pub async fn backup_all( db.as_public().as_server_info().as_id().de()?, )) }) - .await?, + .await + .result?, BackupStatusGuard::new(ctx.db.clone()), ); @@ -348,7 +352,8 @@ async fn perform_backup( .as_last_backup_mut() .ser(&Some(timestamp)) }) - .await?; + .await + .result?; Ok(backup_report) } diff --git a/core/startos/src/backup/target/cifs.rs b/core/startos/src/backup/target/cifs.rs index 71cbe267e..63e18d0d8 100644 --- a/core/startos/src/backup/target/cifs.rs +++ b/core/startos/src/backup/target/cifs.rs @@ -112,7 +112,8 @@ pub async fn add( db.as_private_mut().as_cifs_mut().insert(&id, &cifs)?; Ok(id) }) - .await?; + .await + .result?; Ok(KeyVal { key: BackupTargetId::Cifs { id }, value: BackupTarget::Cifs(CifsBackupTarget { @@ -176,7 +177,8 @@ pub async fn update( })? .ser(&cifs) }) - .await?; + .await + .result?; Ok(KeyVal { key: BackupTargetId::Cifs { id }, value: BackupTarget::Cifs(CifsBackupTarget { @@ -207,7 +209,8 @@ pub async fn remove(ctx: RpcContext, RemoveParams { id }: RemoveParams) -> Resul }; ctx.db .mutate(|db| db.as_private_mut().as_cifs_mut().remove(&id)) - .await?; + .await + .result?; Ok(()) } diff --git a/core/startos/src/context/rpc.rs b/core/startos/src/context/rpc.rs index 96ca3ca63..8bd138b86 100644 --- a/core/startos/src/context/rpc.rs +++ b/core/startos/src/context/rpc.rs @@ -202,7 +202,8 @@ impl RpcContext { .ser(&true) }) .await - .unwrap() + .result + .log_err(); }) .into(), ) @@ -330,7 +331,8 @@ impl RpcContext { } Ok(()) }) - .await?; + .await + .result?; let db = self.db.clone(); self.add_cron(async move { loop { @@ -355,6 +357,7 @@ impl RpcContext { Ok(()) }) .await + .result { tracing::error!("Error in session cleanup cron: {e}"); tracing::debug!("{e:?}"); @@ -424,7 +427,8 @@ impl RpcContext { } Ok(()) }) - .await?; + .await + .result?; check_requested_actions.complete(); Ok(()) diff --git a/core/startos/src/db/mod.rs b/core/startos/src/db/mod.rs index 135153935..6575b401b 100644 --- a/core/startos/src/db/mod.rs +++ b/core/startos/src/db/mod.rs @@ -290,7 +290,8 @@ async fn cli_apply( }; Ok::<_, Error>((value, ())) }) - .await?; + .await + .result?; } else { let method = parent_method.into_iter().chain(method).join("."); context @@ -328,6 +329,7 @@ pub async fn apply(ctx: RpcContext, ApplyParams { expr }: ApplyParams) -> Result ) }) .await + .result } pub fn put() -> ParentHandler { diff --git a/core/startos/src/db/prelude.rs b/core/startos/src/db/prelude.rs index 419b356ef..136f2dd77 100644 --- a/core/startos/src/db/prelude.rs +++ b/core/startos/src/db/prelude.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use chrono::{DateTime, Utc}; pub use imbl_value::Value; use patch_db::value::InternedString; -pub use patch_db::{HasModel, PatchDb}; +pub use patch_db::{HasModel, MutateResult, PatchDb}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; diff --git a/core/startos/src/init.rs b/core/startos/src/init.rs index 63642dfb3..ef2455a29 100644 --- a/core/startos/src/init.rs +++ b/core/startos/src/init.rs @@ -419,7 +419,8 @@ pub async fn init( wifi.as_interface_mut().ser(&wifi_interface)?; wifi.de() }) - .await?; + .await + .result?; crate::net::wifi::synchronize_network_manager(MAIN_DATA, &wifi).await?; load_wifi.complete(); tracing::info!("Synchronized WiFi"); @@ -522,7 +523,8 @@ pub async fn init( server_info.as_status_info_mut().ser(&status_info)?; Ok(()) }) - .await?; + .await + .result?; tracing::info!("Updated server info"); update_server_info.complete(); @@ -540,7 +542,8 @@ pub async fn init( let model = d.de()?; d.ser(&model) }) - .await?; + .await + .result?; tracing::info!("Validated database"); validate_db.complete(); diff --git a/core/startos/src/install/mod.rs b/core/startos/src/install/mod.rs index ef0da2916..d7a939271 100644 --- a/core/startos/src/install/mod.rs +++ b/core/startos/src/install/mod.rs @@ -541,7 +541,8 @@ pub async fn uninstall( )), }) }) - .await?; + .await + .result?; let return_id = id.clone(); diff --git a/core/startos/src/middleware/auth.rs b/core/startos/src/middleware/auth.rs index 7c5eaa4c2..a43f22529 100644 --- a/core/startos/src/middleware/auth.rs +++ b/core/startos/src/middleware/auth.rs @@ -65,7 +65,8 @@ impl HasLoggedOutSessions { Ok(()) }) - .await?; + .await + .result?; Ok(HasLoggedOutSessions(())) } } @@ -136,7 +137,8 @@ impl HasValidSession { Ok(()) }) }) - .await?; + .await + .result?; } Ok(Self(SessionType::Session(session_token))) } diff --git a/core/startos/src/net/acme.rs b/core/startos/src/net/acme.rs index 7e2dd23de..2183f001a 100644 --- a/core/startos/src/net/acme.rs +++ b/core/startos/src/net/acme.rs @@ -74,7 +74,8 @@ impl<'a> async_acme::cache::AcmeCache for AcmeCertCache<'a> { .as_accounts_mut() .insert(&contacts, &Pem::new(key)) }) - .await?; + .await + .result?; Ok(()) } @@ -166,7 +167,8 @@ impl<'a> async_acme::cache::AcmeCache for AcmeCertCache<'a> { .upsert(&directory_url, || Ok(BTreeMap::new()))? .insert(&identifiers, &cert) }) - .await?; + .await + .result?; Ok(()) } @@ -259,7 +261,8 @@ pub async fn init( .as_acme_mut() .insert(&provider, &AcmeSettings { contact }) }) - .await?; + .await + .result?; Ok(()) } @@ -280,6 +283,7 @@ pub async fn remove( .as_acme_mut() .remove(&provider) }) - .await?; + .await + .result?; Ok(()) } diff --git a/core/startos/src/net/host/address.rs b/core/startos/src/net/host/address.rs index b75734a13..bd08c70a3 100644 --- a/core/startos/src/net/host/address.rs +++ b/core/startos/src/net/host/address.rs @@ -202,7 +202,7 @@ pub async fn add_domain( )?; check_duplicates(db) }) - .await?; + .await.result?; Kind::sync_host(&ctx, inheritance).await?; Ok(()) @@ -224,7 +224,8 @@ pub async fn remove_domain( .as_domains_mut() .remove(&domain) }) - .await?; + .await + .result?; Kind::sync_host(&ctx, inheritance).await?; Ok(()) @@ -258,7 +259,8 @@ pub async fn add_onion( .mutate(|a| Ok(a.insert(onion)))?; check_duplicates(db) }) - .await?; + .await + .result?; Kind::sync_host(&ctx, inheritance).await?; @@ -285,7 +287,8 @@ pub async fn remove_onion( .as_onions_mut() .mutate(|a| Ok(a.remove(&onion))) }) - .await?; + .await + .result?; Kind::sync_host(&ctx, inheritance).await?; diff --git a/core/startos/src/net/host/binding.rs b/core/startos/src/net/host/binding.rs index 5b726a82d..2d27a38b2 100644 --- a/core/startos/src/net/host/binding.rs +++ b/core/startos/src/net/host/binding.rs @@ -239,6 +239,7 @@ pub async fn set_public( Ok(()) }) }) - .await?; + .await + .result?; Kind::sync_host(&ctx, inheritance).await } diff --git a/core/startos/src/net/net_controller.rs b/core/startos/src/net/net_controller.rs index c3d0e8676..ca687bedb 100644 --- a/core/startos/src/net/net_controller.rs +++ b/core/startos/src/net/net_controller.rs @@ -178,7 +178,8 @@ impl NetServiceData { } Ok(res) }) - .await?; + .await + .result?; let mut errors = ErrorCollection::new(); for (id, host) in hosts.0 { errors.handle(self.update(ctrl, id, host).await); @@ -202,7 +203,8 @@ impl NetServiceData { })?; host.de() }) - .await?; + .await + .result?; self.update(ctrl, HostId::default(), host).await } } @@ -580,7 +582,8 @@ impl NetServiceData { .as_hostname_info_mut() .ser(&hostname_info) }) - .await?; + .await + .result?; Ok(()) } @@ -681,7 +684,8 @@ impl NetService { db.as_private_mut().as_available_ports_mut().ser(&ports)?; Ok(host) }) - .await?; + .await + .result?; data.update(&*ctrl, id, host).await } diff --git a/core/startos/src/net/network_interface.rs b/core/startos/src/net/network_interface.rs index c870629d4..d89745730 100644 --- a/core/startos/src/net/network_interface.rs +++ b/core/startos/src/net/network_interface.rs @@ -666,7 +666,8 @@ impl NetworkInterfaceController { .as_network_interfaces_mut() .ser(info) }) - .await?; + .await + .result?; let ntp: BTreeSet<_> = info .values() diff --git a/core/startos/src/net/tor.rs b/core/startos/src/net/tor.rs index bba50c371..14934d614 100644 --- a/core/startos/src/net/tor.rs +++ b/core/startos/src/net/tor.rs @@ -156,6 +156,7 @@ pub async fn generate_key(ctx: RpcContext) -> Result { .get_onion_address()) }) .await + .result } #[derive(Deserialize, Serialize, Parser)] @@ -175,7 +176,8 @@ pub async fn add_key( .as_onion_mut() .insert_key(&key) }) - .await?; + .await + .result?; Ok(key.public().get_onion_address()) } diff --git a/core/startos/src/net/vhost.rs b/core/startos/src/net/vhost.rs index 6317fa8c9..a20d7dda7 100644 --- a/core/startos/src/net/vhost.rs +++ b/core/startos/src/net/vhost.rs @@ -499,7 +499,8 @@ impl VHostServer { .as_local_certs_mut() .cert_for(&hostnames) }) - .await?; + .await + .result?; let cfg = ServerConfig::builder_with_provider(crypto_provider.clone()) .with_safe_default_protocol_versions() .with_kind(crate::ErrorKind::OpenSsl)? diff --git a/core/startos/src/net/wifi.rs b/core/startos/src/net/wifi.rs index a70fbfc73..28025ec99 100644 --- a/core/startos/src/net/wifi.rs +++ b/core/startos/src/net/wifi.rs @@ -161,7 +161,8 @@ pub async fn add(ctx: RpcContext, AddParams { ssid, password }: AddParams) -> Re Ok(()) }) }) - .await?; + .await + .result?; Ok(()) } #[derive(Deserialize, Serialize, Parser, TS)] @@ -225,7 +226,8 @@ pub async fn connect(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result })?; wifi.as_selected_mut().ser(&Some(ssid)) }) - .await?; + .await + .result?; Ok(()) } @@ -262,7 +264,8 @@ pub async fn remove(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result< wifi.as_selected_mut() .map_mutate(|s| Ok(s.filter(|s| s == &ssid.0))) }) - .await?; + .await + .result?; Ok(()) } #[derive(serde::Serialize, serde::Deserialize)] @@ -739,6 +742,7 @@ impl WpaCli { .ser(&new_country) }) .await + .result } async fn check_active_network(&self, ssid: &Ssid) -> Result, Error> { Ok(self diff --git a/core/startos/src/notifications.rs b/core/startos/src/notifications.rs index 48444020a..b586a98c6 100644 --- a/core/startos/src/notifications.rs +++ b/core/startos/src/notifications.rs @@ -116,6 +116,7 @@ pub async fn list( } }) .await + .result } #[derive(Deserialize, Serialize, Parser, TS)] @@ -133,6 +134,7 @@ pub async fn remove(ctx: RpcContext, DeleteParams { id }: DeleteParams) -> Resul Ok(()) }) .await + .result } #[derive(Deserialize, Serialize, Parser, TS)] #[serde(rename_all = "camelCase")] @@ -156,6 +158,7 @@ pub async fn remove_before( Ok(()) }) .await + .result } #[derive(Deserialize, Serialize, Parser, TS)] @@ -180,6 +183,7 @@ pub async fn create( ctx.db .mutate(|db| notify(db, package, level, title, message, ())) .await + .result } #[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, TS)] diff --git a/core/startos/src/progress.rs b/core/startos/src/progress.rs index cc3257132..38497d6cf 100644 --- a/core/startos/src/progress.rs +++ b/core/startos/src/progress.rs @@ -294,7 +294,8 @@ impl FullProgressTracker { Ok(true) } }) - .await? + .await + .result? { break; } diff --git a/core/startos/src/registry/admin.rs b/core/startos/src/registry/admin.rs index f3cac9f7e..ffc9c3b35 100644 --- a/core/startos/src/registry/admin.rs +++ b/core/startos/src/registry/admin.rs @@ -148,6 +148,7 @@ pub async fn add_signer(ctx: RegistryContext, signer: SignerInfo) -> Result( @@ -279,6 +282,7 @@ pub async fn add_admin( Ok(()) }) .await + .result } #[derive(Debug, Deserialize, Serialize, Parser)] @@ -310,7 +314,8 @@ pub async fn cli_add_admin( db.as_admins_mut().mutate(|a| Ok(a.insert(signer)))?; Ok(()) }) - .await?; + .await + .result?; } else { ctx.call_remote::( &parent_method.into_iter().chain(method).join("."), diff --git a/core/startos/src/registry/db.rs b/core/startos/src/registry/db.rs index 8de9f8743..59a55d9fb 100644 --- a/core/startos/src/registry/db.rs +++ b/core/startos/src/registry/db.rs @@ -136,7 +136,8 @@ async fn cli_apply( (), )) }) - .await?; + .await + .result?; } else { let method = parent_method.into_iter().chain(method).join("."); context @@ -178,4 +179,5 @@ pub async fn apply( ) }) .await + .result } diff --git a/core/startos/src/registry/info.rs b/core/startos/src/registry/info.rs index 402f0891a..10efda2cb 100644 --- a/core/startos/src/registry/info.rs +++ b/core/startos/src/registry/info.rs @@ -79,6 +79,7 @@ pub async fn set_name( ctx.db .mutate(|db| db.as_index_mut().as_name_mut().ser(&Some(name))) .await + .result } #[derive(Debug, Deserialize, Serialize, TS)] @@ -95,6 +96,7 @@ pub async fn set_icon( ctx.db .mutate(|db| db.as_index_mut().as_icon_mut().ser(&Some(icon))) .await + .result } #[derive(Debug, Deserialize, Serialize, Parser, TS)] diff --git a/core/startos/src/registry/os/asset/add.rs b/core/startos/src/registry/os/asset/add.rs index d609063ea..09a6ad164 100644 --- a/core/startos/src/registry/os/asset/add.rs +++ b/core/startos/src/registry/os/asset/add.rs @@ -131,7 +131,8 @@ async fn add_asset( Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization)) } }) - .await?; + .await + .result?; Ok(()) } diff --git a/core/startos/src/registry/os/asset/sign.rs b/core/startos/src/registry/os/asset/sign.rs index 18b603daf..a2094741b 100644 --- a/core/startos/src/registry/os/asset/sign.rs +++ b/core/startos/src/registry/os/asset/sign.rs @@ -117,6 +117,7 @@ async fn sign_asset( Ok(()) }) .await + .result } pub async fn sign_iso(ctx: RegistryContext, params: SignAssetParams) -> Result<(), Error> { diff --git a/core/startos/src/registry/os/version/mod.rs b/core/startos/src/registry/os/version/mod.rs index 8e4349ed9..12661e4e1 100644 --- a/core/startos/src/registry/os/version/mod.rs +++ b/core/startos/src/registry/os/version/mod.rs @@ -98,6 +98,7 @@ pub async fn add_version( }) }) .await + .result } #[derive(Debug, Deserialize, Serialize, Parser, TS)] @@ -122,6 +123,7 @@ pub async fn remove_version( Ok(()) }) .await + .result } #[derive(Debug, Deserialize, Serialize, Parser, TS)] diff --git a/core/startos/src/registry/os/version/signer.rs b/core/startos/src/registry/os/version/signer.rs index c72bb5ef4..c07e2fa0d 100644 --- a/core/startos/src/registry/os/version/signer.rs +++ b/core/startos/src/registry/os/version/signer.rs @@ -75,6 +75,7 @@ pub async fn add_version_signer( Ok(()) }) .await + .result } pub async fn remove_version_signer( @@ -101,6 +102,7 @@ pub async fn remove_version_signer( Ok(()) }) .await + .result } #[derive(Debug, Deserialize, Serialize, Parser, TS)] diff --git a/core/startos/src/registry/package/add.rs b/core/startos/src/registry/package/add.rs index c52f06ac0..bf3d36fd1 100644 --- a/core/startos/src/registry/package/add.rs +++ b/core/startos/src/registry/package/add.rs @@ -89,6 +89,7 @@ pub async fn add_package( } }) .await + .result } #[derive(Debug, Deserialize, Serialize, Parser)] diff --git a/core/startos/src/registry/package/category.rs b/core/startos/src/registry/package/category.rs index 97b0fb227..7afb8906b 100644 --- a/core/startos/src/registry/package/category.rs +++ b/core/startos/src/registry/package/category.rs @@ -78,7 +78,8 @@ pub async fn add_category( }, ) }) - .await?; + .await + .result?; Ok(()) } @@ -102,7 +103,8 @@ pub async fn remove_category( .as_categories_mut() .remove(&id) }) - .await?; + .await + .result?; Ok(()) } diff --git a/core/startos/src/registry/package/signer.rs b/core/startos/src/registry/package/signer.rs index 56bfc9b1c..7760bad3f 100644 --- a/core/startos/src/registry/package/signer.rs +++ b/core/startos/src/registry/package/signer.rs @@ -74,6 +74,7 @@ pub async fn add_package_signer( Ok(()) }) .await + .result } pub async fn remove_package_signer( @@ -100,6 +101,7 @@ pub async fn remove_package_signer( Ok(()) }) .await + .result } #[derive(Debug, Deserialize, Serialize, Parser, TS)] diff --git a/core/startos/src/s9pk/v2/pack.rs b/core/startos/src/s9pk/v2/pack.rs index f16649ece..aa661fc95 100644 --- a/core/startos/src/s9pk/v2/pack.rs +++ b/core/startos/src/s9pk/v2/pack.rs @@ -139,18 +139,20 @@ impl From for DynFileSource { #[derive(Deserialize, Serialize, Parser)] pub struct PackParams { pub path: Option, - #[arg(short = 'o', long = "output")] + #[arg(short, long)] pub output: Option, - #[arg(long = "javascript")] + #[arg(long)] pub javascript: Option, - #[arg(long = "icon")] + #[arg(long)] pub icon: Option, - #[arg(long = "license")] + #[arg(long)] pub license: Option, - #[arg(long = "instructions")] + #[arg(long)] pub instructions: Option, - #[arg(long = "assets")] + #[arg(long, conflicts_with = "no-assets")] pub assets: Option, + #[arg(long, conflicts_with = "assets")] + pub no_assets: bool, } impl PackParams { fn path(&self) -> &Path { @@ -693,14 +695,16 @@ pub async fn pack(ctx: CliContext, params: PackParams) -> Result<(), Error> { ) .await?; - let assets_dir = params.assets(); - s9pk.as_archive_mut().contents_mut().insert_path( - "assets.squashfs", - Entry::file(TmpSource::new( - tmp_dir.clone(), - PackSource::Squashfs(Arc::new(SqfsDir::new(assets_dir, tmp_dir.clone()))), - )), - )?; + if !params.no_assets { + let assets_dir = params.assets(); + s9pk.as_archive_mut().contents_mut().insert_path( + "assets.squashfs", + Entry::file(TmpSource::new( + tmp_dir.clone(), + PackSource::Squashfs(Arc::new(SqfsDir::new(assets_dir, tmp_dir.clone()))), + )), + )?; + } s9pk.load_images(tmp_dir.clone()).await?; @@ -810,8 +814,10 @@ pub async fn list_ingredients(_: CliContext, params: PackParams) -> Result for ServiceActor { } Ok(()) }) - .await?; + .await + .result?; Ok(result) } } diff --git a/core/startos/src/service/effects/action.rs b/core/startos/src/service/effects/action.rs index 5e3605679..cbab573c2 100644 --- a/core/startos/src/service/effects/action.rs +++ b/core/startos/src/service/effects/action.rs @@ -71,7 +71,8 @@ pub async fn export_action( value.insert(id, metadata); model.ser(&value) }) - .await?; + .await + .result?; Ok(()) } @@ -102,7 +103,8 @@ async fn clear_actions( .as_actions_mut() .mutate(|a| Ok(a.retain(|e, _| except.contains(e)))) }) - .await?; + .await + .result?; Ok(()) } @@ -271,7 +273,8 @@ async fn request_action( .as_requested_actions_mut() .insert(&replay_id, &ActionRequestEntry { active, request }) }) - .await?; + .await + .result?; Ok(()) } @@ -310,6 +313,7 @@ async fn clear_action_requests( })) }) }) - .await?; + .await + .result?; Ok(()) } diff --git a/core/startos/src/service/effects/callbacks.rs b/core/startos/src/service/effects/callbacks.rs index 19946672c..9f676d12e 100644 --- a/core/startos/src/service/effects/callbacks.rs +++ b/core/startos/src/service/effects/callbacks.rs @@ -8,8 +8,10 @@ use futures::future::join_all; use helpers::NonDetachingJoinHandle; use imbl::{vector, Vector}; use imbl_value::InternedString; +use lazy_static::lazy_static; use models::{HostId, PackageId, ServiceInterfaceId}; use patch_db::json_ptr::JsonPointer; +use patch_db::Revision; use serde::{Deserialize, Serialize}; use tracing::warn; use ts_rs::TS; @@ -37,6 +39,7 @@ struct ServiceCallbackMap { >, get_store: BTreeMap>>, get_status: BTreeMap>, + get_container_ip: BTreeMap>, } impl ServiceCallbacks { @@ -260,13 +263,19 @@ impl ServiceCallbacks { pub fn get_store( &self, package_id: &PackageId, - path: &JsonPointer, + revision: &Revision, ) -> Option { + lazy_static! { + static ref BASE: JsonPointer = "/private/packageStores".parse().unwrap(); + } + let for_pkg = BASE.clone().join_end(&**package_id); self.mutate(|this| { if let Some(watched) = this.get_store.get_mut(package_id) { let mut res = Vec::new(); watched.retain(|ptr, cbs| { - if ptr.starts_with(path) || path.starts_with(ptr) { + let mut full_ptr = for_pkg.clone(); + full_ptr.append(ptr); + if revision.patch.affects_path(&full_ptr) { res.append(cbs); false } else { @@ -280,6 +289,25 @@ impl ServiceCallbacks { .filter(|cb| !cb.0.is_empty()) }) } + + pub(super) fn add_get_container_ip(&self, package_id: PackageId, handler: CallbackHandler) { + self.mutate(|this| { + this.get_container_ip + .entry(package_id) + .or_default() + .push(handler) + }) + } + + #[must_use] + pub fn get_container_ip(&self, package_id: &PackageId) -> Option { + self.mutate(|this| { + this.get_container_ip + .remove(package_id) + .map(CallbackHandlers) + .filter(|cb| !cb.0.is_empty()) + }) + } } pub struct CallbackHandler { diff --git a/core/startos/src/service/effects/control.rs b/core/startos/src/service/effects/control.rs index 4b9817b77..aee3fd9db 100644 --- a/core/startos/src/service/effects/control.rs +++ b/core/startos/src/service/effects/control.rs @@ -46,6 +46,15 @@ pub async fn get_status( let context = context.deref()?; let id = package_id.unwrap_or_else(|| context.seed.id.clone()); let db = context.seed.ctx.db.peek().await; + + if let Some(callback) = callback { + let callback = callback.register(&context.seed.persistent_container); + context.seed.ctx.callbacks.add_get_status( + id.clone(), + super::callbacks::CallbackHandler::new(&context, callback), + ); + } + let status = db .as_public() .as_package_data() @@ -54,14 +63,6 @@ pub async fn get_status( .as_status() .de()?; - if let Some(callback) = callback { - let callback = callback.register(&context.seed.persistent_container); - context.seed.ctx.callbacks.add_get_status( - id, - super::callbacks::CallbackHandler::new(&context, callback), - ); - } - Ok(status) } diff --git a/core/startos/src/service/effects/dependency.rs b/core/startos/src/service/effects/dependency.rs index 2a16b4155..5bf0ee4f7 100644 --- a/core/startos/src/service/effects/dependency.rs +++ b/core/startos/src/service/effects/dependency.rs @@ -249,6 +249,7 @@ pub async fn set_dependencies( .ser(&CurrentDependencies(deps)) }) .await + .result } pub async fn get_dependencies(context: EffectContext) -> Result, Error> { diff --git a/core/startos/src/service/effects/health.rs b/core/startos/src/service/effects/health.rs index c95dea946..26524c1f5 100644 --- a/core/startos/src/service/effects/health.rs +++ b/core/startos/src/service/effects/health.rs @@ -40,6 +40,7 @@ pub async fn set_health( Ok(()) }) }) - .await?; + .await + .result?; Ok(()) } diff --git a/core/startos/src/service/effects/mod.rs b/core/startos/src/service/effects/mod.rs index 48b901d07..43d893efc 100644 --- a/core/startos/src/service/effects/mod.rs +++ b/core/startos/src/service/effects/mod.rs @@ -192,6 +192,4 @@ pub fn handler() -> ParentHandler { "get-system-smtp", from_fn_async(system::get_system_smtp).no_cli(), ) - - // TODO Callbacks } diff --git a/core/startos/src/service/effects/net/host.rs b/core/startos/src/service/effects/net/host.rs index 570d5033d..7039942d7 100644 --- a/core/startos/src/service/effects/net/host.rs +++ b/core/startos/src/service/effects/net/host.rs @@ -27,6 +27,15 @@ pub async fn get_host_info( let db = context.seed.ctx.db.peek().await; let package_id = package_id.unwrap_or_else(|| context.seed.id.clone()); + if let Some(callback) = callback { + let callback = callback.register(&context.seed.persistent_container); + context.seed.ctx.callbacks.add_get_host_info( + package_id.clone(), + host_id.clone(), + CallbackHandler::new(&context, callback), + ); + } + let res = db .as_public() .as_package_data() @@ -35,14 +44,5 @@ pub async fn get_host_info( .map(|m| m.de()) .transpose()?; - if let Some(callback) = callback { - let callback = callback.register(&context.seed.persistent_container); - context.seed.ctx.callbacks.add_get_host_info( - package_id, - host_id, - CallbackHandler::new(&context, callback), - ); - } - Ok(res) } diff --git a/core/startos/src/service/effects/net/info.rs b/core/startos/src/service/effects/net/info.rs index 766c0015f..3b6b38e83 100644 --- a/core/startos/src/service/effects/net/info.rs +++ b/core/startos/src/service/effects/net/info.rs @@ -1,9 +1,55 @@ use std::net::Ipv4Addr; +use models::PackageId; + +use crate::service::effects::callbacks::CallbackHandler; use crate::service::effects::prelude::*; +use crate::service::rpc::CallbackId; use crate::HOST_IP; -pub async fn get_container_ip(context: EffectContext) -> Result { - let context = context.deref()?; - Ok(context.seed.persistent_container.net_service.get_ip().await) +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export)] +pub struct GetContainerIpParams { + #[ts(optional)] + package_id: Option, + #[ts(optional)] + callback: Option, +} + +pub async fn get_container_ip( + context: EffectContext, + GetContainerIpParams { + package_id, + callback, + }: GetContainerIpParams, +) -> Result, Error> { + let context = context.deref()?; + + if let Some(package_id) = package_id.filter(|id| id != &context.seed.id) { + if let Some(callback) = callback { + // ip is static for the lifetime of the container, so callback unnecessary for self + let callback = callback.register(&context.seed.persistent_container); + context + .seed + .ctx + .callbacks + .add_get_container_ip(package_id.clone(), CallbackHandler::new(&context, callback)); + } + let Some(svc) = &*context.seed.ctx.services.get(&package_id).await else { + return Ok(None); + }; + + let Some(lxc) = svc.seed.persistent_container.lxc_container.get() else { + return Ok(None); + }; + let res = lxc.ip().await?; + + Ok(Some(res)) + } else { + let Some(lxc) = context.seed.persistent_container.lxc_container.get() else { + return Ok(None); + }; + lxc.ip().await.map(Some) + } } diff --git a/core/startos/src/service/effects/net/interface.rs b/core/startos/src/service/effects/net/interface.rs index 5de9638c4..6cb327fff 100644 --- a/core/startos/src/service/effects/net/interface.rs +++ b/core/startos/src/service/effects/net/interface.rs @@ -42,35 +42,40 @@ pub async fn export_service_interface( interface_type: r#type, }; - context + let res = context .seed .ctx .db .mutate(|db| { - db.as_public_mut() + let ifaces = db + .as_public_mut() .as_package_data_mut() .as_idx_mut(&package_id) .or_not_found(&package_id)? - .as_service_interfaces_mut() - .insert(&id, &service_interface)?; + .as_service_interfaces_mut(); + ifaces.insert(&id, &service_interface)?; Ok(()) }) - .await?; - if let Some(callbacks) = context - .seed - .ctx - .callbacks - .get_service_interface(&(package_id.clone(), id)) - { - callbacks.call(vector![]).await?; - } - if let Some(callbacks) = context - .seed - .ctx - .callbacks - .list_service_interfaces(&package_id) - { - callbacks.call(vector![]).await?; + .await; + res.result?; + + if res.revision.is_some() { + if let Some(callbacks) = context + .seed + .ctx + .callbacks + .get_service_interface(&(package_id.clone(), id)) + { + callbacks.call(vector![]).await?; + } + if let Some(callbacks) = context + .seed + .ctx + .callbacks + .list_service_interfaces(&package_id) + { + callbacks.call(vector![]).await?; + } } Ok(()) @@ -98,6 +103,15 @@ pub async fn get_service_interface( let package_id = package_id.unwrap_or_else(|| context.seed.id.clone()); let db = context.seed.ctx.db.peek().await; + if let Some(callback) = callback { + let callback = callback.register(&context.seed.persistent_container); + context.seed.ctx.callbacks.add_get_service_interface( + package_id.clone(), + service_interface_id.clone(), + CallbackHandler::new(&context, callback), + ); + } + let interface = db .as_public() .as_package_data() @@ -106,15 +120,6 @@ pub async fn get_service_interface( .map(|m| m.de()) .transpose()?; - if let Some(callback) = callback { - let callback = callback.register(&context.seed.persistent_container); - context.seed.ctx.callbacks.add_get_service_interface( - package_id, - service_interface_id, - CallbackHandler::new(&context, callback), - ); - } - Ok(interface) } @@ -137,6 +142,14 @@ pub async fn list_service_interfaces( let context = context.deref()?; let package_id = package_id.unwrap_or_else(|| context.seed.id.clone()); + if let Some(callback) = callback { + let callback = callback.register(&context.seed.persistent_container); + context.seed.ctx.callbacks.add_list_service_interfaces( + package_id.clone(), + CallbackHandler::new(&context, callback), + ); + } + let res = context .seed .ctx @@ -150,15 +163,6 @@ pub async fn list_service_interfaces( .transpose()? .unwrap_or_default(); - if let Some(callback) = callback { - let callback = callback.register(&context.seed.persistent_container); - context - .seed - .ctx - .callbacks - .add_list_service_interfaces(package_id, CallbackHandler::new(&context, callback)); - } - Ok(res) } @@ -176,17 +180,52 @@ pub async fn clear_service_interfaces( let context = context.deref()?; let package_id = context.seed.id.clone(); - context + let res = context .seed .ctx .db .mutate(|db| { + let mut removed = Vec::new(); db.as_public_mut() .as_package_data_mut() .as_idx_mut(&package_id) .or_not_found(&package_id)? .as_service_interfaces_mut() - .mutate(|s| Ok(s.retain(|id, _| except.contains(id)))) + .mutate(|s| { + Ok(s.retain(|id, _| { + if except.contains(id) { + true + } else { + removed.push(id.clone()); + false + } + })) + })?; + Ok(removed) }) - .await + .await; + let removed = res.result?; + + if res.revision.is_some() { + for id in removed { + if let Some(callbacks) = context + .seed + .ctx + .callbacks + .get_service_interface(&(package_id.clone(), id)) + { + callbacks.call(vector![]).await?; + } + } + if let Some(callbacks) = context + .seed + .ctx + .callbacks + .list_service_interfaces(&package_id) + { + callbacks.call(vector![]).await?; + } + } + + Ok(()) } diff --git a/core/startos/src/service/effects/net/ssl.rs b/core/startos/src/service/effects/net/ssl.rs index 66b4fa1e6..2ebd4e006 100644 --- a/core/startos/src/service/effects/net/ssl.rs +++ b/core/startos/src/service/effects/net/ssl.rs @@ -81,7 +81,8 @@ pub async fn get_ssl_certificate( .as_local_certs_mut() .cert_for(&hostnames) }) - .await?; + .await + .result?; let fullchain = match algorithm { Algorithm::Ecdsa => cert.fullchain_nistp256(), Algorithm::Ed25519 => cert.fullchain_ed25519(), @@ -171,7 +172,8 @@ pub async fn get_ssl_key( .as_local_certs_mut() .cert_for(&hostnames) }) - .await?; + .await + .result?; let key = match algorithm { Algorithm::Ecdsa => cert.leaf.keys.nistp256, Algorithm::Ed25519 => cert.leaf.keys.ed25519, diff --git a/core/startos/src/service/effects/store.rs b/core/startos/src/service/effects/store.rs index 39166c333..6ea28488e 100644 --- a/core/startos/src/service/effects/store.rs +++ b/core/startos/src/service/effects/store.rs @@ -65,7 +65,7 @@ pub async fn set_store( ) -> Result<(), Error> { let context = context.deref()?; let package_id = &context.seed.id; - context + let res = context .seed .ctx .db @@ -82,10 +82,13 @@ pub async fn set_store( .with_kind(ErrorKind::ParseDbField)?; model.ser(&model_value) }) - .await?; + .await; + res.result?; - if let Some(callbacks) = context.seed.ctx.callbacks.get_store(package_id, &path) { - callbacks.call(vector![]).await?; + if let Some(revision) = res.revision { + if let Some(callbacks) = context.seed.ctx.callbacks.get_store(package_id, &revision) { + callbacks.call(vector![]).await?; + } } Ok(()) @@ -116,7 +119,8 @@ pub async fn set_data_version( .as_data_version_mut() .ser(&Some(version)) }) - .await?; + .await + .result?; Ok(()) } diff --git a/core/startos/src/service/effects/system.rs b/core/startos/src/service/effects/system.rs index abf0a33c6..abf6f36ad 100644 --- a/core/startos/src/service/effects/system.rs +++ b/core/startos/src/service/effects/system.rs @@ -15,6 +15,16 @@ pub async fn get_system_smtp( GetSystemSmtpParams { callback }: GetSystemSmtpParams, ) -> Result, Error> { let context = context.deref()?; + + if let Some(callback) = callback { + let callback = callback.register(&context.seed.persistent_container); + context + .seed + .ctx + .callbacks + .add_get_system_smtp(CallbackHandler::new(&context, callback)); + } + let res = context .seed .ctx @@ -26,14 +36,5 @@ pub async fn get_system_smtp( .into_smtp() .de()?; - if let Some(callback) = callback { - let callback = callback.register(&context.seed.persistent_container); - context - .seed - .ctx - .callbacks - .add_get_system_smtp(CallbackHandler::new(&context, callback)); - } - Ok(res) } diff --git a/core/startos/src/service/mod.rs b/core/startos/src/service/mod.rs index 3cc8cb67b..8d3db1944 100644 --- a/core/startos/src/service/mod.rs +++ b/core/startos/src/service/mod.rs @@ -171,7 +171,8 @@ impl ServiceRef { Ok(None) } }) - .await? + .await + .result? { let state = pde.state_info.expect_removing()?; if !soft { @@ -336,7 +337,8 @@ impl Service { // TODO: delete s9pk? ctx.db .mutate(|v| v.as_public_mut().as_package_data_mut().remove(id)) - .await?; + .await + .result?; Ok(None) } PackageStateMatchModelRef::Updating(s) => { @@ -392,7 +394,7 @@ impl Service { }) } }) - .await?; + .await.result?; handle_installed(s9pk, entry).await } PackageStateMatchModelRef::Removing(_) | PackageStateMatchModelRef::Restoring(_) => { @@ -419,7 +421,8 @@ impl Service { ctx.db .mutate(|v| v.as_public_mut().as_package_data_mut().remove(id)) - .await?; + .await + .result?; Ok(None) } @@ -550,7 +553,8 @@ impl Service { Ok(()) }) - .await?; + .await + .result?; Ok(service) } diff --git a/core/startos/src/service/persistent_container.rs b/core/startos/src/service/persistent_container.rs index 016cae49f..a20f5c650 100644 --- a/core/startos/src/service/persistent_container.rs +++ b/core/startos/src/service/persistent_container.rs @@ -7,7 +7,7 @@ use std::time::Duration; use futures::future::ready; use futures::Future; use helpers::NonDetachingJoinHandle; -use imbl::Vector; +use imbl::{vector, Vector}; use imbl_value::InternedString; use models::{ImageId, ProcedureName, VolumeId}; use rpc_toolkit::{Empty, Server, ShutdownHandle}; @@ -297,10 +297,16 @@ impl PersistentContainer { .await?; } } + let ip = lxc_container.ip().await?; let net_service = ctx .net_controller - .create_service(s9pk.as_manifest().id.clone(), lxc_container.ip().await?) + .create_service(s9pk.as_manifest().id.clone(), ip) .await?; + if let Some(callbacks) = ctx.callbacks.get_container_ip(&s9pk.as_manifest().id) { + callbacks + .call(vector![Value::String(Arc::new(ip.to_string()))]) + .await?; + } Ok(Self { s9pk, lxc_container: OnceCell::new_with(Some(lxc_container)), diff --git a/core/startos/src/service/service_actor.rs b/core/startos/src/service/service_actor.rs index a56c92288..422198441 100644 --- a/core/startos/src/service/service_actor.rs +++ b/core/startos/src/service/service_actor.rs @@ -99,7 +99,8 @@ async fn service_actor_loop( } Ok(None) }) - .await?; + .await + .result?; if let Some((previous, new_state)) = major_changes_state { if let Some(callbacks) = seed.ctx.callbacks.get_status(id) { callbacks diff --git a/core/startos/src/service/service_map.rs b/core/startos/src/service/service_map.rs index cec0c8564..777be2bd7 100644 --- a/core/startos/src/service/service_map.rs +++ b/core/startos/src/service/service_map.rs @@ -117,7 +117,8 @@ impl ServiceMap { } Ok(()) }) - .await?; + .await + .result?; } } shutdown_err?; @@ -174,54 +175,62 @@ impl ServiceMap { let mut reload_guard = ServiceRefReloadGuard::new(ctx.clone(), id.clone(), op_name); reload_guard - .handle(ctx.db.mutate({ - let manifest = manifest.clone(); - let id = id.clone(); - let install_progress = progress.snapshot(); - move |db| { - if let Some(pde) = db.as_public_mut().as_package_data_mut().as_idx_mut(&id) { - let prev = pde.as_state_info().expect_installed()?.de()?; - pde.as_state_info_mut() - .ser(&PackageState::Updating(UpdatingState { - manifest: prev.manifest, - installing_info: InstallingInfo { - new_manifest: manifest, - progress: install_progress, - }, - }))?; - } else { - let installing = InstallingState { - installing_info: InstallingInfo { - new_manifest: manifest, - progress: install_progress, - }, - }; - db.as_public_mut().as_package_data_mut().insert( - &id, - &PackageDataEntry { - state_info: if restoring { - PackageState::Restoring(installing) - } else { - PackageState::Installing(installing) - }, - data_version: None, - status: MainStatus::Stopped, - registry: None, - developer_key: Pem::new(developer_key), - icon, - last_backup: None, - current_dependencies: Default::default(), - actions: Default::default(), - requested_actions: Default::default(), - service_interfaces: Default::default(), - hosts: Default::default(), - store_exposed_dependents: Default::default(), - }, - )?; - }; - Ok(()) - } - })) + .handle(async { + ctx.db + .mutate({ + let manifest = manifest.clone(); + let id = id.clone(); + let install_progress = progress.snapshot(); + move |db| { + if let Some(pde) = + db.as_public_mut().as_package_data_mut().as_idx_mut(&id) + { + let prev = pde.as_state_info().expect_installed()?.de()?; + pde.as_state_info_mut().ser(&PackageState::Updating( + UpdatingState { + manifest: prev.manifest, + installing_info: InstallingInfo { + new_manifest: manifest, + progress: install_progress, + }, + }, + ))?; + } else { + let installing = InstallingState { + installing_info: InstallingInfo { + new_manifest: manifest, + progress: install_progress, + }, + }; + db.as_public_mut().as_package_data_mut().insert( + &id, + &PackageDataEntry { + state_info: if restoring { + PackageState::Restoring(installing) + } else { + PackageState::Installing(installing) + }, + data_version: None, + status: MainStatus::Stopped, + registry: None, + developer_key: Pem::new(developer_key), + icon, + last_backup: None, + current_dependencies: Default::default(), + actions: Default::default(), + requested_actions: Default::default(), + service_interfaces: Default::default(), + hosts: Default::default(), + store_exposed_dependents: Default::default(), + }, + )?; + }; + Ok(()) + } + }) + .await + .result + }) .await?; Ok(async move { @@ -425,7 +434,8 @@ impl ServiceRefReloadInfo { (), ) }) - .await?; + .await + .result?; } Ok(()) } diff --git a/core/startos/src/setup.rs b/core/startos/src/setup.rs index 186fbb0c4..a1976e285 100644 --- a/core/startos/src/setup.rs +++ b/core/startos/src/setup.rs @@ -98,7 +98,8 @@ async fn setup_init( .ser(&account.password)?; Ok(account) }) - .await?; + .await + .result?; Ok((account, init_result)) } diff --git a/core/startos/src/shutdown.rs b/core/startos/src/shutdown.rs index 4e45f74c0..12deff743 100644 --- a/core/startos/src/shutdown.rs +++ b/core/startos/src/shutdown.rs @@ -84,7 +84,8 @@ pub async fn shutdown(ctx: RpcContext) -> Result<(), Error> { .as_shutting_down_mut() .ser(&true) }) - .await?; + .await + .result?; ctx.shutdown .send(Some(Shutdown { export_args: Some((ctx.disk_guid.clone(), Path::new(DATA_DIR).to_owned())), @@ -104,7 +105,8 @@ pub async fn restart(ctx: RpcContext) -> Result<(), Error> { .as_restarting_mut() .ser(&true) }) - .await?; + .await + .result?; ctx.shutdown .send(Some(Shutdown { export_args: Some((ctx.disk_guid.clone(), Path::new(DATA_DIR).to_owned())), diff --git a/core/startos/src/ssh.rs b/core/startos/src/ssh.rs index 301ed8721..0f236b813 100644 --- a/core/startos/src/ssh.rs +++ b/core/startos/src/ssh.rs @@ -145,7 +145,8 @@ pub async fn add(ctx: RpcContext, AddParams { key }: AddParams) -> Result Result< .ser(&enable)?; Ok(()) }) - .await?; + .await + .result?; Ok(()) } @@ -168,7 +169,8 @@ pub async fn governor( .as_governor_mut() .ser(&Some(set)) }) - .await?; + .await + .result?; } let current = ctx .db @@ -856,7 +858,8 @@ pub async fn set_system_smtp(ctx: RpcContext, smtp: SmtpValue) -> Result<(), Err .as_smtp_mut() .ser(&smtp) }) - .await?; + .await + .result?; if let Some(callbacks) = ctx.callbacks.get_system_smtp() { callbacks.call(vector![to_value(&smtp)?]).await?; } @@ -870,7 +873,8 @@ pub async fn clear_system_smtp(ctx: RpcContext) -> Result<(), Error> { .as_smtp_mut() .ser(&None) }) - .await?; + .await + .result?; if let Some(callbacks) = ctx.callbacks.get_system_smtp() { callbacks.call(vector![Value::Null]).await?; } diff --git a/core/startos/src/update/mod.rs b/core/startos/src/update/mod.rs index 7daa4f3b2..bf11983ca 100644 --- a/core/startos/src/update/mod.rs +++ b/core/startos/src/update/mod.rs @@ -288,7 +288,8 @@ async fn maybe_do_update( .ser(&status)?; Ok(status) }) - .await?; + .await + .result?; if status.updated { return Err(Error::new( @@ -332,12 +333,10 @@ async fn maybe_do_update( status_info.as_update_progress_mut().ser(&None)?; status_info.as_updated_mut().ser(&true) }) - .await?; - progress_task.await.with_kind(ErrorKind::Unknown)??; - CIRCLE_OF_5THS_SHORT - .play() .await - .expect("could not play sound"); + .result?; + progress_task.await.with_kind(ErrorKind::Unknown)??; + CIRCLE_OF_5THS_SHORT.play().await.log_err(); } Err(e) => { let err_string = format!("Update was not successful because of {}", e); @@ -358,24 +357,13 @@ async fn maybe_do_update( ) }) .await - .unwrap(); + .result + .log_err(); // TODO: refactor sound lib to make compound tempos easier to deal with - UPDATE_FAILED_1 - .play() - .await - .expect("could not play song: update failed 1"); - UPDATE_FAILED_2 - .play() - .await - .expect("could not play song: update failed 2"); - UPDATE_FAILED_3 - .play() - .await - .expect("could not play song: update failed 3"); - UPDATE_FAILED_4 - .play() - .await - .expect("could not play song: update failed 4"); + UPDATE_FAILED_1.play().await.log_err(); + UPDATE_FAILED_2.play().await.log_err(); + UPDATE_FAILED_3.play().await.log_err(); + UPDATE_FAILED_4.play().await.log_err(); } } Ok::<(), Error>(()) diff --git a/core/startos/src/version/mod.rs b/core/startos/src/version/mod.rs index 01f9c5e86..087f64e2f 100644 --- a/core/startos/src/version/mod.rs +++ b/core/startos/src/version/mod.rs @@ -36,8 +36,9 @@ mod v0_3_6_alpha_13; mod v0_3_6_alpha_14; mod v0_3_6_alpha_15; mod v0_3_6_alpha_16; +mod v0_3_6_alpha_17; -pub type Current = v0_3_6_alpha_16::Version; // VERSION_BUMP +pub type Current = v0_3_6_alpha_17::Version; // VERSION_BUMP impl Current { #[instrument(skip(self, db))] @@ -54,7 +55,8 @@ impl Current { rollback_to_unchecked(&from, &self, &mut db)?; Ok::<_, Error>((db, ())) }) - .await?; + .await + .result?; } Ordering::Less => { let pre_ups = PreUps::load(&from, &self).await?; @@ -62,7 +64,8 @@ impl Current { migrate_from_unchecked(&from, &self, pre_ups, &mut db)?; Ok::<_, Error>((to_value(&from_value::(db.clone())?)?, ())) }) - .await?; + .await + .result?; } Ordering::Equal => (), } @@ -103,7 +106,8 @@ pub async fn post_init( .as_post_init_migration_todos_mut() .mutate(|m| Ok(m.remove(&version.0.semver()))) }) - .await?; + .await + .result?; progress += 1; } } @@ -135,7 +139,8 @@ enum Version { V0_3_6_alpha_13(Wrapper), V0_3_6_alpha_14(Wrapper), V0_3_6_alpha_15(Wrapper), - V0_3_6_alpha_16(Wrapper), // VERSION_BUMP + V0_3_6_alpha_16(Wrapper), + V0_3_6_alpha_17(Wrapper), // VERSION_BUMP Other(exver::Version), } @@ -175,7 +180,8 @@ impl Version { Self::V0_3_6_alpha_13(v) => DynVersion(Box::new(v.0)), Self::V0_3_6_alpha_14(v) => DynVersion(Box::new(v.0)), Self::V0_3_6_alpha_15(v) => DynVersion(Box::new(v.0)), - Self::V0_3_6_alpha_16(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP + Self::V0_3_6_alpha_16(v) => DynVersion(Box::new(v.0)), + Self::V0_3_6_alpha_17(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP Self::Other(v) => { return Err(Error::new( eyre!("unknown version {v}"), @@ -207,7 +213,8 @@ impl Version { Version::V0_3_6_alpha_13(Wrapper(x)) => x.semver(), Version::V0_3_6_alpha_14(Wrapper(x)) => x.semver(), Version::V0_3_6_alpha_15(Wrapper(x)) => x.semver(), - Version::V0_3_6_alpha_16(Wrapper(x)) => x.semver(), // VERSION_BUMP + Version::V0_3_6_alpha_16(Wrapper(x)) => x.semver(), + Version::V0_3_6_alpha_17(Wrapper(x)) => x.semver(), // VERSION_BUMP Version::Other(x) => x.clone(), } } diff --git a/core/startos/src/version/v0_3_6_alpha_17.rs b/core/startos/src/version/v0_3_6_alpha_17.rs new file mode 100644 index 000000000..2d58bab5a --- /dev/null +++ b/core/startos/src/version/v0_3_6_alpha_17.rs @@ -0,0 +1,36 @@ +use exver::{PreReleaseSegment, VersionRange}; + +use super::v0_3_5::V0_3_0_COMPAT; +use super::{v0_3_6_alpha_16, VersionT}; +use crate::prelude::*; + +lazy_static::lazy_static! { + static ref V0_3_6_alpha_17: exver::Version = exver::Version::new( + [0, 3, 6], + [PreReleaseSegment::String("alpha".into()), 17.into()] + ); +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct Version; + +impl VersionT for Version { + type Previous = v0_3_6_alpha_16::Version; + type PreUpRes = (); + + async fn pre_up(self) -> Result { + Ok(()) + } + fn semver(self) -> exver::Version { + V0_3_6_alpha_17.clone() + } + fn compat(self) -> &'static VersionRange { + &V0_3_0_COMPAT + } + fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> { + Ok(()) + } + fn down(self, _db: &mut Value) -> Result<(), Error> { + Ok(()) + } +} diff --git a/core/startos/src/version/v0_3_6_alpha_6.rs b/core/startos/src/version/v0_3_6_alpha_6.rs index 7d62773ea..61d6675e4 100644 --- a/core/startos/src/version/v0_3_6_alpha_6.rs +++ b/core/startos/src/version/v0_3_6_alpha_6.rs @@ -45,7 +45,8 @@ impl VersionT for Version { )?; Ok(()) }) - .await?; + .await + .result?; Ok(()) } fn down(self, _db: &mut Value) -> Result<(), Error> { diff --git a/image-recipe/build.sh b/image-recipe/build.sh index eaf5e8382..8dc4a57d8 100755 --- a/image-recipe/build.sh +++ b/image-recipe/build.sh @@ -147,7 +147,7 @@ if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then fi cat > config/archives/backports.pref <<- EOF -Package: * +Package: linux-image-* Pin: release n=${IB_SUITE}-backports Pin-Priority: 500 EOF diff --git a/patch-db b/patch-db index 0df18c651..d1362bdcd 160000 --- a/patch-db +++ b/patch-db @@ -1 +1 @@ -Subproject commit 0df18c651f2311e2e26f3e6c8535a9e40b71502f +Subproject commit d1362bdcd9138125a8079e58ed9cc54358aa56f1 diff --git a/sdk/base/lib/Effects.ts b/sdk/base/lib/Effects.ts index b7c67af12..941e57cf9 100644 --- a/sdk/base/lib/Effects.ts +++ b/sdk/base/lib/Effects.ts @@ -130,7 +130,10 @@ export type Effects = { callback?: () => void }): Promise /** Returns the IP address of the container */ - getContainerIp(): Promise + getContainerIp(options: { + packageId?: PackageId + callback?: () => void + }): Promise /** Returns the IP address of StartOS */ getOsIp(): Promise // interface diff --git a/sdk/base/lib/osBindings/GetContainerIpParams.ts b/sdk/base/lib/osBindings/GetContainerIpParams.ts new file mode 100644 index 000000000..2c84b4960 --- /dev/null +++ b/sdk/base/lib/osBindings/GetContainerIpParams.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CallbackId } from "./CallbackId" +import type { PackageId } from "./PackageId" + +export type GetContainerIpParams = { + packageId?: PackageId + callback?: CallbackId +} diff --git a/sdk/base/lib/osBindings/index.ts b/sdk/base/lib/osBindings/index.ts index e2ab33033..305128b60 100644 --- a/sdk/base/lib/osBindings/index.ts +++ b/sdk/base/lib/osBindings/index.ts @@ -80,6 +80,7 @@ export { ForgetInterfaceParams } from "./ForgetInterfaceParams" export { FullIndex } from "./FullIndex" export { FullProgress } from "./FullProgress" export { GetActionInputParams } from "./GetActionInputParams" +export { GetContainerIpParams } from "./GetContainerIpParams" export { GetHostInfoParams } from "./GetHostInfoParams" export { GetOsAssetParams } from "./GetOsAssetParams" export { GetOsVersionParams } from "./GetOsVersionParams" diff --git a/sdk/base/lib/test/startosTypeValidation.test.ts b/sdk/base/lib/test/startosTypeValidation.test.ts index f6656e55d..3a66de1e1 100644 --- a/sdk/base/lib/test/startosTypeValidation.test.ts +++ b/sdk/base/lib/test/startosTypeValidation.test.ts @@ -7,6 +7,7 @@ import { ClearCallbacksParams, ClearServiceInterfacesParams, GetActionInputParams, + GetContainerIpParams, GetStatusParams, RequestActionParams, RunActionParams, @@ -77,7 +78,7 @@ describe("startosTypeValidation ", () => { set: {} as any, // as SetStoreParams, }, getSystemSmtp: {} as WithCallback, - getContainerIp: undefined, + getContainerIp: {} as WithCallback, getOsIp: undefined, getServicePortForward: {} as GetServicePortForwardParams, clearServiceInterfaces: {} as ClearServiceInterfacesParams, diff --git a/sdk/package/lib/StartSdk.ts b/sdk/package/lib/StartSdk.ts index 42229f436..799adcb3c 100644 --- a/sdk/package/lib/StartSdk.ts +++ b/sdk/package/lib/StartSdk.ts @@ -72,7 +72,7 @@ import * as actions from "../../base/lib/actions" import { setupInit } from "./inits/setupInit" import * as fs from "node:fs/promises" -export const OSVersion = testTypeVersion("0.3.6-alpha.16") +export const OSVersion = testTypeVersion("0.3.6-alpha.17") // prettier-ignore type AnyNeverCond = @@ -104,7 +104,10 @@ export class StartSdk { | "getHostInfo" type MainUsedEffects = "setMainStatus" | "setHealth" type CallbackEffects = "constRetry" | "clearCallbacks" - type AlreadyExposed = "getSslCertificate" | "getSystemSmtp" + type AlreadyExposed = + | "getSslCertificate" + | "getSystemSmtp" + | "getContainerIp" // prettier-ignore type StartSdkEffectWrapper = { @@ -123,7 +126,6 @@ export class StartSdk { getServicePortForward: (effects, ...args) => effects.getServicePortForward(...args), clearBindings: (effects, ...args) => effects.clearBindings(...args), - getContainerIp: (effects, ...args) => effects.getContainerIp(...args), getOsIp: (effects, ...args) => effects.getOsIp(...args), getSslKey: (effects, ...args) => effects.getSslKey(...args), setDataVersion: (effects, ...args) => effects.setDataVersion(...args), @@ -191,7 +193,61 @@ export class StartSdk { opts: { packageId: PackageId }, ) => getServiceInterfaces(effects, opts), }, - + getContainerIp: ( + effects: T.Effects, + options: Omit< + Parameters[0], + "callback" + > = {}, + ) => { + async function* watch() { + while (true) { + let callback: () => void = () => {} + const waitForNext = new Promise((resolve) => { + callback = resolve + }) + yield await effects.getContainerIp({ ...options, callback }) + await waitForNext + } + } + return { + const: () => + effects.getContainerIp({ + ...options, + callback: + effects.constRetry && + (() => effects.constRetry && effects.constRetry()), + }), + once: () => effects.getContainerIp(options), + watch, + onChange: ( + callback: ( + value: string | null, + error?: Error, + ) => void | Promise, + ) => { + ;(async () => { + for await (const value of watch()) { + try { + await callback(value) + } catch (e) { + console.error( + "callback function threw an error @ getContainerIp.onChange", + e, + ) + } + } + })() + .catch((e) => callback(null, e)) + .catch((e) => + console.error( + "callback function threw an error @ getContainerIp.onChange", + e, + ), + ) + }, + } + }, store: { get: ( effects: E, diff --git a/sdk/package/package-lock.json b/sdk/package/package-lock.json index 58aec58ad..e6eee8cac 100644 --- a/sdk/package/package-lock.json +++ b/sdk/package/package-lock.json @@ -1,12 +1,12 @@ { "name": "@start9labs/start-sdk", - "version": "0.3.6-beta.18", + "version": "0.3.6-beta.19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@start9labs/start-sdk", - "version": "0.3.6-beta.18", + "version": "0.3.6-beta.19", "license": "MIT", "dependencies": { "@iarna/toml": "^2.2.5", diff --git a/sdk/package/package.json b/sdk/package/package.json index ef9116d92..69d2c1f97 100644 --- a/sdk/package/package.json +++ b/sdk/package/package.json @@ -1,6 +1,6 @@ { "name": "@start9labs/start-sdk", - "version": "0.3.6-beta.18", + "version": "0.3.6-beta.19", "description": "Software development kit to facilitate packaging services for StartOS", "main": "./package/lib/index.js", "types": "./package/lib/index.d.ts", diff --git a/web/package-lock.json b/web/package-lock.json index 36379429c..b7eb9b040 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "startos-ui", - "version": "0.3.6-alpha.16", + "version": "0.3.6-alpha.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "startos-ui", - "version": "0.3.6-alpha.16", + "version": "0.3.6-alpha.17", "license": "MIT", "dependencies": { "@angular/animations": "^14.1.0", diff --git a/web/package.json b/web/package.json index 5b7402d5f..622124743 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "startos-ui", - "version": "0.3.6-alpha.16", + "version": "0.3.6-alpha.17", "author": "Start9 Labs, Inc", "homepage": "https://start9.com/", "license": "MIT",