mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
feat: Change all the dependency errors at once (#2427)
* feat: Change all the dependency errors at once * remove deprecated dependency-errors field * set pointers to [] by default * chore: Something about fixing the build * fix migration --------- Co-authored-by: Aiden McClelland <me@drbonez.dev>
This commit is contained in:
4
backend/Cargo.lock
generated
4
backend/Cargo.lock
generated
@@ -2120,9 +2120,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.17.6"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730"
|
||||
checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
|
||||
dependencies = [
|
||||
"console",
|
||||
"instant",
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::account::AccountInfo;
|
||||
use crate::core::rpc_continuations::{RequestGuid, RestHandler, RpcContinuation};
|
||||
use crate::db::model::{CurrentDependents, Database, PackageDataEntryMatchModelRef};
|
||||
use crate::db::prelude::PatchDbExt;
|
||||
use crate::dependencies::compute_dependency_config_errs;
|
||||
use crate::disk::OsPartitionInfo;
|
||||
use crate::init::init_postgres;
|
||||
use crate::install::cleanup::{cleanup_failed, uninstall};
|
||||
@@ -155,8 +156,7 @@ impl RpcContext {
|
||||
.unwrap_or(SocketAddr::from(([127, 0, 0, 1], 9051))),
|
||||
tor_proxy,
|
||||
base.dns_bind
|
||||
.as_ref()
|
||||
.map(|v| v.as_slice())
|
||||
.as_deref()
|
||||
.unwrap_or(&[SocketAddr::from(([127, 0, 0, 1], 53))]),
|
||||
SslManager::new(&account)?,
|
||||
&account.hostname,
|
||||
@@ -217,11 +217,8 @@ impl RpcContext {
|
||||
});
|
||||
|
||||
let res = Self(seed.clone());
|
||||
res.cleanup().await?;
|
||||
res.cleanup_and_initialize().await?;
|
||||
tracing::info!("Cleaned up transient states");
|
||||
let peeked = res.db.peek().await?;
|
||||
res.managers.init(res.clone(), peeked).await?;
|
||||
tracing::info!("Initialized Package Managers");
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -236,7 +233,7 @@ impl RpcContext {
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
pub async fn cleanup(&self) -> Result<(), Error> {
|
||||
pub async fn cleanup_and_initialize(&self) -> Result<(), Error> {
|
||||
self.db
|
||||
.mutate(|f| {
|
||||
let mut current_dependents = f
|
||||
@@ -278,9 +275,10 @@ impl RpcContext {
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
|
||||
let peek = self.db.peek().await?;
|
||||
|
||||
for (package_id, package) in peek.as_package_data().as_entries()?.into_iter() {
|
||||
let package = package.clone();
|
||||
let action = match package.as_match() {
|
||||
PackageDataEntryMatchModelRef::Installing(_)
|
||||
| PackageDataEntryMatchModelRef::Restoring(_)
|
||||
@@ -298,7 +296,7 @@ impl RpcContext {
|
||||
&self.datadir,
|
||||
&package_id,
|
||||
&version,
|
||||
&volume_id,
|
||||
volume_id,
|
||||
))
|
||||
.with_kind(ErrorKind::Filesystem)?;
|
||||
if tokio::fs::metadata(&tmp_path).await.is_ok() {
|
||||
@@ -314,7 +312,8 @@ impl RpcContext {
|
||||
tracing::debug!("{:?}", e);
|
||||
}
|
||||
}
|
||||
self.db
|
||||
let peek = self
|
||||
.db
|
||||
.mutate(|v| {
|
||||
for (_, pde) in v.as_package_data_mut().as_entries_mut()? {
|
||||
let status = pde
|
||||
@@ -329,9 +328,49 @@ impl RpcContext {
|
||||
MainStatus::Stopped
|
||||
})?;
|
||||
}
|
||||
Ok(v.clone())
|
||||
})
|
||||
.await?;
|
||||
self.managers.init(self.clone(), peek.clone()).await?;
|
||||
tracing::info!("Initialized Package Managers");
|
||||
|
||||
let mut all_dependency_config_errs = BTreeMap::new();
|
||||
for (package_id, package) in peek.as_package_data().as_entries()?.into_iter() {
|
||||
let package = package.clone();
|
||||
if let Some(current_dependencies) = package
|
||||
.as_installed()
|
||||
.and_then(|x| x.as_current_dependencies().de().ok())
|
||||
{
|
||||
let manifest = package.as_manifest().de()?;
|
||||
all_dependency_config_errs.insert(
|
||||
package_id.clone(),
|
||||
compute_dependency_config_errs(
|
||||
self,
|
||||
&peek,
|
||||
&manifest,
|
||||
¤t_dependencies,
|
||||
&Default::default(),
|
||||
)
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
}
|
||||
self.db
|
||||
.mutate(|v| {
|
||||
for (package_id, errs) in all_dependency_config_errs {
|
||||
if let Some(config_errors) = v
|
||||
.as_package_data_mut()
|
||||
.as_idx_mut(&package_id)
|
||||
.and_then(|pde| pde.as_installed_mut())
|
||||
.map(|i| i.as_status_mut().as_dependency_config_errors_mut())
|
||||
{
|
||||
config_errors.ser(&errs)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -389,7 +428,7 @@ impl RpcContext {
|
||||
}
|
||||
impl AsRef<Jwk> for RpcContext {
|
||||
fn as_ref(&self) -> &Jwk {
|
||||
&*CURRENT_SECRET
|
||||
&CURRENT_SECRET
|
||||
}
|
||||
}
|
||||
impl Context for RpcContext {}
|
||||
@@ -403,7 +442,7 @@ impl Deref for RpcContext {
|
||||
tracing_error::SpanTrace::capture()
|
||||
);
|
||||
}
|
||||
&*self.0
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl Drop for RpcContext {
|
||||
|
||||
@@ -480,6 +480,7 @@ pub struct StaticDependencyInfo {
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[model = "Model<Self>"]
|
||||
pub struct CurrentDependencyInfo {
|
||||
#[serde(default)]
|
||||
pub pointers: BTreeSet<PackagePointerSpec>,
|
||||
pub health_checks: BTreeSet<HealthCheckId>,
|
||||
}
|
||||
|
||||
@@ -200,11 +200,6 @@ pub async fn init(cfg: &RpcContextConfig) -> Result<InitResult, Error> {
|
||||
|
||||
let account = AccountInfo::load(&secret_store).await?;
|
||||
let db = cfg.db(&account).await?;
|
||||
db.mutate(|d| {
|
||||
let model = d.de()?;
|
||||
d.ser(&model)
|
||||
})
|
||||
.await?;
|
||||
tracing::info!("Opened PatchDB");
|
||||
let peek = db.peek().await?;
|
||||
let mut server_info = peek.as_server_info().de()?;
|
||||
@@ -375,6 +370,12 @@ pub async fn init(cfg: &RpcContextConfig) -> Result<InitResult, Error> {
|
||||
|
||||
crate::version::init(&db, &secret_store).await?;
|
||||
|
||||
db.mutate(|d| {
|
||||
let model = d.de()?;
|
||||
d.ser(&model)
|
||||
})
|
||||
.await?;
|
||||
|
||||
if should_rebuild {
|
||||
match tokio::fs::remove_file(SYSTEM_REBUILD_PATH).await {
|
||||
Ok(()) => Ok(()),
|
||||
|
||||
@@ -1105,7 +1105,6 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin + Send + Sync>(
|
||||
status: Status {
|
||||
configured: manifest.config.is_none(),
|
||||
main: MainStatus::Stopped,
|
||||
dependency_errors: Default::default(),
|
||||
dependency_config_errors: compute_dependency_config_errs(
|
||||
&ctx,
|
||||
&peek,
|
||||
|
||||
@@ -16,8 +16,6 @@ pub struct Status {
|
||||
pub configured: bool,
|
||||
pub main: MainStatus,
|
||||
#[serde(default)]
|
||||
pub dependency_errors: BTreeMap<(), ()>, // TODO: remove
|
||||
#[serde(default)]
|
||||
pub dependency_config_errors: DependencyConfigErrors,
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@ mod v0_3_4_1;
|
||||
mod v0_3_4_2;
|
||||
mod v0_3_4_3;
|
||||
mod v0_3_4_4;
|
||||
mod v0_3_5;
|
||||
|
||||
pub type Current = v0_3_4_4::Version;
|
||||
pub type Current = v0_3_5::Version;
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||
#[serde(untagged)]
|
||||
@@ -24,6 +25,7 @@ enum Version {
|
||||
V0_3_4_2(Wrapper<v0_3_4_2::Version>),
|
||||
V0_3_4_3(Wrapper<v0_3_4_3::Version>),
|
||||
V0_3_4_4(Wrapper<v0_3_4_4::Version>),
|
||||
V0_3_5(Wrapper<v0_3_5::Version>),
|
||||
Other(emver::Version),
|
||||
}
|
||||
|
||||
@@ -44,6 +46,7 @@ impl Version {
|
||||
Version::V0_3_4_2(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_4_3(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_4_4(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_5(Wrapper(x)) => x.semver(),
|
||||
Version::Other(x) => x.clone(),
|
||||
}
|
||||
}
|
||||
@@ -168,6 +171,7 @@ pub async fn init(db: &PatchDb, secrets: &PgPool) -> Result<(), Error> {
|
||||
Version::V0_3_4_2(v) => v.0.migrate_to(&Current::new(), db.clone(), secrets).await?,
|
||||
Version::V0_3_4_3(v) => v.0.migrate_to(&Current::new(), db.clone(), secrets).await?,
|
||||
Version::V0_3_4_4(v) => v.0.migrate_to(&Current::new(), db.clone(), secrets).await?,
|
||||
Version::V0_3_5(v) => v.0.migrate_to(&Current::new(), db.clone(), secrets).await?,
|
||||
Version::Other(_) => {
|
||||
return Err(Error::new(
|
||||
eyre!("Cannot downgrade"),
|
||||
|
||||
98
backend/src/version/v0_3_5.rs
Normal file
98
backend/src/version/v0_3_5.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use emver::VersionRange;
|
||||
use models::DataUrl;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use super::v0_3_4::V0_3_0_COMPAT;
|
||||
use super::{v0_3_4_4, VersionT};
|
||||
use crate::prelude::*;
|
||||
|
||||
const V0_3_5: emver::Version = emver::Version::new(0, 3, 5, 0);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_4_4::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_5
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&V0_3_0_COMPAT
|
||||
}
|
||||
async fn up(&self, db: PatchDb, _secrets: &PgPool) -> Result<(), Error> {
|
||||
let peek = db.peek().await?;
|
||||
let mut url_replacements = BTreeMap::new();
|
||||
for (_, pde) in peek.as_package_data().as_entries()? {
|
||||
for (dependency, info) in pde
|
||||
.as_installed()
|
||||
.map(|i| i.as_dependency_info().as_entries())
|
||||
.transpose()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
if !url_replacements.contains_key(&dependency) {
|
||||
url_replacements.insert(
|
||||
dependency,
|
||||
DataUrl::from_path(
|
||||
<&Value>::from(info.as_icon())
|
||||
.as_str()
|
||||
.and_then(|i| i.strip_prefix("/public/package-data/"))
|
||||
.map(|path| {
|
||||
Path::new("/embassy-data/package-data/public").join(path)
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.await
|
||||
.unwrap_or_else(|_| {
|
||||
DataUrl::from_slice(
|
||||
"image/png",
|
||||
include_bytes!("../install/package-icon.png"),
|
||||
)
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
db.mutate(|v| {
|
||||
for (_, pde) in v.as_package_data_mut().as_entries_mut()? {
|
||||
for (dependency, info) in pde
|
||||
.as_installed_mut()
|
||||
.map(|i| i.as_dependency_info_mut().as_entries_mut())
|
||||
.transpose()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
if let Some(url) = url_replacements.get(&dependency) {
|
||||
info.as_icon_mut().ser(url)?;
|
||||
}
|
||||
let manifest = <&mut Value>::from(&mut *info)
|
||||
.as_object_mut()
|
||||
.and_then(|o| o.remove("manifest"));
|
||||
if let Some(title) = manifest
|
||||
.as_ref()
|
||||
.and_then(|m| m.as_object())
|
||||
.and_then(|m| m.get("title"))
|
||||
.and_then(|t| t.as_str())
|
||||
.map(|s| s.to_owned())
|
||||
{
|
||||
info.as_title_mut().ser(&title)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn down(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ export class AppShowPage {
|
||||
return {
|
||||
id: depId,
|
||||
version: pkgInstalled.manifest.dependencies[depId].version, // do we want this version range?
|
||||
title: depInfo?.manifest?.title || depId,
|
||||
title: depInfo?.title || depId,
|
||||
icon: depInfo?.icon || '',
|
||||
errorText: errorText
|
||||
? `${errorText}. ${pkgInstalled.manifest.title} will not work as expected.`
|
||||
|
||||
@@ -1958,7 +1958,7 @@ export module Mock {
|
||||
},
|
||||
'dependency-info': {
|
||||
bitcoind: {
|
||||
manifest: Mock.MockManifestBitcoind,
|
||||
title: Mock.MockManifestBitcoind.title,
|
||||
icon: 'assets/img/service-icons/bitcoind.svg',
|
||||
},
|
||||
},
|
||||
@@ -2012,11 +2012,11 @@ export module Mock {
|
||||
},
|
||||
'dependency-info': {
|
||||
bitcoind: {
|
||||
manifest: Mock.MockManifestBitcoind,
|
||||
title: Mock.MockManifestBitcoind.title,
|
||||
icon: 'assets/img/service-icons/bitcoind.svg',
|
||||
},
|
||||
'btc-rpc-proxy': {
|
||||
manifest: Mock.MockManifestBitcoinProxy,
|
||||
title: Mock.MockManifestBitcoinProxy.title,
|
||||
icon: 'assets/img/service-icons/btc-rpc-proxy.png',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -664,15 +664,11 @@ export const mockPatchData: DataModel = {
|
||||
},
|
||||
'dependency-info': {
|
||||
bitcoind: {
|
||||
manifest: {
|
||||
title: 'Bitcoin Core',
|
||||
} as Manifest,
|
||||
title: 'Bitcoin Core',
|
||||
icon: 'assets/img/service-icons/bitcoind.svg',
|
||||
},
|
||||
'btc-rpc-proxy': {
|
||||
manifest: {
|
||||
title: 'Bitcoin Proxy',
|
||||
} as Manifest,
|
||||
title: 'Bitcoin Proxy',
|
||||
icon: 'assets/img/service-icons/btc-rpc-proxy.png',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -132,7 +132,7 @@ export interface InstalledPackageDataEntry {
|
||||
'current-dependencies': { [id: string]: CurrentDependencyInfo }
|
||||
'dependency-info': {
|
||||
[id: string]: {
|
||||
manifest: Manifest
|
||||
title: string
|
||||
icon: Url
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user