mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
Feature/dry auto configure (#584)
* rename variables for clarity * return altered dep config * add utils system image, move compat into system-images * rename variables for clarity * sync integration and add debug instrumentation * debugging * add trace instrumentation * fix compilation for instrumentation * fix potential deadlocking behavior * fix import * fix dep check response return * hook back up to rpc, was overwritten in rebase * fix package command * get proper package config * testing dep config * version/volume for dep * vars * compat debugs * clean up * remove tar Co-authored-by: Chris Guida <chrisguida@gmail.com>
This commit is contained in:
@@ -1,23 +1,34 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::util::display_none;
|
||||
use color_eyre::eyre::eyre;
|
||||
use emver::VersionRange;
|
||||
use futures::future::BoxFuture;
|
||||
use futures::FutureExt;
|
||||
use patch_db::{DbHandle, DiffPatch, HasModel, Map, MapModel};
|
||||
use patch_db::{DbHandle, HasModel, Map, MapModel, PatchDbHandle};
|
||||
use rpc_toolkit::command;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::action::{ActionImplementation, NoOutput};
|
||||
use crate::config::Config;
|
||||
use crate::context::RpcContext;
|
||||
use crate::db::model::CurrentDependencyInfo;
|
||||
use crate::error::ResultExt;
|
||||
use crate::s9pk::manifest::{Manifest, PackageId};
|
||||
use crate::status::health_check::{HealthCheckId, HealthCheckResult};
|
||||
use crate::status::{MainStatus, Status};
|
||||
use crate::util::display_serializable;
|
||||
use crate::util::Version;
|
||||
use crate::volume::Volumes;
|
||||
use crate::Error;
|
||||
|
||||
#[command(subcommands(configure))]
|
||||
pub fn dependency() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[serde(tag = "type")]
|
||||
@@ -78,6 +89,7 @@ impl DependencyError {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[instrument(skip(ctx, db))]
|
||||
pub fn try_heal<'a, Db: DbHandle>(
|
||||
self,
|
||||
ctx: &'a RpcContext,
|
||||
@@ -166,7 +178,7 @@ impl DependencyError {
|
||||
Config::default()
|
||||
};
|
||||
if let Some(cfg_req) = &info.config {
|
||||
if let Err(e) = cfg_req
|
||||
if let Err(error) = cfg_req
|
||||
.check(
|
||||
ctx,
|
||||
id,
|
||||
@@ -174,15 +186,9 @@ impl DependencyError {
|
||||
&dependent_manifest.volumes,
|
||||
&dependency_config,
|
||||
)
|
||||
.await
|
||||
.await?
|
||||
{
|
||||
if e.kind == crate::ErrorKind::ConfigRulesViolation {
|
||||
return Ok(Some(DependencyError::ConfigUnsatisfied {
|
||||
error: format!("{}", e),
|
||||
}));
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(Some(DependencyError::ConfigUnsatisfied { error }));
|
||||
}
|
||||
}
|
||||
DependencyError::NotRunning
|
||||
@@ -440,6 +446,146 @@ impl DependencyConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[command(
|
||||
subcommands(self(configure_impl(async)), configure_dry),
|
||||
display(display_none)
|
||||
)]
|
||||
pub async fn configure(
|
||||
#[arg(rename = "dependent-id")] dependent_id: PackageId,
|
||||
#[arg(rename = "dependency-id")] dependency_id: PackageId,
|
||||
) -> Result<(PackageId, PackageId), Error> {
|
||||
Ok((dependent_id, dependency_id))
|
||||
}
|
||||
|
||||
pub async fn configure_impl(
|
||||
ctx: RpcContext,
|
||||
(pkg_id, dep_id): (PackageId, PackageId),
|
||||
) -> Result<(), Error> {
|
||||
let mut db = ctx.db.handle();
|
||||
let new_config = configure_logic(ctx.clone(), &mut db, (pkg_id, dep_id.clone())).await?;
|
||||
Ok(crate::config::configure(
|
||||
&ctx,
|
||||
&mut db,
|
||||
&dep_id,
|
||||
Some(new_config),
|
||||
&Some(Duration::from_secs(3)),
|
||||
false,
|
||||
&mut BTreeMap::new(),
|
||||
&mut BTreeMap::new(),
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
#[command(rename = "dry", display(display_serializable))]
|
||||
#[instrument(skip(ctx))]
|
||||
pub async fn configure_dry(
|
||||
#[context] ctx: RpcContext,
|
||||
#[parent_data] (pkg_id, dependency_id): (PackageId, PackageId),
|
||||
) -> Result<Config, Error> {
|
||||
let mut db = ctx.db.handle();
|
||||
configure_logic(ctx, &mut db, (pkg_id, dependency_id)).await
|
||||
}
|
||||
|
||||
pub async fn configure_logic(
|
||||
ctx: RpcContext,
|
||||
db: &mut PatchDbHandle,
|
||||
(pkg_id, dependency_id): (PackageId, PackageId),
|
||||
) -> Result<Config, Error> {
|
||||
let pkg_model = crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.idx_model(&pkg_id)
|
||||
.and_then(|m| m.installed())
|
||||
.expect(db)
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::NotFound)?;
|
||||
let pkg_version = pkg_model.clone().manifest().version().get(db, true).await?;
|
||||
let pkg_volumes = pkg_model.clone().manifest().volumes().get(db, true).await?;
|
||||
let dependency_model = crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.idx_model(&dependency_id)
|
||||
.and_then(|m| m.installed())
|
||||
.expect(db)
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::NotFound)?;
|
||||
let dependency_config_action = dependency_model
|
||||
.clone()
|
||||
.manifest()
|
||||
.config()
|
||||
.get(db, true)
|
||||
.await?
|
||||
.to_owned()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("{} has no config", dependency_id),
|
||||
crate::ErrorKind::NotFound,
|
||||
)
|
||||
})?;
|
||||
let dependency_version = dependency_model
|
||||
.clone()
|
||||
.manifest()
|
||||
.version()
|
||||
.get(db, true)
|
||||
.await?;
|
||||
let dependency_volumes = dependency_model
|
||||
.clone()
|
||||
.manifest()
|
||||
.volumes()
|
||||
.get(db, true)
|
||||
.await?;
|
||||
let dependencies = pkg_model
|
||||
.clone()
|
||||
.manifest()
|
||||
.dependencies()
|
||||
.get(db, true)
|
||||
.await?;
|
||||
|
||||
let dependency = dependencies
|
||||
.get(&dependency_id)
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!(
|
||||
"dependency for {} not found in the manifest for {}",
|
||||
dependency_id,
|
||||
pkg_id
|
||||
),
|
||||
crate::ErrorKind::NotFound,
|
||||
)
|
||||
})?
|
||||
.config
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!(
|
||||
"dependency config for {} not found on {}",
|
||||
dependency_id,
|
||||
pkg_id
|
||||
),
|
||||
crate::ErrorKind::NotFound,
|
||||
)
|
||||
})?;
|
||||
let config: Config = dependency_config_action
|
||||
.get(
|
||||
&ctx,
|
||||
&dependency_id,
|
||||
&*dependency_version,
|
||||
&*dependency_volumes,
|
||||
)
|
||||
.await?
|
||||
.config
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("no config get action found for {}", dependency_id),
|
||||
crate::ErrorKind::NotFound,
|
||||
)
|
||||
})?;
|
||||
Ok(dependency
|
||||
.auto_configure
|
||||
.sandboxed(&ctx, &pkg_id, &pkg_version, &pkg_volumes, Some(config))
|
||||
.await?
|
||||
.map_err(|e| Error::new(eyre!("{}", e.1), crate::ErrorKind::AutoConfigure))?)
|
||||
}
|
||||
|
||||
#[instrument(skip(db, current_dependencies))]
|
||||
pub async fn update_current_dependents<
|
||||
'a,
|
||||
Db: DbHandle,
|
||||
@@ -542,6 +688,7 @@ pub async fn break_all_dependents_transitive<'a, Db: DbHandle>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(db))]
|
||||
pub fn break_transitive<'a, Db: DbHandle>(
|
||||
db: &'a mut Db,
|
||||
id: &'a PackageId,
|
||||
@@ -609,6 +756,7 @@ pub fn break_transitive<'a, Db: DbHandle>(
|
||||
.boxed()
|
||||
}
|
||||
|
||||
#[instrument(skip(ctx, db))]
|
||||
pub async fn heal_all_dependents_transitive<'a, Db: DbHandle>(
|
||||
ctx: &'a RpcContext,
|
||||
db: &'a mut Db,
|
||||
@@ -629,6 +777,7 @@ pub async fn heal_all_dependents_transitive<'a, Db: DbHandle>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(ctx, db))]
|
||||
pub fn heal_transitive<'a, Db: DbHandle>(
|
||||
ctx: &'a RpcContext,
|
||||
db: &'a mut Db,
|
||||
|
||||
@@ -91,6 +91,7 @@ pub fn server() -> Result<(), RpcError> {
|
||||
control::stop,
|
||||
logs::logs,
|
||||
properties::properties,
|
||||
dependencies::dependency
|
||||
))]
|
||||
pub fn package() -> Result<(), RpcError> {
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user