mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
handle todos
This commit is contained in:
@@ -93,7 +93,6 @@ pub fn auth() -> ParentHandler {
|
|||||||
from_fn_async(logout)
|
from_fn_async(logout)
|
||||||
.with_metadata("get-session", Value::Bool(true))
|
.with_metadata("get-session", Value::Bool(true))
|
||||||
.with_remote_cli::<CliContext>()
|
.with_remote_cli::<CliContext>()
|
||||||
// TODO @dr-bonez
|
|
||||||
.no_display(),
|
.no_display(),
|
||||||
)
|
)
|
||||||
.subcommand("session", session())
|
.subcommand("session", session())
|
||||||
|
|||||||
@@ -45,6 +45,15 @@ pub fn backup() -> ParentHandler {
|
|||||||
.subcommand("target", target::target())
|
.subcommand("target", target::target())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn package_backup() -> ParentHandler {
|
||||||
|
ParentHandler::new().subcommand(
|
||||||
|
"restore",
|
||||||
|
from_fn_async(restore::restore_packages_rpc)
|
||||||
|
.no_display()
|
||||||
|
.with_remote_cli::<CliContext>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
struct BackupMetadata {
|
struct BackupMetadata {
|
||||||
pub timestamp: DateTime<Utc>,
|
pub timestamp: DateTime<Utc>,
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ pub struct RestorePackageParams {
|
|||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO dr Why doesn't anything use this
|
|
||||||
// #[command(rename = "restore", display(display_none))]
|
// #[command(rename = "restore", display(display_none))]
|
||||||
#[instrument(skip(ctx, password))]
|
#[instrument(skip(ctx, password))]
|
||||||
pub async fn restore_packages_rpc(
|
pub async fn restore_packages_rpc(
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ pub struct SetParams {
|
|||||||
pub config: StdinDeserializable<Option<Config>>,
|
pub config: StdinDeserializable<Option<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Dr Why isn't this used?
|
|
||||||
// #[command(
|
// #[command(
|
||||||
// subcommands(self(set_impl(async, context(RpcContext))), set_dry),
|
// subcommands(self(set_impl(async, context(RpcContext))), set_dry),
|
||||||
// display(display_none),
|
// display(display_none),
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use super::setup::CURRENT_SECRET;
|
|||||||
use crate::account::AccountInfo;
|
use crate::account::AccountInfo;
|
||||||
use crate::context::config::ServerConfig;
|
use crate::context::config::ServerConfig;
|
||||||
use crate::core::rpc_continuations::{RequestGuid, RestHandler, RpcContinuation, WebSocketHandler};
|
use crate::core::rpc_continuations::{RequestGuid, RestHandler, RpcContinuation, WebSocketHandler};
|
||||||
use crate::db::model::package::CurrentDependents;
|
|
||||||
use crate::db::prelude::PatchDbExt;
|
use crate::db::prelude::PatchDbExt;
|
||||||
use crate::dependencies::compute_dependency_config_errs;
|
use crate::dependencies::compute_dependency_config_errs;
|
||||||
use crate::disk::OsPartitionInfo;
|
use crate::disk::OsPartitionInfo;
|
||||||
@@ -207,39 +206,6 @@ impl RpcContext {
|
|||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub async fn cleanup_and_initialize(&self) -> Result<(), Error> {
|
pub async fn cleanup_and_initialize(&self) -> Result<(), Error> {
|
||||||
self.db
|
|
||||||
.mutate(|f| {
|
|
||||||
let mut current_dependents = f
|
|
||||||
.as_public_mut()
|
|
||||||
.as_package_data()
|
|
||||||
.keys()?
|
|
||||||
.into_iter()
|
|
||||||
.map(|k| (k.clone(), BTreeMap::new()))
|
|
||||||
.collect::<BTreeMap<_, _>>();
|
|
||||||
for (package_id, package) in
|
|
||||||
f.as_public_mut().as_package_data_mut().as_entries_mut()?
|
|
||||||
{
|
|
||||||
for (k, v) in package.clone().into_current_dependencies().into_entries()? {
|
|
||||||
let mut entry: BTreeMap<_, _> =
|
|
||||||
current_dependents.remove(&k).unwrap_or_default();
|
|
||||||
entry.insert(package_id.clone(), v.de()?);
|
|
||||||
current_dependents.insert(k, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (package_id, current_dependents) in current_dependents {
|
|
||||||
if let Some(deps) = f
|
|
||||||
.as_public_mut()
|
|
||||||
.as_package_data_mut()
|
|
||||||
.as_idx_mut(&package_id)
|
|
||||||
.map(|i| i.as_current_dependents_mut())
|
|
||||||
{
|
|
||||||
deps.ser(&CurrentDependents(current_dependents))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.services.init(&self).await?;
|
self.services.init(&self).await?;
|
||||||
tracing::info!("Initialized Package Managers");
|
tracing::info!("Initialized Package Managers");
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use emver::VersionRange;
|
||||||
use imbl_value::InternedString;
|
use imbl_value::InternedString;
|
||||||
use models::{DataUrl, HealthCheckId, HostId, PackageId};
|
use models::{DataUrl, HealthCheckId, HostId, PackageId};
|
||||||
use patch_db::json_ptr::JsonPointer;
|
use patch_db::json_ptr::JsonPointer;
|
||||||
@@ -299,7 +300,6 @@ pub struct PackageDataEntry {
|
|||||||
pub icon: DataUrl<'static>,
|
pub icon: DataUrl<'static>,
|
||||||
pub last_backup: Option<DateTime<Utc>>,
|
pub last_backup: Option<DateTime<Utc>>,
|
||||||
pub dependency_info: BTreeMap<PackageId, StaticDependencyInfo>,
|
pub dependency_info: BTreeMap<PackageId, StaticDependencyInfo>,
|
||||||
pub current_dependents: CurrentDependents,
|
|
||||||
pub current_dependencies: CurrentDependencies,
|
pub current_dependencies: CurrentDependencies,
|
||||||
pub interface_addresses: InterfaceAddressMap,
|
pub interface_addresses: InterfaceAddressMap,
|
||||||
pub hosts: HostInfo,
|
pub hosts: HostInfo,
|
||||||
@@ -357,29 +357,6 @@ impl Default for ExposedUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
|
||||||
pub struct CurrentDependents(pub BTreeMap<PackageId, CurrentDependencyInfo>);
|
|
||||||
impl CurrentDependents {
|
|
||||||
pub fn map(
|
|
||||||
mut self,
|
|
||||||
transform: impl Fn(
|
|
||||||
BTreeMap<PackageId, CurrentDependencyInfo>,
|
|
||||||
) -> BTreeMap<PackageId, CurrentDependencyInfo>,
|
|
||||||
) -> Self {
|
|
||||||
self.0 = transform(self.0);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Map for CurrentDependents {
|
|
||||||
type Key = PackageId;
|
|
||||||
type Value = CurrentDependencyInfo;
|
|
||||||
fn key_str(key: &Self::Key) -> Result<impl AsRef<str>, Error> {
|
|
||||||
Ok(key)
|
|
||||||
}
|
|
||||||
fn key_string(key: &Self::Key) -> Result<InternedString, Error> {
|
|
||||||
Ok(key.clone().into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||||
pub struct CurrentDependencies(pub BTreeMap<PackageId, CurrentDependencyInfo>);
|
pub struct CurrentDependencies(pub BTreeMap<PackageId, CurrentDependencyInfo>);
|
||||||
impl CurrentDependencies {
|
impl CurrentDependencies {
|
||||||
@@ -416,9 +393,19 @@ pub struct StaticDependencyInfo {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum CurrentDependencyInfo {
|
pub enum CurrentDependencyInfo {
|
||||||
Exists,
|
#[serde(rename_all = "camelCase")]
|
||||||
|
Exists {
|
||||||
|
#[ts(type = "string")]
|
||||||
|
url: Url,
|
||||||
|
#[ts(type = "string")]
|
||||||
|
version_spec: VersionRange,
|
||||||
|
},
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
Running {
|
Running {
|
||||||
|
#[ts(type = "string")]
|
||||||
|
url: Url,
|
||||||
|
#[ts(type = "string")]
|
||||||
|
version_spec: VersionRange,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[ts(type = "string[]")]
|
#[ts(type = "string[]")]
|
||||||
health_checks: BTreeSet<HealthCheckId>,
|
health_checks: BTreeSet<HealthCheckId>,
|
||||||
|
|||||||
@@ -56,8 +56,6 @@ pub struct DepInfo {
|
|||||||
pub version: VersionRange,
|
pub version: VersionRange,
|
||||||
pub requirement: DependencyRequirement,
|
pub requirement: DependencyRequirement,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
#[serde(default)]
|
|
||||||
pub config: Option<Value>, // TODO: remove
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Parser)]
|
#[derive(Deserialize, Serialize, Parser)]
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ pub fn package() -> ParentHandler {
|
|||||||
.with_remote_cli::<CliContext>(),
|
.with_remote_cli::<CliContext>(),
|
||||||
)
|
)
|
||||||
.subcommand("dependency", dependencies::dependency())
|
.subcommand("dependency", dependencies::dependency())
|
||||||
.subcommand("package-backup", backup::backup())
|
.subcommand("backup", backup::package_backup())
|
||||||
.subcommand("connect", from_fn_async(service::connect_rpc).no_cli())
|
.subcommand("connect", from_fn_async(service::connect_rpc).no_cli())
|
||||||
.subcommand(
|
.subcommand(
|
||||||
"connect",
|
"connect",
|
||||||
|
|||||||
@@ -183,7 +183,6 @@ pub async fn root_ca_start_time() -> Result<SystemTime, Error> {
|
|||||||
const EC_CURVE_NAME: nid::Nid = nid::Nid::X9_62_PRIME256V1;
|
const EC_CURVE_NAME: nid::Nid = nid::Nid::X9_62_PRIME256V1;
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref EC_GROUP: EcGroup = EcGroup::from_curve_name(EC_CURVE_NAME).unwrap();
|
static ref EC_GROUP: EcGroup = EcGroup::from_curve_name(EC_CURVE_NAME).unwrap();
|
||||||
static ref SSL_MUTEX: Mutex<()> = Mutex::new(()); // TODO: make thread safe
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn export_key(key: &PKey<Private>, target: &Path) -> Result<(), Error> {
|
pub async fn export_key(key: &PKey<Private>, target: &Path) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -768,7 +768,7 @@ async fn test() {
|
|||||||
let mut conn = torut::control::UnauthenticatedConn::new(
|
let mut conn = torut::control::UnauthenticatedConn::new(
|
||||||
TcpStream::connect(SocketAddr::from(([127, 0, 0, 1], 9051)))
|
TcpStream::connect(SocketAddr::from(([127, 0, 0, 1], 9051)))
|
||||||
.await
|
.await
|
||||||
.unwrap(), // TODO
|
.unwrap(),
|
||||||
);
|
);
|
||||||
let auth = conn
|
let auth = conn
|
||||||
.load_protocol_info()
|
.load_protocol_info()
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ async fn add_image(
|
|||||||
Command::new("bash")
|
Command::new("bash")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(format!(
|
.arg(format!(
|
||||||
"{CONTAINER_TOOL} export {container_id} | mksquashfs - {sqfs} -tar -force-uid 100000 -force-gid 100000", // TODO: real uid mapping
|
"{CONTAINER_TOOL} export {container_id} | mksquashfs - {sqfs} -tar",
|
||||||
container_id = container_id.trim(),
|
container_id = container_id.trim(),
|
||||||
sqfs = sqfs_path.display()
|
sqfs = sqfs_path.display()
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
use std::collections::BTreeMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use imbl_value::InOMap;
|
use imbl_value::InOMap;
|
||||||
pub use models::PackageId;
|
pub use models::PackageId;
|
||||||
|
use models::VolumeId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
@@ -11,7 +13,6 @@ use crate::prelude::*;
|
|||||||
use crate::s9pk::manifest::{Alerts, Description, HardwareRequirements};
|
use crate::s9pk::manifest::{Alerts, Description, HardwareRequirements};
|
||||||
use crate::util::Version;
|
use crate::util::Version;
|
||||||
use crate::version::{Current, VersionT};
|
use crate::version::{Current, VersionT};
|
||||||
use crate::volume::Volumes;
|
|
||||||
|
|
||||||
fn current_version() -> Version {
|
fn current_version() -> Version {
|
||||||
Current::new().semver().into()
|
Current::new().semver().into()
|
||||||
@@ -40,7 +41,7 @@ pub struct Manifest {
|
|||||||
pub donation_url: Option<Url>,
|
pub donation_url: Option<Url>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub alerts: Alerts,
|
pub alerts: Alerts,
|
||||||
pub volumes: Volumes,
|
pub volumes: BTreeMap<VolumeId, Value>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub dependencies: Dependencies,
|
pub dependencies: Dependencies,
|
||||||
pub config: Option<InOMap<String, Value>>,
|
pub config: Option<InOMap<String, Value>>,
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use crate::s9pk::v1::reader::S9pkReader;
|
|||||||
use crate::s9pk::v2::S9pk;
|
use crate::s9pk::v2::S9pk;
|
||||||
use crate::util::io::TmpDir;
|
use crate::util::io::TmpDir;
|
||||||
use crate::util::Invoke;
|
use crate::util::Invoke;
|
||||||
use crate::volume::Volume;
|
|
||||||
use crate::ARCH;
|
use crate::ARCH;
|
||||||
|
|
||||||
pub const MAGIC_AND_VERSION: &[u8] = &[0x3b, 0x3b, 0x01];
|
pub const MAGIC_AND_VERSION: &[u8] = &[0x3b, 0x3b, 0x01];
|
||||||
@@ -254,7 +253,7 @@ impl S9pk<Section<MultiCursorFile>> {
|
|||||||
for (asset_id, _) in manifest
|
for (asset_id, _) in manifest
|
||||||
.volumes
|
.volumes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, v)| matches!(v, Volume::Assets { .. }))
|
.filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("assets"))
|
||||||
{
|
{
|
||||||
let assets_path = asset_dir.join(&asset_id);
|
let assets_path = asset_dir.join(&asset_id);
|
||||||
let sqfs_path = assets_path.with_extension("squashfs");
|
let sqfs_path = assets_path.with_extension("squashfs");
|
||||||
@@ -338,13 +337,13 @@ impl From<ManifestV1> for Manifest {
|
|||||||
assets: value
|
assets: value
|
||||||
.volumes
|
.volumes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, v)| matches!(v, &&Volume::Assets { .. }))
|
.filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("assets"))
|
||||||
.map(|(id, _)| id.clone())
|
.map(|(id, _)| id.clone())
|
||||||
.collect(),
|
.collect(),
|
||||||
volumes: value
|
volumes: value
|
||||||
.volumes
|
.volumes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, v)| matches!(v, &&Volume::Data { .. }))
|
.filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("data"))
|
||||||
.map(|(id, _)| id.clone())
|
.map(|(id, _)| id.clone())
|
||||||
.collect(),
|
.collect(),
|
||||||
alerts: value.alerts,
|
alerts: value.alerts,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::sync::{Arc, Weak};
|
|||||||
|
|
||||||
use clap::builder::ValueParserFactory;
|
use clap::builder::ValueParserFactory;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use emver::VersionRange;
|
||||||
use imbl::OrdMap;
|
use imbl::OrdMap;
|
||||||
use imbl_value::{json, InternedString};
|
use imbl_value::{json, InternedString};
|
||||||
use models::{ActionId, HealthCheckId, ImageId, PackageId, VolumeId};
|
use models::{ActionId, HealthCheckId, ImageId, PackageId, VolumeId};
|
||||||
@@ -16,6 +17,7 @@ use rpc_toolkit::{from_fn, from_fn_async, AnyContext, Context, Empty, HandlerExt
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use crate::db::model::package::{
|
use crate::db::model::package::{
|
||||||
CurrentDependencies, CurrentDependencyInfo, ExposedUI, StoreExposedUI,
|
CurrentDependencies, CurrentDependencyInfo, ExposedUI, StoreExposedUI,
|
||||||
@@ -1096,15 +1098,19 @@ enum DependencyRequirement {
|
|||||||
id: PackageId,
|
id: PackageId,
|
||||||
#[ts(type = "string[]")]
|
#[ts(type = "string[]")]
|
||||||
health_checks: BTreeSet<HealthCheckId>,
|
health_checks: BTreeSet<HealthCheckId>,
|
||||||
version_spec: String,
|
#[ts(type = "string")]
|
||||||
url: String,
|
version_spec: VersionRange,
|
||||||
|
#[ts(type = "string")]
|
||||||
|
url: Url,
|
||||||
},
|
},
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
Exists {
|
Exists {
|
||||||
#[ts(type = "string")]
|
#[ts(type = "string")]
|
||||||
id: PackageId,
|
id: PackageId,
|
||||||
version_spec: String,
|
#[ts(type = "string")]
|
||||||
url: String,
|
version_spec: VersionRange,
|
||||||
|
#[ts(type = "string")]
|
||||||
|
url: Url,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// filebrowser:exists,bitcoind:running:foo+bar+baz
|
// filebrowser:exists,bitcoind:running:foo+bar+baz
|
||||||
@@ -1114,8 +1120,8 @@ impl FromStr for DependencyRequirement {
|
|||||||
match s.split_once(':') {
|
match s.split_once(':') {
|
||||||
Some((id, "e")) | Some((id, "exists")) => Ok(Self::Exists {
|
Some((id, "e")) | Some((id, "exists")) => Ok(Self::Exists {
|
||||||
id: id.parse()?,
|
id: id.parse()?,
|
||||||
url: "".to_string(),
|
url: "".parse()?, // TODO
|
||||||
version_spec: "*".to_string(),
|
version_spec: "*".parse()?, // TODO
|
||||||
}),
|
}),
|
||||||
Some((id, rest)) => {
|
Some((id, rest)) => {
|
||||||
let health_checks = match rest.split_once(':') {
|
let health_checks = match rest.split_once(':') {
|
||||||
@@ -1138,15 +1144,15 @@ impl FromStr for DependencyRequirement {
|
|||||||
Ok(Self::Running {
|
Ok(Self::Running {
|
||||||
id: id.parse()?,
|
id: id.parse()?,
|
||||||
health_checks,
|
health_checks,
|
||||||
url: "".to_string(),
|
url: "".parse()?, // TODO
|
||||||
version_spec: "*".to_string(),
|
version_spec: "*".parse()?, // TODO
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
None => Ok(Self::Running {
|
None => Ok(Self::Running {
|
||||||
id: s.parse()?,
|
id: s.parse()?,
|
||||||
health_checks: BTreeSet::new(),
|
health_checks: BTreeSet::new(),
|
||||||
url: "".to_string(),
|
url: "".parse()?, // TODO
|
||||||
version_spec: "*".to_string(),
|
version_spec: "*".parse()?, // TODO
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1183,23 +1189,23 @@ async fn set_dependencies(
|
|||||||
id,
|
id,
|
||||||
url,
|
url,
|
||||||
version_spec,
|
version_spec,
|
||||||
} => (id, CurrentDependencyInfo::Exists),
|
} => (id, CurrentDependencyInfo::Exists { url, version_spec }),
|
||||||
DependencyRequirement::Running {
|
DependencyRequirement::Running {
|
||||||
id,
|
id,
|
||||||
health_checks,
|
health_checks,
|
||||||
url,
|
url,
|
||||||
version_spec,
|
version_spec,
|
||||||
} => (id, CurrentDependencyInfo::Running { health_checks }),
|
} => (
|
||||||
|
id,
|
||||||
|
CurrentDependencyInfo::Running {
|
||||||
|
url,
|
||||||
|
version_spec,
|
||||||
|
health_checks,
|
||||||
|
},
|
||||||
|
),
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
for (dep, entry) in db.as_public_mut().as_package_data_mut().as_entries_mut()? {
|
|
||||||
if let Some(info) = dependencies.0.get(&dep) {
|
|
||||||
entry.as_current_dependents_mut().insert(id, info)?;
|
|
||||||
} else {
|
|
||||||
entry.as_current_dependents_mut().remove(id)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
db.as_public_mut()
|
db.as_public_mut()
|
||||||
.as_package_data_mut()
|
.as_package_data_mut()
|
||||||
.as_idx_mut(id)
|
.as_idx_mut(id)
|
||||||
|
|||||||
@@ -171,7 +171,6 @@ impl ServiceMap {
|
|||||||
icon,
|
icon,
|
||||||
last_backup: None,
|
last_backup: None,
|
||||||
dependency_info: Default::default(),
|
dependency_info: Default::default(),
|
||||||
current_dependents: Default::default(), // TODO: initialize
|
|
||||||
current_dependencies: Default::default(),
|
current_dependencies: Default::default(),
|
||||||
interface_addresses: Default::default(),
|
interface_addresses: Default::default(),
|
||||||
hosts: Default::default(),
|
hosts: Default::default(),
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
use std::collections::BTreeMap;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub use helpers::script_dir;
|
pub use helpers::script_dir;
|
||||||
use imbl_value::InternedString;
|
|
||||||
pub use models::VolumeId;
|
pub use models::VolumeId;
|
||||||
use models::{HostId, PackageId};
|
use models::{HostId, PackageId};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tracing::instrument;
|
|
||||||
|
|
||||||
use crate::context::RpcContext;
|
|
||||||
use crate::net::PACKAGE_CERT_PATH;
|
use crate::net::PACKAGE_CERT_PATH;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::Version;
|
use crate::util::Version;
|
||||||
@@ -17,72 +11,6 @@ use crate::util::Version;
|
|||||||
pub const PKG_VOLUME_DIR: &str = "package-data/volumes";
|
pub const PKG_VOLUME_DIR: &str = "package-data/volumes";
|
||||||
pub const BACKUP_DIR: &str = "/media/embassy/backups";
|
pub const BACKUP_DIR: &str = "/media/embassy/backups";
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
|
||||||
pub struct Volumes(BTreeMap<VolumeId, Volume>);
|
|
||||||
impl Volumes {
|
|
||||||
#[instrument(skip_all)]
|
|
||||||
pub async fn install(
|
|
||||||
&self,
|
|
||||||
ctx: &RpcContext,
|
|
||||||
pkg_id: &PackageId,
|
|
||||||
version: &Version,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
for (volume_id, volume) in &self.0 {
|
|
||||||
volume
|
|
||||||
.install(&ctx.datadir, pkg_id, version, volume_id)
|
|
||||||
.await?; // TODO: concurrent?
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
pub fn get_path_for(
|
|
||||||
&self,
|
|
||||||
path: &PathBuf,
|
|
||||||
pkg_id: &PackageId,
|
|
||||||
version: &Version,
|
|
||||||
volume_id: &VolumeId,
|
|
||||||
) -> Option<PathBuf> {
|
|
||||||
self.0
|
|
||||||
.get(volume_id)
|
|
||||||
.map(|volume| volume.path_for(path, pkg_id, version, volume_id))
|
|
||||||
}
|
|
||||||
pub fn to_readonly(&self) -> Self {
|
|
||||||
Volumes(
|
|
||||||
self.0
|
|
||||||
.iter()
|
|
||||||
.map(|(id, volume)| {
|
|
||||||
let mut volume = volume.clone();
|
|
||||||
volume.set_readonly();
|
|
||||||
(id.clone(), volume)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Deref for Volumes {
|
|
||||||
type Target = BTreeMap<VolumeId, Volume>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl DerefMut for Volumes {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Map for Volumes {
|
|
||||||
type Key = VolumeId;
|
|
||||||
type Value = Volume;
|
|
||||||
fn key_str(key: &Self::Key) -> Result<impl AsRef<str>, Error> {
|
|
||||||
Ok(key)
|
|
||||||
}
|
|
||||||
fn key_string(key: &Self::Key) -> Result<InternedString, Error> {
|
|
||||||
match key {
|
|
||||||
VolumeId::Custom(id) => Ok(id.clone().into()),
|
|
||||||
_ => Self::key_str(key).map(|s| InternedString::intern(s.as_ref())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn data_dir<P: AsRef<Path>>(datadir: P, pkg_id: &PackageId, volume_id: &VolumeId) -> PathBuf {
|
pub fn data_dir<P: AsRef<Path>>(datadir: P, pkg_id: &PackageId, volume_id: &VolumeId) -> PathBuf {
|
||||||
datadir
|
datadir
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -108,114 +36,3 @@ pub fn backup_dir(pkg_id: &PackageId) -> PathBuf {
|
|||||||
pub fn cert_dir(pkg_id: &PackageId, host_id: &HostId) -> PathBuf {
|
pub fn cert_dir(pkg_id: &PackageId, host_id: &HostId) -> PathBuf {
|
||||||
Path::new(PACKAGE_CERT_PATH).join(pkg_id).join(host_id)
|
Path::new(PACKAGE_CERT_PATH).join(pkg_id).join(host_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
#[serde(tag = "type")]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub enum Volume {
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
Data {
|
|
||||||
#[serde(skip)]
|
|
||||||
readonly: bool,
|
|
||||||
},
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
Assets {},
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
Pointer {
|
|
||||||
package_id: PackageId,
|
|
||||||
volume_id: VolumeId,
|
|
||||||
path: PathBuf,
|
|
||||||
readonly: bool,
|
|
||||||
},
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
Certificate { interface_id: HostId },
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
Backup { readonly: bool },
|
|
||||||
}
|
|
||||||
impl Volume {
|
|
||||||
pub async fn install(
|
|
||||||
&self,
|
|
||||||
path: &PathBuf,
|
|
||||||
pkg_id: &PackageId,
|
|
||||||
version: &Version,
|
|
||||||
volume_id: &VolumeId,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
match self {
|
|
||||||
Volume::Data { .. } => {
|
|
||||||
tokio::fs::create_dir_all(self.path_for(path, pkg_id, version, volume_id)).await?;
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
pub fn path_for(
|
|
||||||
&self,
|
|
||||||
data_dir_path: impl AsRef<Path>,
|
|
||||||
pkg_id: &PackageId,
|
|
||||||
version: &Version,
|
|
||||||
volume_id: &VolumeId,
|
|
||||||
) -> PathBuf {
|
|
||||||
match self {
|
|
||||||
Volume::Data { .. } => data_dir(&data_dir_path, pkg_id, volume_id),
|
|
||||||
Volume::Assets {} => asset_dir(&data_dir_path, pkg_id, version).join(volume_id),
|
|
||||||
Volume::Pointer {
|
|
||||||
package_id,
|
|
||||||
volume_id,
|
|
||||||
path,
|
|
||||||
..
|
|
||||||
} => data_dir(&data_dir_path, package_id, volume_id).join(if path.is_absolute() {
|
|
||||||
path.strip_prefix("/").unwrap()
|
|
||||||
} else {
|
|
||||||
path.as_ref()
|
|
||||||
}),
|
|
||||||
Volume::Certificate { interface_id } => cert_dir(pkg_id, &interface_id),
|
|
||||||
Volume::Backup { .. } => backup_dir(pkg_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pointer_path(&self, data_dir_path: impl AsRef<Path>) -> Option<PathBuf> {
|
|
||||||
if let Volume::Pointer {
|
|
||||||
path,
|
|
||||||
package_id,
|
|
||||||
volume_id,
|
|
||||||
..
|
|
||||||
} = self
|
|
||||||
{
|
|
||||||
Some(
|
|
||||||
data_dir(data_dir_path.as_ref(), package_id, volume_id).join(
|
|
||||||
if path.is_absolute() {
|
|
||||||
path.strip_prefix("/").unwrap()
|
|
||||||
} else {
|
|
||||||
path.as_ref()
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_readonly(&mut self) {
|
|
||||||
match self {
|
|
||||||
Volume::Data { readonly } => {
|
|
||||||
*readonly = true;
|
|
||||||
}
|
|
||||||
Volume::Pointer { readonly, .. } => {
|
|
||||||
*readonly = true;
|
|
||||||
}
|
|
||||||
Volume::Backup { readonly } => {
|
|
||||||
*readonly = true;
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn readonly(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Volume::Data { readonly } => *readonly,
|
|
||||||
Volume::Assets {} => true,
|
|
||||||
Volume::Pointer { readonly, .. } => *readonly,
|
|
||||||
Volume::Certificate { .. } => true,
|
|
||||||
Volume::Backup { readonly } => *readonly,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -139,7 +139,9 @@ export enum PackageState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CurrentDependencyInfo {
|
export interface CurrentDependencyInfo {
|
||||||
versionRange: string
|
kind: 'exists' | 'running'
|
||||||
|
url: string
|
||||||
|
versionSpec: string
|
||||||
healthChecks: string[] // array of health check IDs
|
healthChecks: string[] // array of health check IDs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user