mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
take marketplace as an argument from the frontend
This commit is contained in:
committed by
Aiden McClelland
parent
9d3f0a9d2b
commit
5c7c23459d
@@ -18,7 +18,6 @@ use super::PackageBackupReport;
|
|||||||
use crate::auth::check_password_against_db;
|
use crate::auth::check_password_against_db;
|
||||||
use crate::backup::{BackupReport, ServerBackupReport};
|
use crate::backup::{BackupReport, ServerBackupReport};
|
||||||
use crate::context::RpcContext;
|
use crate::context::RpcContext;
|
||||||
use crate::db::model::ServerStatus;
|
|
||||||
use crate::db::util::WithRevision;
|
use crate::db::util::WithRevision;
|
||||||
use crate::disk::mount::backup::BackupMountGuard;
|
use crate::disk::mount::backup::BackupMountGuard;
|
||||||
use crate::disk::mount::guard::TmpMountGuard;
|
use crate::disk::mount::guard::TmpMountGuard;
|
||||||
@@ -134,7 +133,10 @@ pub async fn backup_all(
|
|||||||
let revision = assure_backing_up(&mut db).await?;
|
let revision = assure_backing_up(&mut db).await?;
|
||||||
tokio::task::spawn(async move {
|
tokio::task::spawn(async move {
|
||||||
let backup_res = perform_backup(&ctx, &mut db, backup_guard).await;
|
let backup_res = perform_backup(&ctx, &mut db, backup_guard).await;
|
||||||
let status_model = crate::db::DatabaseModel::new().server_info().status();
|
let status_model = crate::db::DatabaseModel::new()
|
||||||
|
.server_info()
|
||||||
|
.status_info()
|
||||||
|
.backing_up();
|
||||||
status_model
|
status_model
|
||||||
.clone()
|
.clone()
|
||||||
.lock(&mut db, LockType::Write)
|
.lock(&mut db, LockType::Write)
|
||||||
@@ -203,7 +205,7 @@ pub async fn backup_all(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
status_model
|
status_model
|
||||||
.put(&mut db, &ServerStatus::Running)
|
.put(&mut db, &false)
|
||||||
.await
|
.await
|
||||||
.expect("failed to change server status");
|
.expect("failed to change server status");
|
||||||
});
|
});
|
||||||
@@ -216,33 +218,21 @@ pub async fn backup_all(
|
|||||||
#[instrument(skip(db))]
|
#[instrument(skip(db))]
|
||||||
async fn assure_backing_up(db: &mut PatchDbHandle) -> Result<Option<Arc<Revision>>, Error> {
|
async fn assure_backing_up(db: &mut PatchDbHandle) -> Result<Option<Arc<Revision>>, Error> {
|
||||||
let mut tx = db.begin().await?;
|
let mut tx = db.begin().await?;
|
||||||
let mut info = crate::db::DatabaseModel::new()
|
let mut backing_up = crate::db::DatabaseModel::new()
|
||||||
.server_info()
|
.server_info()
|
||||||
|
.status_info()
|
||||||
|
.backing_up()
|
||||||
.get_mut(&mut tx)
|
.get_mut(&mut tx)
|
||||||
.await?;
|
.await?;
|
||||||
match &info.status {
|
|
||||||
ServerStatus::Updating => {
|
if *backing_up {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
eyre!("Server is updating!"),
|
eyre!("Server is already backing up!"),
|
||||||
crate::ErrorKind::InvalidRequest,
|
crate::ErrorKind::InvalidRequest,
|
||||||
))
|
));
|
||||||
}
|
|
||||||
ServerStatus::Updated => {
|
|
||||||
return Err(Error::new(
|
|
||||||
eyre!("Server is updated and needs to be reset"),
|
|
||||||
crate::ErrorKind::InvalidRequest,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
ServerStatus::BackingUp => {
|
|
||||||
return Err(Error::new(
|
|
||||||
eyre!("Server is already backing up!"),
|
|
||||||
crate::ErrorKind::InvalidRequest,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
ServerStatus::Running => (),
|
|
||||||
}
|
}
|
||||||
info.status = ServerStatus::BackingUp;
|
*backing_up = true;
|
||||||
info.save(&mut tx).await?;
|
backing_up.save(&mut tx).await?;
|
||||||
Ok(tx.commit(None).await?)
|
Ok(tx.commit(None).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ async fn restore_package<'a>(
|
|||||||
Ok((
|
Ok((
|
||||||
progress.clone(),
|
progress.clone(),
|
||||||
async move {
|
async move {
|
||||||
download_install_s9pk(&ctx, &manifest, progress, file).await?;
|
download_install_s9pk(&ctx, &manifest, None, progress, file).await?;
|
||||||
|
|
||||||
guard.unmount().await?;
|
guard.unmount().await?;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use tracing::instrument;
|
|||||||
|
|
||||||
use crate::core::rpc_continuations::{RequestGuid, RpcContinuation};
|
use crate::core::rpc_continuations::{RequestGuid, RpcContinuation};
|
||||||
use crate::db::model::{Database, InstalledPackageDataEntry, PackageDataEntry};
|
use crate::db::model::{Database, InstalledPackageDataEntry, PackageDataEntry};
|
||||||
use crate::hostname::{derive_hostname, derive_id, get_hostname, get_id, get_product_key};
|
use crate::hostname::{derive_hostname, derive_id, get_product_key};
|
||||||
use crate::install::cleanup::{cleanup_failed, uninstall};
|
use crate::install::cleanup::{cleanup_failed, uninstall};
|
||||||
use crate::manager::ManagerMap;
|
use crate::manager::ManagerMap;
|
||||||
use crate::middleware::auth::HashSessionToken;
|
use crate::middleware::auth::HashSessionToken;
|
||||||
@@ -230,31 +230,6 @@ impl RpcContext {
|
|||||||
tracing::info!("Initialized Package Managers");
|
tracing::info!("Initialized Package Managers");
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
#[instrument(skip(self))]
|
|
||||||
pub async fn package_registry_url(&self) -> Result<Url, Error> {
|
|
||||||
Ok(
|
|
||||||
if let Some(market) = crate::db::DatabaseModel::new()
|
|
||||||
.server_info()
|
|
||||||
.package_marketplace()
|
|
||||||
.get(&mut self.db.handle(), false)
|
|
||||||
.await?
|
|
||||||
.to_owned()
|
|
||||||
{
|
|
||||||
market
|
|
||||||
} else {
|
|
||||||
self.eos_registry_url().await?
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
#[instrument(skip(self))]
|
|
||||||
pub async fn eos_registry_url(&self) -> Result<Url, Error> {
|
|
||||||
Ok(crate::db::DatabaseModel::new()
|
|
||||||
.server_info()
|
|
||||||
.eos_marketplace()
|
|
||||||
.get(&mut self.db.handle(), false)
|
|
||||||
.await?
|
|
||||||
.to_owned())
|
|
||||||
}
|
|
||||||
#[instrument(skip(self, db))]
|
#[instrument(skip(self, db))]
|
||||||
pub async fn set_nginx_conf<Db: DbHandle>(&self, db: &mut Db) -> Result<(), Error> {
|
pub async fn set_nginx_conf<Db: DbHandle>(&self, db: &mut Db) -> Result<(), Error> {
|
||||||
tokio::fs::write("/etc/nginx/sites-available/default", {
|
tokio::fs::write("/etc/nginx/sites-available/default", {
|
||||||
@@ -266,11 +241,6 @@ impl RpcContext {
|
|||||||
include_str!("../nginx/main-ui.conf.template"),
|
include_str!("../nginx/main-ui.conf.template"),
|
||||||
lan_hostname = info.lan_address.host_str().unwrap(),
|
lan_hostname = info.lan_address.host_str().unwrap(),
|
||||||
tor_hostname = info.tor_address.host_str().unwrap(),
|
tor_hostname = info.tor_address.host_str().unwrap(),
|
||||||
eos_marketplace = info.eos_marketplace,
|
|
||||||
package_marketplace = info
|
|
||||||
.package_marketplace
|
|
||||||
.as_ref()
|
|
||||||
.unwrap_or(&info.eos_marketplace),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use tracing::instrument;
|
|||||||
use url::Host;
|
use url::Host;
|
||||||
|
|
||||||
use crate::db::model::Database;
|
use crate::db::model::Database;
|
||||||
use crate::hostname::{derive_hostname, derive_id, get_hostname, get_id, get_product_key};
|
use crate::hostname::{derive_hostname, derive_id, get_product_key};
|
||||||
use crate::net::tor::os_key;
|
use crate::net::tor::os_key;
|
||||||
use crate::setup::{password_hash, RecoveryStatus};
|
use crate::setup::{password_hash, RecoveryStatus};
|
||||||
use crate::util::io::from_toml_async_reader;
|
use crate::util::io::from_toml_async_reader;
|
||||||
|
|||||||
@@ -50,12 +50,11 @@ impl Database {
|
|||||||
tor_address: format!("http://{}", tor_key.public().get_onion_address())
|
tor_address: format!("http://{}", tor_key.public().get_onion_address())
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
status: ServerStatus::Running {},
|
status_info: ServerStatus {
|
||||||
#[cfg(not(feature = "beta"))]
|
backing_up: false,
|
||||||
eos_marketplace: "https://marketplace.start9.com".parse().unwrap(),
|
updated: false,
|
||||||
#[cfg(feature = "beta")]
|
update_progress: None,
|
||||||
eos_marketplace: "https://beta-registry-0-3.start9labs.com".parse().unwrap(),
|
},
|
||||||
package_marketplace: None,
|
|
||||||
wifi: WifiInfo {
|
wifi: WifiInfo {
|
||||||
ssids: Vec::new(),
|
ssids: Vec::new(),
|
||||||
connected: None,
|
connected: None,
|
||||||
@@ -67,7 +66,6 @@ impl Database {
|
|||||||
clearnet: Vec::new(),
|
clearnet: Vec::new(),
|
||||||
},
|
},
|
||||||
share_stats: false,
|
share_stats: false,
|
||||||
update_progress: None,
|
|
||||||
password_hash,
|
password_hash,
|
||||||
},
|
},
|
||||||
package_data: AllPackageData::default(),
|
package_data: AllPackageData::default(),
|
||||||
@@ -93,25 +91,23 @@ pub struct ServerInfo {
|
|||||||
pub eos_version_compat: VersionRange,
|
pub eos_version_compat: VersionRange,
|
||||||
pub lan_address: Url,
|
pub lan_address: Url,
|
||||||
pub tor_address: Url,
|
pub tor_address: Url,
|
||||||
pub status: ServerStatus,
|
#[model]
|
||||||
pub eos_marketplace: Url,
|
#[serde(default)]
|
||||||
pub package_marketplace: Option<Url>, // None implies use eos_marketplace
|
pub status_info: ServerStatus,
|
||||||
pub wifi: WifiInfo,
|
pub wifi: WifiInfo,
|
||||||
pub unread_notification_count: u64,
|
pub unread_notification_count: u64,
|
||||||
pub connection_addresses: ConnectionAddresses,
|
pub connection_addresses: ConnectionAddresses,
|
||||||
pub share_stats: bool,
|
pub share_stats: bool,
|
||||||
#[model]
|
|
||||||
pub update_progress: Option<UpdateProgress>,
|
|
||||||
pub password_hash: String,
|
pub password_hash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize, HasModel)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub enum ServerStatus {
|
pub struct ServerStatus {
|
||||||
Running,
|
pub backing_up: bool,
|
||||||
Updating,
|
pub updated: bool,
|
||||||
Updated,
|
#[model]
|
||||||
BackingUp,
|
pub update_progress: Option<UpdateProgress>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, HasModel)]
|
#[derive(Debug, Deserialize, Serialize, HasModel)]
|
||||||
@@ -257,6 +253,9 @@ impl PackageDataEntryModel {
|
|||||||
pub struct InstalledPackageDataEntry {
|
pub struct InstalledPackageDataEntry {
|
||||||
#[model]
|
#[model]
|
||||||
pub status: Status,
|
pub status: Status,
|
||||||
|
pub marketplace_url: Option<Url>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub developer_key: ed25519_dalek::PublicKey,
|
||||||
#[model]
|
#[model]
|
||||||
pub manifest: Manifest,
|
pub manifest: Manifest,
|
||||||
pub last_backup: Option<DateTime<Utc>>,
|
pub last_backup: Option<DateTime<Utc>>,
|
||||||
|
|||||||
@@ -93,15 +93,11 @@ pub async fn init(cfg: &RpcContextConfig, product_key: &str) -> Result<(), Error
|
|||||||
.server_info()
|
.server_info()
|
||||||
.get_mut(&mut handle)
|
.get_mut(&mut handle)
|
||||||
.await?;
|
.await?;
|
||||||
match info.status {
|
info.status_info = ServerStatus {
|
||||||
ServerStatus::Running | ServerStatus::Updated | ServerStatus::BackingUp => {
|
backing_up: false,
|
||||||
info.status = ServerStatus::Running;
|
updated: false,
|
||||||
}
|
update_progress: None,
|
||||||
ServerStatus::Updating => {
|
};
|
||||||
info.update_progress = None;
|
|
||||||
info.status = ServerStatus::Running;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info.save(&mut handle).await?;
|
info.save(&mut handle).await?;
|
||||||
|
|
||||||
crate::version::init(&mut handle).await?;
|
crate::version::init(&mut handle).await?;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use http::header::CONTENT_LENGTH;
|
|||||||
use http::{Request, Response, StatusCode};
|
use http::{Request, Response, StatusCode};
|
||||||
use hyper::Body;
|
use hyper::Body;
|
||||||
use patch_db::{DbHandle, LockType};
|
use patch_db::{DbHandle, LockType};
|
||||||
|
use reqwest::Url;
|
||||||
use rpc_toolkit::yajrc::RpcError;
|
use rpc_toolkit::yajrc::RpcError;
|
||||||
use rpc_toolkit::{command, Context};
|
use rpc_toolkit::{command, Context};
|
||||||
use tokio::fs::{File, OpenOptions};
|
use tokio::fs::{File, OpenOptions};
|
||||||
@@ -85,18 +86,23 @@ pub async fn list(#[context] ctx: RpcContext) -> Result<Vec<(PackageId, Version)
|
|||||||
pub async fn install(
|
pub async fn install(
|
||||||
#[context] ctx: RpcContext,
|
#[context] ctx: RpcContext,
|
||||||
#[arg] id: String,
|
#[arg] id: String,
|
||||||
#[arg(rename = "version-spec")] version_spec: Option<String>,
|
#[arg(short = "m", long = "marketplace-url", rename = "marketplace-url")]
|
||||||
|
marketplace_url: Option<Url>,
|
||||||
|
#[arg(short = "v", long = "version-spec", rename = "version-spec")] version_spec: Option<
|
||||||
|
String,
|
||||||
|
>,
|
||||||
) -> Result<WithRevision<()>, Error> {
|
) -> Result<WithRevision<()>, Error> {
|
||||||
let version_str = match &version_spec {
|
let version_str = match &version_spec {
|
||||||
None => "*",
|
None => "*",
|
||||||
Some(v) => &*v,
|
Some(v) => &*v,
|
||||||
};
|
};
|
||||||
let version: VersionRange = version_str.parse()?;
|
let version: VersionRange = version_str.parse()?;
|
||||||
let reg_url = ctx.package_registry_url().await?;
|
let marketplace_url =
|
||||||
|
marketplace_url.unwrap_or_else(|| crate::DEFAULT_MARKETPLACE.parse().unwrap());
|
||||||
let (man_res, s9pk) = tokio::try_join!(
|
let (man_res, s9pk) = tokio::try_join!(
|
||||||
reqwest::get(format!(
|
reqwest::get(format!(
|
||||||
"{}/package/manifest/{}?spec={}&eos-version-compat={}&arch={}",
|
"{}/package/manifest/{}?spec={}&eos-version-compat={}&arch={}",
|
||||||
reg_url,
|
marketplace_url,
|
||||||
id,
|
id,
|
||||||
version,
|
version,
|
||||||
Current::new().compat(),
|
Current::new().compat(),
|
||||||
@@ -104,7 +110,7 @@ pub async fn install(
|
|||||||
)),
|
)),
|
||||||
reqwest::get(format!(
|
reqwest::get(format!(
|
||||||
"{}/package/{}.s9pk?spec={}&eos-version-compat={}&arch={}",
|
"{}/package/{}.s9pk?spec={}&eos-version-compat={}&arch={}",
|
||||||
reg_url,
|
marketplace_url,
|
||||||
id,
|
id,
|
||||||
version,
|
version,
|
||||||
Current::new().compat(),
|
Current::new().compat(),
|
||||||
@@ -112,7 +118,15 @@ pub async fn install(
|
|||||||
))
|
))
|
||||||
)
|
)
|
||||||
.with_kind(crate::ErrorKind::Registry)?;
|
.with_kind(crate::ErrorKind::Registry)?;
|
||||||
let man: Manifest = man_res.json().await.with_kind(crate::ErrorKind::Registry)?;
|
let man: Manifest = man_res
|
||||||
|
.error_for_status()
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?;
|
||||||
|
let s9pk = s9pk
|
||||||
|
.error_for_status()
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?;
|
||||||
|
|
||||||
if man.id.as_str() != id || !man.version.satisfies(&version) {
|
if man.id.as_str() != id || !man.version.satisfies(&version) {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@@ -166,6 +180,7 @@ pub async fn install(
|
|||||||
if let Err(e) = download_install_s9pk(
|
if let Err(e) = download_install_s9pk(
|
||||||
&ctx,
|
&ctx,
|
||||||
&man,
|
&man,
|
||||||
|
Some(marketplace_url),
|
||||||
InstallProgress::new(s9pk.content_length()),
|
InstallProgress::new(s9pk.content_length()),
|
||||||
tokio_util::io::StreamReader::new(s9pk.bytes_stream().map_err(|e| {
|
tokio_util::io::StreamReader::new(s9pk.bytes_stream().map_err(|e| {
|
||||||
std::io::Error::new(
|
std::io::Error::new(
|
||||||
@@ -286,6 +301,7 @@ pub async fn sideload(
|
|||||||
download_install_s9pk(
|
download_install_s9pk(
|
||||||
&new_ctx,
|
&new_ctx,
|
||||||
&manifest,
|
&manifest,
|
||||||
|
None,
|
||||||
progress,
|
progress,
|
||||||
tokio_util::io::StreamReader::new(req.into_body().map_err(|e| {
|
tokio_util::io::StreamReader::new(req.into_body().map_err(|e| {
|
||||||
std::io::Error::new(
|
std::io::Error::new(
|
||||||
@@ -330,6 +346,7 @@ pub async fn sideload(
|
|||||||
async fn cli_install(
|
async fn cli_install(
|
||||||
ctx: CliContext,
|
ctx: CliContext,
|
||||||
target: String,
|
target: String,
|
||||||
|
marketplace_url: Option<Url>,
|
||||||
version_spec: Option<String>,
|
version_spec: Option<String>,
|
||||||
) -> Result<(), RpcError> {
|
) -> Result<(), RpcError> {
|
||||||
if target.ends_with(".s9pk") {
|
if target.ends_with(".s9pk") {
|
||||||
@@ -373,7 +390,9 @@ async fn cli_install(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let params = match (target.split_once("@"), version_spec) {
|
let params = match (target.split_once("@"), version_spec) {
|
||||||
(Some((pkg, v)), None) => serde_json::json!({ "id": pkg, "version-spec": v }),
|
(Some((pkg, v)), None) => {
|
||||||
|
serde_json::json!({ "id": pkg, "marketplace-url": marketplace_url, "version-spec": v })
|
||||||
|
}
|
||||||
(Some(_), Some(_)) => {
|
(Some(_), Some(_)) => {
|
||||||
return Err(crate::Error::new(
|
return Err(crate::Error::new(
|
||||||
eyre!("Invalid package id {}", target),
|
eyre!("Invalid package id {}", target),
|
||||||
@@ -381,8 +400,10 @@ async fn cli_install(
|
|||||||
)
|
)
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
(None, Some(v)) => serde_json::json!({ "id": target, "version-spec": v }),
|
(None, Some(v)) => {
|
||||||
(None, None) => serde_json::json!({ "id": target }),
|
serde_json::json!({ "id": target, "marketplace-url": marketplace_url, "version-spec": v })
|
||||||
|
}
|
||||||
|
(None, None) => serde_json::json!({ "id": target, "marketplace-url": marketplace_url }),
|
||||||
};
|
};
|
||||||
tracing::debug!("calling package.install");
|
tracing::debug!("calling package.install");
|
||||||
rpc_toolkit::command_helpers::call_remote(
|
rpc_toolkit::command_helpers::call_remote(
|
||||||
@@ -489,6 +510,7 @@ pub async fn uninstall_impl(ctx: RpcContext, id: PackageId) -> Result<WithRevisi
|
|||||||
pub async fn download_install_s9pk(
|
pub async fn download_install_s9pk(
|
||||||
ctx: &RpcContext,
|
ctx: &RpcContext,
|
||||||
temp_manifest: &Manifest,
|
temp_manifest: &Manifest,
|
||||||
|
marketplace_url: Option<Url>,
|
||||||
progress: Arc<InstallProgress>,
|
progress: Arc<InstallProgress>,
|
||||||
mut s9pk: impl AsyncRead + Unpin,
|
mut s9pk: impl AsyncRead + Unpin,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
@@ -537,7 +559,15 @@ pub async fn download_install_s9pk(
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
install_s9pk(&ctx, pkg_id, version, &mut s9pk_reader, progress).await?;
|
install_s9pk(
|
||||||
|
&ctx,
|
||||||
|
pkg_id,
|
||||||
|
version,
|
||||||
|
marketplace_url,
|
||||||
|
&mut s9pk_reader,
|
||||||
|
progress,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -563,11 +593,13 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
|
|||||||
ctx: &RpcContext,
|
ctx: &RpcContext,
|
||||||
pkg_id: &PackageId,
|
pkg_id: &PackageId,
|
||||||
version: &Version,
|
version: &Version,
|
||||||
|
marketplace_url: Option<Url>,
|
||||||
rdr: &mut S9pkReader<InstallProgressTracker<R>>,
|
rdr: &mut S9pkReader<InstallProgressTracker<R>>,
|
||||||
progress: Arc<InstallProgress>,
|
progress: Arc<InstallProgress>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
rdr.validate().await?;
|
rdr.validate().await?;
|
||||||
rdr.validated();
|
rdr.validated();
|
||||||
|
let developer_key = rdr.developer_key().clone();
|
||||||
rdr.reset().await?;
|
rdr.reset().await?;
|
||||||
let model = crate::db::DatabaseModel::new()
|
let model = crate::db::DatabaseModel::new()
|
||||||
.package_data()
|
.package_data()
|
||||||
@@ -582,78 +614,97 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
|
|||||||
|
|
||||||
tracing::info!("Install {}@{}: Fetching Dependency Info", pkg_id, version);
|
tracing::info!("Install {}@{}: Fetching Dependency Info", pkg_id, version);
|
||||||
let mut dependency_info = BTreeMap::new();
|
let mut dependency_info = BTreeMap::new();
|
||||||
let reg_url = ctx.package_registry_url().await?;
|
|
||||||
for (dep, info) in &manifest.dependencies.0 {
|
for (dep, info) in &manifest.dependencies.0 {
|
||||||
let manifest: Option<Manifest> = match reqwest::get(format!(
|
let manifest: Option<Manifest> = if let Some(local_man) = crate::db::DatabaseModel::new()
|
||||||
"{}/package/manifest/{}?spec={}&eos-version-compat={}&arch={}",
|
.package_data()
|
||||||
reg_url,
|
.idx_model(dep)
|
||||||
dep,
|
.map::<_, Manifest>(|pde| pde.manifest())
|
||||||
info.version,
|
.get(&mut ctx.db.handle(), false)
|
||||||
Current::new().compat(),
|
.await?
|
||||||
platforms::TARGET_ARCH,
|
.into_owned()
|
||||||
))
|
|
||||||
.await
|
|
||||||
.with_kind(crate::ErrorKind::Registry)?
|
|
||||||
.error_for_status()
|
|
||||||
{
|
{
|
||||||
Ok(a) => Ok(Some(
|
Some(local_man)
|
||||||
a.json()
|
} else if let Some(marketplace_url) = &marketplace_url {
|
||||||
|
match reqwest::get(format!(
|
||||||
|
"{}/package/manifest/{}?spec={}&eos-version-compat={}&arch={}",
|
||||||
|
marketplace_url,
|
||||||
|
dep,
|
||||||
|
info.version,
|
||||||
|
Current::new().compat(),
|
||||||
|
platforms::TARGET_ARCH,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?
|
||||||
|
.error_for_status()
|
||||||
|
{
|
||||||
|
Ok(a) => Ok(Some(
|
||||||
|
a.json()
|
||||||
|
.await
|
||||||
|
.with_kind(crate::ErrorKind::Deserialization)?,
|
||||||
|
)),
|
||||||
|
Err(e) if e.status() == Some(StatusCode::BAD_REQUEST) => Ok(None),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(marketplace_url) = &marketplace_url {
|
||||||
|
if let Some(manifest) = &manifest {
|
||||||
|
let dir = ctx
|
||||||
|
.datadir
|
||||||
|
.join(PKG_PUBLIC_DIR)
|
||||||
|
.join(&manifest.id)
|
||||||
|
.join(manifest.version.as_str());
|
||||||
|
let icon_path = dir.join(format!("icon.{}", manifest.assets.icon_type()));
|
||||||
|
if tokio::fs::metadata(&icon_path).await.is_err() {
|
||||||
|
tokio::fs::create_dir_all(&dir).await?;
|
||||||
|
let icon = reqwest::get(format!(
|
||||||
|
"{}/package/icon/{}?spec={}&eos-version-compat={}&arch={}",
|
||||||
|
marketplace_url,
|
||||||
|
dep,
|
||||||
|
info.version,
|
||||||
|
Current::new().compat(),
|
||||||
|
platforms::TARGET_ARCH,
|
||||||
|
))
|
||||||
.await
|
.await
|
||||||
.with_kind(crate::ErrorKind::Deserialization)?,
|
.with_kind(crate::ErrorKind::Registry)?;
|
||||||
)),
|
let mut dst = File::create(&icon_path).await?;
|
||||||
Err(e) if e.status() == Some(StatusCode::BAD_REQUEST) => Ok(None),
|
tokio::io::copy(
|
||||||
Err(e) => Err(e),
|
&mut tokio_util::io::StreamReader::new(icon.bytes_stream().map_err(|e| {
|
||||||
}
|
std::io::Error::new(
|
||||||
.with_kind(crate::ErrorKind::Registry)?;
|
if e.is_connect() {
|
||||||
if let Some(manifest) = manifest {
|
std::io::ErrorKind::ConnectionRefused
|
||||||
let dir = ctx
|
} else if e.is_timeout() {
|
||||||
.datadir
|
std::io::ErrorKind::TimedOut
|
||||||
.join(PKG_PUBLIC_DIR)
|
} else {
|
||||||
.join(&manifest.id)
|
std::io::ErrorKind::Other
|
||||||
.join(manifest.version.as_str());
|
},
|
||||||
let icon_path = dir.join(format!("icon.{}", manifest.assets.icon_type()));
|
e,
|
||||||
if tokio::fs::metadata(&icon_path).await.is_err() {
|
)
|
||||||
tokio::fs::create_dir_all(&dir).await?;
|
})),
|
||||||
let icon = reqwest::get(format!(
|
&mut dst,
|
||||||
"{}/package/icon/{}?spec={}&eos-version-compat={}&arch={}",
|
)
|
||||||
reg_url,
|
.await?;
|
||||||
dep,
|
dst.sync_all().await?;
|
||||||
info.version,
|
}
|
||||||
Current::new().compat(),
|
|
||||||
platforms::TARGET_ARCH,
|
|
||||||
))
|
|
||||||
.await
|
|
||||||
.with_kind(crate::ErrorKind::Registry)?;
|
|
||||||
let mut dst = File::create(&icon_path).await?;
|
|
||||||
tokio::io::copy(
|
|
||||||
&mut tokio_util::io::StreamReader::new(icon.bytes_stream().map_err(|e| {
|
|
||||||
std::io::Error::new(
|
|
||||||
if e.is_connect() {
|
|
||||||
std::io::ErrorKind::ConnectionRefused
|
|
||||||
} else if e.is_timeout() {
|
|
||||||
std::io::ErrorKind::TimedOut
|
|
||||||
} else {
|
|
||||||
std::io::ErrorKind::Other
|
|
||||||
},
|
|
||||||
e,
|
|
||||||
)
|
|
||||||
})),
|
|
||||||
&mut dst,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
dst.sync_all().await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependency_info.insert(
|
dependency_info.insert(
|
||||||
dep.clone(),
|
dep.clone(),
|
||||||
StaticDependencyInfo {
|
StaticDependencyInfo {
|
||||||
icon: format!(
|
icon: if let Some(manifest) = &manifest {
|
||||||
"/public/package-data/{}/{}/icon.{}",
|
format!(
|
||||||
manifest.id,
|
"/public/package-data/{}/{}/icon.{}",
|
||||||
manifest.version,
|
manifest.id,
|
||||||
manifest.assets.icon_type()
|
manifest.version,
|
||||||
),
|
manifest.assets.icon_type()
|
||||||
manifest: Some(manifest),
|
)
|
||||||
|
} else {
|
||||||
|
"/assets/img/package-icon.png".to_owned()
|
||||||
|
},
|
||||||
|
manifest,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -842,13 +893,36 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let current_dependents = {
|
let current_dependents = {
|
||||||
// search required dependencies
|
|
||||||
let mut deps = BTreeMap::new();
|
let mut deps = BTreeMap::new();
|
||||||
for package in crate::db::DatabaseModel::new()
|
for package in crate::db::DatabaseModel::new()
|
||||||
.package_data()
|
.package_data()
|
||||||
.keys(&mut tx, true)
|
.keys(&mut tx, true)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
// update dependency_info on dependents
|
||||||
|
if let Some(dep_info_model) = crate::db::DatabaseModel::new()
|
||||||
|
.package_data()
|
||||||
|
.idx_model(&package)
|
||||||
|
.expect(&mut tx)
|
||||||
|
.await?
|
||||||
|
.installed()
|
||||||
|
.and_then(|i| i.dependency_info().idx_model(pkg_id))
|
||||||
|
.check(&mut tx)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
let mut dep_info = dep_info_model.get_mut(&mut tx).await?;
|
||||||
|
*dep_info = StaticDependencyInfo {
|
||||||
|
icon: format!(
|
||||||
|
"/public/package-data/{}/{}/icon.{}",
|
||||||
|
manifest.id,
|
||||||
|
manifest.version,
|
||||||
|
manifest.assets.icon_type()
|
||||||
|
),
|
||||||
|
manifest: Some(manifest.clone()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// search required dependencies
|
||||||
if let Some(dep) = crate::db::DatabaseModel::new()
|
if let Some(dep) = crate::db::DatabaseModel::new()
|
||||||
.package_data()
|
.package_data()
|
||||||
.idx_model(&package)
|
.idx_model(&package)
|
||||||
@@ -877,6 +951,8 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
|
|||||||
main: MainStatus::Stopped,
|
main: MainStatus::Stopped,
|
||||||
dependency_errors: DependencyErrors::default(),
|
dependency_errors: DependencyErrors::default(),
|
||||||
},
|
},
|
||||||
|
marketplace_url,
|
||||||
|
developer_key,
|
||||||
manifest: manifest.clone(),
|
manifest: manifest.clone(),
|
||||||
last_backup: match &*pde {
|
last_backup: match &*pde {
|
||||||
PackageDataEntry::Updating {
|
PackageDataEntry::Updating {
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
pub const CONFIG_PATH: &'static str = "/etc/embassy/config.toml";
|
pub const CONFIG_PATH: &str = "/etc/embassy/config.yaml";
|
||||||
|
#[cfg(not(feature = "beta"))]
|
||||||
|
pub const DEFAULT_MARKETPLACE: &str = "https://marketplace.start9.com";
|
||||||
|
#[cfg(feature = "beta")]
|
||||||
|
pub const DEFAULT_MARKETPLACE: &str = "https://beta-registry-0-3.start9labs.com";
|
||||||
pub const BUFFER_SIZE: usize = 1024;
|
pub const BUFFER_SIZE: usize = 1024;
|
||||||
pub const HOST_IP: [u8; 4] = [172, 18, 0, 1];
|
pub const HOST_IP: [u8; 4] = [172, 18, 0, 1];
|
||||||
|
|
||||||
@@ -78,7 +82,6 @@ pub fn main_api() -> Result<(), RpcError> {
|
|||||||
shutdown::restart,
|
shutdown::restart,
|
||||||
shutdown::rebuild,
|
shutdown::rebuild,
|
||||||
update::update_system,
|
update::update_system,
|
||||||
marketplace::set_eos_url,
|
|
||||||
))]
|
))]
|
||||||
pub fn server() -> Result<(), RpcError> {
|
pub fn server() -> Result<(), RpcError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -98,7 +101,6 @@ pub fn server() -> Result<(), RpcError> {
|
|||||||
properties::properties,
|
properties::properties,
|
||||||
dependencies::dependency,
|
dependencies::dependency,
|
||||||
backup::package_backup,
|
backup::package_backup,
|
||||||
marketplace::set_package_url,
|
|
||||||
))]
|
))]
|
||||||
pub fn package() -> Result<(), RpcError> {
|
pub fn package() -> Result<(), RpcError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,43 +1,35 @@
|
|||||||
use patch_db::{DbHandle, LockType};
|
use color_eyre::eyre::eyre;
|
||||||
use reqwest::Url;
|
use reqwest::{StatusCode, Url};
|
||||||
use rpc_toolkit::command;
|
use rpc_toolkit::command;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::context::RpcContext;
|
use crate::{Error, ResultExt};
|
||||||
use crate::util::display_none;
|
|
||||||
use crate::Error;
|
|
||||||
|
|
||||||
#[command(rename = "set-marketplace", display(display_none))]
|
#[command(subcommands(get))]
|
||||||
pub async fn set_eos_url(#[context] ctx: RpcContext, #[arg] url: Url) -> Result<(), Error> {
|
pub fn marketplace() -> Result<(), Error> {
|
||||||
let mut db = ctx.db.handle();
|
|
||||||
let mut tx = db.begin().await?;
|
|
||||||
crate::db::DatabaseModel::new()
|
|
||||||
.server_info()
|
|
||||||
.lock(&mut tx, LockType::Write)
|
|
||||||
.await?;
|
|
||||||
crate::db::DatabaseModel::new()
|
|
||||||
.server_info()
|
|
||||||
.eos_marketplace()
|
|
||||||
.put(&mut tx, &url)
|
|
||||||
.await?;
|
|
||||||
ctx.set_nginx_conf(&mut tx).await?;
|
|
||||||
tx.commit(None).await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command(rename = "set-marketplace", display(display_none))]
|
#[command]
|
||||||
pub async fn set_package_url(#[context] ctx: RpcContext, #[arg] url: Url) -> Result<(), Error> {
|
pub async fn get(#[arg] url: Url) -> Result<Value, Error> {
|
||||||
let mut db = ctx.db.handle();
|
let response = reqwest::get(url)
|
||||||
let mut tx = db.begin().await?;
|
.await
|
||||||
crate::db::DatabaseModel::new()
|
.with_kind(crate::ErrorKind::Network)?;
|
||||||
.server_info()
|
let status = response.status();
|
||||||
.lock(&mut tx, LockType::Write)
|
if status.is_success() {
|
||||||
.await?;
|
response
|
||||||
crate::db::DatabaseModel::new()
|
.json()
|
||||||
.server_info()
|
.await
|
||||||
.package_marketplace()
|
.with_kind(crate::ErrorKind::Deserialization)
|
||||||
.put(&mut tx, &Some(url))
|
} else {
|
||||||
.await?;
|
let message = response.text().await.with_kind(crate::ErrorKind::Network)?;
|
||||||
ctx.set_nginx_conf(&mut tx).await?;
|
Err(Error::new(
|
||||||
tx.commit(None).await?;
|
eyre!("{}", message),
|
||||||
Ok(())
|
match status {
|
||||||
|
StatusCode::BAD_REQUEST => crate::ErrorKind::InvalidRequest,
|
||||||
|
StatusCode::NOT_FOUND => crate::ErrorKind::NotFound,
|
||||||
|
_ => crate::ErrorKind::Registry,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,18 +45,6 @@ server {{
|
|||||||
proxy_pass http://127.0.0.1:5961/;
|
proxy_pass http://127.0.0.1:5961/;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
location /marketplace/eos/ {{
|
|
||||||
# ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com
|
|
||||||
resolver 173.245.58.51 173.245.59.41 198.41.222.173;
|
|
||||||
proxy_pass {eos_marketplace}eos/;
|
|
||||||
}}
|
|
||||||
|
|
||||||
location /marketplace/package/ {{
|
|
||||||
# ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com
|
|
||||||
resolver 173.245.58.51 173.245.59.41 198.41.222.173;
|
|
||||||
proxy_pass {package_marketplace}package/;
|
|
||||||
}}
|
|
||||||
|
|
||||||
location / {{
|
location / {{
|
||||||
try_files $uri $uri/ =404;
|
try_files $uri $uri/ =404;
|
||||||
}}
|
}}
|
||||||
@@ -111,18 +99,6 @@ server {{
|
|||||||
proxy_pass http://127.0.0.1:5961/;
|
proxy_pass http://127.0.0.1:5961/;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
location /marketplace/eos/ {{
|
|
||||||
# ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com
|
|
||||||
resolver 173.245.58.51 173.245.59.41 198.41.222.173;
|
|
||||||
proxy_pass {eos_marketplace}eos/;
|
|
||||||
}}
|
|
||||||
|
|
||||||
location /marketplace/package/ {{
|
|
||||||
# ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com
|
|
||||||
resolver 173.245.58.51 173.245.59.41 198.41.222.173;
|
|
||||||
proxy_pass {package_marketplace}package/;
|
|
||||||
}}
|
|
||||||
|
|
||||||
location / {{
|
location / {{
|
||||||
try_files $uri $uri/ =404;
|
try_files $uri $uri/ =404;
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::pin::Pin;
|
|||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use digest::Output;
|
use digest::Output;
|
||||||
|
use ed25519_dalek::PublicKey;
|
||||||
use sha2::{Digest, Sha512};
|
use sha2::{Digest, Sha512};
|
||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, ReadBuf, Take};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, ReadBuf, Take};
|
||||||
@@ -47,6 +48,7 @@ impl<'a, R: AsyncRead + AsyncSeek + Unpin> AsyncRead for ReadHandle<'a, R> {
|
|||||||
pub struct S9pkReader<R: AsyncRead + AsyncSeek + Unpin = File> {
|
pub struct S9pkReader<R: AsyncRead + AsyncSeek + Unpin = File> {
|
||||||
hash: Option<Output<Sha512>>,
|
hash: Option<Output<Sha512>>,
|
||||||
hash_string: Option<String>,
|
hash_string: Option<String>,
|
||||||
|
developer_key: PublicKey,
|
||||||
toc: TableOfContents,
|
toc: TableOfContents,
|
||||||
pos: u64,
|
pos: u64,
|
||||||
rdr: R,
|
rdr: R,
|
||||||
@@ -105,6 +107,7 @@ impl<R: AsyncRead + AsyncSeek + Unpin> S9pkReader<R> {
|
|||||||
Ok(S9pkReader {
|
Ok(S9pkReader {
|
||||||
hash_string,
|
hash_string,
|
||||||
hash,
|
hash,
|
||||||
|
developer_key: header.pubkey,
|
||||||
toc: header.table_of_contents,
|
toc: header.table_of_contents,
|
||||||
pos,
|
pos,
|
||||||
rdr,
|
rdr,
|
||||||
@@ -119,6 +122,10 @@ impl<R: AsyncRead + AsyncSeek + Unpin> S9pkReader<R> {
|
|||||||
self.hash_string.as_ref().map(|s| s.as_str())
|
self.hash_string.as_ref().map(|s| s.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn developer_key(&self) -> &PublicKey {
|
||||||
|
&self.developer_key
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn reset(&mut self) -> Result<(), Error> {
|
pub async fn reset(&mut self) -> Result<(), Error> {
|
||||||
self.rdr.seek(SeekFrom::Start(0)).await?;
|
self.rdr.seek(SeekFrom::Start(0)).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ use tokio_stream::StreamExt;
|
|||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use crate::context::RpcContext;
|
use crate::context::RpcContext;
|
||||||
use crate::db::model::{ServerStatus, UpdateProgress};
|
use crate::db::model::UpdateProgress;
|
||||||
use crate::db::util::WithRevision;
|
use crate::db::util::WithRevision;
|
||||||
use crate::disk::mount::filesystem::block_dev::BlockDev;
|
use crate::disk::mount::filesystem::block_dev::BlockDev;
|
||||||
use crate::disk::mount::filesystem::FileSystem;
|
use crate::disk::mount::filesystem::FileSystem;
|
||||||
@@ -48,6 +48,7 @@ lazy_static! {
|
|||||||
#[instrument(skip(ctx))]
|
#[instrument(skip(ctx))]
|
||||||
pub async fn update_system(
|
pub async fn update_system(
|
||||||
#[context] ctx: RpcContext,
|
#[context] ctx: RpcContext,
|
||||||
|
#[arg(rename = "marketplace-url")] marketplace_url: Url,
|
||||||
) -> Result<WithRevision<UpdateResult>, Error> {
|
) -> Result<WithRevision<UpdateResult>, Error> {
|
||||||
let noop = WithRevision {
|
let noop = WithRevision {
|
||||||
response: UpdateResult::NoUpdates,
|
response: UpdateResult::NoUpdates,
|
||||||
@@ -56,7 +57,7 @@ pub async fn update_system(
|
|||||||
if UPDATED.load(Ordering::SeqCst) {
|
if UPDATED.load(Ordering::SeqCst) {
|
||||||
return Ok(noop);
|
return Ok(noop);
|
||||||
}
|
}
|
||||||
match maybe_do_update(ctx).await? {
|
match maybe_do_update(ctx, marketplace_url).await? {
|
||||||
None => Ok(noop),
|
None => Ok(noop),
|
||||||
Some(r) => Ok(WithRevision {
|
Some(r) => Ok(WithRevision {
|
||||||
response: UpdateResult::Updating,
|
response: UpdateResult::Updating,
|
||||||
@@ -127,11 +128,14 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(ctx))]
|
#[instrument(skip(ctx))]
|
||||||
async fn maybe_do_update(ctx: RpcContext) -> Result<Option<Arc<Revision>>, Error> {
|
async fn maybe_do_update(
|
||||||
|
ctx: RpcContext,
|
||||||
|
marketplace_url: Url,
|
||||||
|
) -> Result<Option<Arc<Revision>>, Error> {
|
||||||
let mut db = ctx.db.handle();
|
let mut db = ctx.db.handle();
|
||||||
let latest_version = reqwest::get(format!(
|
let latest_version = reqwest::get(format!(
|
||||||
"{}/eos/latest?eos-version={}&arch={}",
|
"{}/eos/latest?eos-version={}&arch={}",
|
||||||
ctx.eos_registry_url().await?,
|
marketplace_url,
|
||||||
Current::new().semver(),
|
Current::new().semver(),
|
||||||
platforms::TARGET_ARCH,
|
platforms::TARGET_ARCH,
|
||||||
))
|
))
|
||||||
@@ -154,67 +158,58 @@ async fn maybe_do_update(ctx: RpcContext) -> Result<Option<Arc<Revision>>, Error
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let mut tx = db.begin().await?;
|
let mut tx = db.begin().await?;
|
||||||
let mut info = crate::db::DatabaseModel::new()
|
let mut status = crate::db::DatabaseModel::new()
|
||||||
.server_info()
|
.server_info()
|
||||||
|
.status_info()
|
||||||
.get_mut(&mut tx)
|
.get_mut(&mut tx)
|
||||||
.await?;
|
.await?;
|
||||||
match &info.status {
|
if status.update_progress.is_some() {
|
||||||
ServerStatus::Updating => {
|
return Err(Error::new(
|
||||||
return Err(Error::new(
|
eyre!("Server is already updating!"),
|
||||||
eyre!("Server is already updating!"),
|
crate::ErrorKind::InvalidRequest,
|
||||||
crate::ErrorKind::InvalidRequest,
|
));
|
||||||
))
|
}
|
||||||
}
|
if status.updated {
|
||||||
ServerStatus::Updated => {
|
return Ok(None);
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
ServerStatus::BackingUp => {
|
|
||||||
return Err(Error::new(
|
|
||||||
eyre!("Server is backing up!"),
|
|
||||||
crate::ErrorKind::InvalidRequest,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
ServerStatus::Running => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (new_label, _current_label) = query_mounted_label().await?;
|
let (new_label, _current_label) = query_mounted_label().await?;
|
||||||
let (size, download) = download_file(
|
let (size, download) = download_file(
|
||||||
ctx.db.handle(),
|
ctx.db.handle(),
|
||||||
&EosUrl {
|
&EosUrl {
|
||||||
base: info.eos_marketplace.clone(),
|
base: marketplace_url,
|
||||||
version: latest_version.clone(),
|
version: latest_version.clone(),
|
||||||
},
|
},
|
||||||
new_label,
|
new_label,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
info.status = ServerStatus::Updating;
|
status.update_progress = Some(UpdateProgress {
|
||||||
info.update_progress = Some(UpdateProgress {
|
|
||||||
size,
|
size,
|
||||||
downloaded: 0,
|
downloaded: 0,
|
||||||
});
|
});
|
||||||
info.save(&mut tx).await?;
|
status.save(&mut tx).await?;
|
||||||
let rev = tx.commit(None).await?;
|
let rev = tx.commit(None).await?;
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut db = ctx.db.handle();
|
let mut db = ctx.db.handle();
|
||||||
let res = do_update(download, new_label).await;
|
let res = do_update(download, new_label).await;
|
||||||
let mut info = crate::db::DatabaseModel::new()
|
let mut status = crate::db::DatabaseModel::new()
|
||||||
.server_info()
|
.server_info()
|
||||||
|
.status_info()
|
||||||
.get_mut(&mut db)
|
.get_mut(&mut db)
|
||||||
.await
|
.await
|
||||||
.expect("could not access status");
|
.expect("could not access status");
|
||||||
info.update_progress = None;
|
status.update_progress = None;
|
||||||
match res {
|
match res {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
info.status = ServerStatus::Updated;
|
status.updated = true;
|
||||||
info.save(&mut db).await.expect("could not save status");
|
status.save(&mut db).await.expect("could not save status");
|
||||||
BEP.play().await.expect("could not bep");
|
BEP.play().await.expect("could not bep");
|
||||||
BEP.play().await.expect("could not bep");
|
BEP.play().await.expect("could not bep");
|
||||||
BEP.play().await.expect("could not bep");
|
BEP.play().await.expect("could not bep");
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info.status = ServerStatus::Running;
|
status.save(&mut db).await.expect("could not save status");
|
||||||
info.save(&mut db).await.expect("could not save status");
|
|
||||||
ctx.notification_manager
|
ctx.notification_manager
|
||||||
.notify(
|
.notify(
|
||||||
&mut db,
|
&mut db,
|
||||||
@@ -365,6 +360,7 @@ async fn write_stream_to_label<Db: DbHandle>(
|
|||||||
last_progress_update = Instant::now();
|
last_progress_update = Instant::now();
|
||||||
crate::db::DatabaseModel::new()
|
crate::db::DatabaseModel::new()
|
||||||
.server_info()
|
.server_info()
|
||||||
|
.status_info()
|
||||||
.update_progress()
|
.update_progress()
|
||||||
.put(db, &UpdateProgress { size, downloaded })
|
.put(db, &UpdateProgress { size, downloaded })
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user