diff --git a/appmgr/src/backup/mod.rs b/appmgr/src/backup/mod.rs index 887d55e06..6de98f03e 100644 --- a/appmgr/src/backup/mod.rs +++ b/appmgr/src/backup/mod.rs @@ -3,7 +3,7 @@ use std::path::Path; use chrono::{DateTime, Utc}; use color_eyre::eyre::eyre; -use patch_db::{DbHandle, HasModel}; +use patch_db::{DbHandle, HasModel, LockType}; use rpc_toolkit::command; use serde::{Deserialize, Serialize}; use sqlx::{Executor, Sqlite}; @@ -14,6 +14,7 @@ use tracing::instrument; use self::target::PackageBackupInfo; use crate::action::{ActionImplementation, NoOutput}; use crate::context::RpcContext; +use crate::dependencies::reconfigure_dependents_with_live_pointers; use crate::install::PKG_ARCHIVE_DIR; use crate::net::interface::{InterfaceId, Interfaces}; use crate::s9pk::manifest::PackageId; @@ -201,6 +202,10 @@ impl BackupActions { .execute(&mut *secrets) .await?; } + crate::db::DatabaseModel::new() + .package_data() + .lock(db, LockType::Write) + .await?; crate::db::DatabaseModel::new() .package_data() .idx_model(pkg_id) @@ -212,6 +217,20 @@ impl BackupActions { .interface_addresses() .put(db, &interfaces.install(&mut *secrets, pkg_id).await?) .await?; + + let entry = crate::db::DatabaseModel::new() + .package_data() + .idx_model(pkg_id) + .expect(db) + .await? + .installed() + .expect(db) + .await? + .get(db, true) + .await?; + + reconfigure_dependents_with_live_pointers(ctx, db, &entry).await?; + Ok(()) } } diff --git a/appmgr/src/config/spec.rs b/appmgr/src/config/spec.rs index 992cdb7e7..d46203fc0 100644 --- a/appmgr/src/config/spec.rs +++ b/appmgr/src/config/spec.rs @@ -1636,7 +1636,7 @@ impl ValueSpec for PackagePointerSpec { #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub struct TorAddressPointer { - package_id: PackageId, + pub package_id: PackageId, interface: InterfaceId, } impl TorAddressPointer { @@ -1667,7 +1667,7 @@ impl fmt::Display for TorAddressPointer { #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub struct LanAddressPointer { - package_id: PackageId, + pub package_id: PackageId, interface: InterfaceId, } impl fmt::Display for LanAddressPointer { diff --git a/appmgr/src/dependencies.rs b/appmgr/src/dependencies.rs index 466140776..ba3ccabf5 100644 --- a/appmgr/src/dependencies.rs +++ b/appmgr/src/dependencies.rs @@ -14,9 +14,10 @@ use tracing::instrument; use crate::action::{ActionImplementation, NoOutput}; use crate::config::action::ConfigRes; +use crate::config::spec::PackagePointerSpec; use crate::config::{Config, ConfigSpec}; use crate::context::RpcContext; -use crate::db::model::CurrentDependencyInfo; +use crate::db::model::{CurrentDependencyInfo, InstalledPackageDataEntry}; use crate::error::ResultExt; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::status::health_check::{HealthCheckId, HealthCheckResult}; @@ -876,3 +877,35 @@ pub fn heal_transitive<'a, Db: DbHandle>( } .boxed() } + +pub async fn reconfigure_dependents_with_live_pointers( + ctx: &RpcContext, + mut tx: impl DbHandle, + pde: &InstalledPackageDataEntry, +) -> Result<(), Error> { + let dependents = &pde.current_dependents; + let me = &pde.manifest.id; + for (dependent_id, dependency_info) in dependents { + if dependency_info.pointers.iter().any(|ptr| match ptr { + // dependency id matches the package being uninstalled + PackagePointerSpec::TorAddress(ptr) => &ptr.package_id == me && dependent_id != me, + PackagePointerSpec::LanAddress(ptr) => &ptr.package_id == me && dependent_id != me, + // we never need to retarget these + PackagePointerSpec::TorKey(_) => false, + PackagePointerSpec::Config(_) => false, + }) { + crate::config::configure( + ctx, + &mut tx, + dependent_id, + None, + &None, + false, + &mut BTreeMap::new(), + &mut BTreeMap::new(), + ) + .await?; + } + } + Ok(()) +} diff --git a/appmgr/src/install/cleanup.rs b/appmgr/src/install/cleanup.rs index 8e6264e2a..1633d3c36 100644 --- a/appmgr/src/install/cleanup.rs +++ b/appmgr/src/install/cleanup.rs @@ -2,12 +2,13 @@ use std::collections::{BTreeMap, HashMap}; use bollard::image::ListImagesOptions; use color_eyre::eyre::eyre; -use patch_db::{DbHandle, PatchDbHandle}; +use patch_db::{DbHandle, LockType, PatchDbHandle}; use tracing::instrument; use super::{PKG_ARCHIVE_DIR, PKG_DOCKER_DIR}; use crate::context::RpcContext; use crate::db::model::{CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry}; +use crate::dependencies::reconfigure_dependents_with_live_pointers; use crate::error::ErrorCollection; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::util::{Apply, Version}; @@ -235,6 +236,10 @@ pub async fn uninstall( id: &PackageId, ) -> Result<(), Error> { let mut tx = db.begin().await?; + crate::db::DatabaseModel::new() + .package_data() + .lock(&mut tx, LockType::Write) + .await?; let entry = crate::db::DatabaseModel::new() .package_data() .idx_model(id) @@ -249,10 +254,15 @@ pub async fn uninstall( ) })?; cleanup(ctx, &entry.manifest.id, &entry.manifest.version).await?; + crate::db::DatabaseModel::new() .package_data() .remove(&mut tx, id) .await?; + + // once we have removed the package entry, we can change all the dependent pointers to null + reconfigure_dependents_with_live_pointers(ctx, &mut tx, &entry).await?; + remove_from_current_dependents_lists( &mut tx, &entry.manifest.id, diff --git a/appmgr/src/install/mod.rs b/appmgr/src/install/mod.rs index 18e521978..52d077f91 100644 --- a/appmgr/src/install/mod.rs +++ b/appmgr/src/install/mod.rs @@ -32,8 +32,8 @@ use crate::db::model::{ }; use crate::db::util::WithRevision; use crate::dependencies::{ - add_dependent_to_current_dependents_lists, break_all_dependents_transitive, BreakageRes, - DependencyError, DependencyErrors, + add_dependent_to_current_dependents_lists, break_all_dependents_transitive, + reconfigure_dependents_with_live_pointers, BreakageRes, DependencyError, DependencyErrors, }; use crate::install::cleanup::{cleanup, update_dependency_errors_of_dependents}; use crate::install::progress::{InstallProgress, InstallProgressTracker}; @@ -899,6 +899,7 @@ pub async fn install_s9pk( current_dependencies: current_dependencies.clone(), interface_addresses, }; + let prev = std::mem::replace( &mut *pde, PackageDataEntry::Installed { @@ -1048,6 +1049,10 @@ pub async fn install_s9pk( .remove(&mut tx, pkg_id) .await?; + if let Some(installed) = pde.installed() { + reconfigure_dependents_with_live_pointers(ctx, &mut tx, installed).await?; + } + sql_tx.commit().await?; tx.commit(None).await?;