appmgr inspect is back

This commit is contained in:
Aiden McClelland
2021-07-01 16:51:03 -06:00
parent 7bbbb5463e
commit 0fe91c023f
10 changed files with 160 additions and 14 deletions

View File

@@ -2,6 +2,8 @@ use clap::Arg;
use embassy::context::{CliContext, EitherContext}; use embassy::context::{CliContext, EitherContext};
use embassy::Error; use embassy::Error;
use rpc_toolkit::run_cli; use rpc_toolkit::run_cli;
use rpc_toolkit::yajrc::RpcError;
use serde_json::Value;
fn inner_main() -> Result<(), Error> { fn inner_main() -> Result<(), Error> {
run_cli!( run_cli!(
@@ -33,8 +35,19 @@ fn inner_main() -> Result<(), Error> {
}); });
EitherContext::Cli(CliContext::init(matches)?) EitherContext::Cli(CliContext::init(matches)?)
}, },
|code| if code < 0 { 1 } else { code } |e: RpcError| {
) match e.data {
Some(Value::String(s)) => eprintln!("{}: {}", e.message, s),
Some(Value::Object(o)) => if let Some(Value::String(s)) = o.get("message") {
eprintln!("{}: {}", e.message, s)
}
Some(a) => eprintln!("{}: {}", e.message, a),
None => eprintln!("{}", e.message),
}
std::process::exit(e.code);
}
);
Ok(())
} }
fn main() { fn main() {

View File

@@ -1,7 +1,8 @@
use clap::Arg;
use embassy::context::{CliContext, EitherContext}; use embassy::context::{CliContext, EitherContext};
use embassy::Error; use embassy::Error;
use rpc_toolkit::run_cli; use rpc_toolkit::run_cli;
use rpc_toolkit::yajrc::RpcError;
use serde_json::Value;
fn inner_main() -> Result<(), Error> { fn inner_main() -> Result<(), Error> {
run_cli!( run_cli!(
@@ -31,8 +32,19 @@ fn inner_main() -> Result<(), Error> {
}); });
EitherContext::Cli(CliContext::init(matches)?) EitherContext::Cli(CliContext::init(matches)?)
}, },
|code| if code < 0 { 1 } else { code } |e: RpcError| {
) match e.data {
Some(Value::String(s)) => eprintln!("{}: {}", e.message, s),
Some(Value::Object(o)) => if let Some(Value::String(s)) = o.get("message") {
eprintln!("{}: {}", e.message, s)
}
Some(a) => eprintln!("{}: {}", e.message, a),
None => eprintln!("{}", e.message),
}
std::process::exit(e.code);
}
);
Ok(())
} }
fn main() { fn main() {

View File

@@ -74,6 +74,18 @@ impl EitherContext {
_ => None, _ => None,
} }
} }
pub fn to_cli(self) -> Option<CliContext> {
match self {
EitherContext::Cli(a) => Some(a),
_ => None,
}
}
pub fn to_rpc(self) -> Option<RpcContext> {
match self {
EitherContext::Rpc(a) => Some(a),
_ => None,
}
}
} }
impl Context for EitherContext { impl Context for EitherContext {
fn host(&self) -> Host<&str> { fn host(&self) -> Host<&str> {

View File

@@ -5,6 +5,7 @@ use std::sync::Arc;
use bollard::Docker; use bollard::Docker;
use patch_db::PatchDb; use patch_db::PatchDb;
use reqwest::Url;
use rpc_toolkit::url::Host; use rpc_toolkit::url::Host;
use rpc_toolkit::Context; use rpc_toolkit::Context;
use serde::Deserialize; use serde::Deserialize;
@@ -83,6 +84,14 @@ impl RpcContext {
}); });
Ok(Self(seed)) Ok(Self(seed))
} }
pub async fn package_registry_url(&self) -> Result<Url, Error> {
Ok(crate::db::DatabaseModel::new()
.server_info()
.registry()
.get(&mut self.db.handle())
.await?
.to_owned())
}
} }
impl Context for RpcContext { impl Context for RpcContext {
fn host(&self) -> Host<&str> { fn host(&self) -> Host<&str> {

View File

@@ -43,7 +43,7 @@ impl Database {
.parse() .parse()
.unwrap(), .unwrap(),
updating: false, updating: false,
registry: "https://registry.start9.com".parse().unwrap(), registry: "https://beta-registry-0-3.start9labs.com".parse().unwrap(),
unread_notification_count: 0, unread_notification_count: 0,
}, },
package_data: AllPackageData::default(), package_data: AllPackageData::default(),

View File

@@ -183,7 +183,7 @@ impl From<torut::control::ConnError> for Error {
impl From<Error> for RpcError { impl From<Error> for RpcError {
fn from(e: Error) -> Self { fn from(e: Error) -> Self {
let mut data_object = serde_json::Map::with_capacity(2); let mut data_object = serde_json::Map::with_capacity(2);
data_object.insert("message".to_owned(), format!("{}", e).into()); data_object.insert("message".to_owned(), format!("{}", e.source).into());
data_object.insert( data_object.insert(
"revision".to_owned(), "revision".to_owned(),
match serde_json::to_value(&e.revision) { match serde_json::to_value(&e.revision) {

64
appmgr/src/inspect.rs Normal file
View File

@@ -0,0 +1,64 @@
use std::path::PathBuf;
use rpc_toolkit::command;
use crate::context::{CliContext, EitherContext};
use crate::s9pk::manifest::Manifest;
use crate::s9pk::reader::S9pkReader;
use crate::util::{display_none, display_serializable, IoFormat};
use crate::Error;
#[command(subcommands(manifest, license, icon, instructions, docker_images))]
pub fn inspect(#[context] ctx: EitherContext) -> Result<(), Error> {
Ok(())
}
#[command(cli_only, display(display_serializable))]
pub async fn manifest(
#[arg] path: PathBuf,
#[allow(unused_variables)]
#[arg(long = "format")]
format: Option<IoFormat>,
) -> Result<Manifest, Error> {
S9pkReader::open(path).await?.manifest().await
}
#[command(cli_only, display(display_none))]
pub async fn license(#[arg] path: PathBuf) -> Result<(), Error> {
tokio::io::copy(
&mut S9pkReader::open(path).await?.license().await?,
&mut tokio::io::stdout(),
)
.await?;
Ok(())
}
#[command(cli_only, display(display_none))]
pub async fn icon(#[arg] path: PathBuf) -> Result<(), Error> {
tokio::io::copy(
&mut S9pkReader::open(path).await?.icon().await?,
&mut tokio::io::stdout(),
)
.await?;
Ok(())
}
#[command(cli_only, display(display_none))]
pub async fn instructions(#[arg] path: PathBuf) -> Result<(), Error> {
tokio::io::copy(
&mut S9pkReader::open(path).await?.instructions().await?,
&mut tokio::io::stdout(),
)
.await?;
Ok(())
}
#[command(cli_only, display(display_none), rename = "docker-images")]
pub async fn docker_images(#[arg] path: PathBuf) -> Result<(), Error> {
tokio::io::copy(
&mut S9pkReader::open(path).await?.docker_images().await?,
&mut tokio::io::stdout(),
)
.await?;
Ok(())
}

View File

@@ -9,6 +9,7 @@ use std::task::{Context, Poll};
use std::time::Duration; use std::time::Duration;
use anyhow::anyhow; use anyhow::anyhow;
use emver::VersionRange;
use futures::TryStreamExt; use futures::TryStreamExt;
use http::HeaderMap; use http::HeaderMap;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
@@ -17,6 +18,7 @@ use patch_db::{
DbHandle, HasModel, MapModel, Model, ModelData, OptionModel, PatchDbHandle, Revision, DbHandle, HasModel, MapModel, Model, ModelData, OptionModel, PatchDbHandle, Revision,
}; };
use reqwest::Response; use reqwest::Response;
use rpc_toolkit::command;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
@@ -24,23 +26,48 @@ use tokio::fs::{File, OpenOptions};
use tokio::io::{AsyncRead, AsyncSeek, AsyncSeekExt, AsyncWrite, AsyncWriteExt}; use tokio::io::{AsyncRead, AsyncSeek, AsyncSeekExt, AsyncWrite, AsyncWriteExt};
use self::progress::{InstallProgress, InstallProgressTracker}; use self::progress::{InstallProgress, InstallProgressTracker};
use crate::context::RpcContext; use crate::context::{EitherContext, ExtendedContext, RpcContext};
use crate::db::model::{ use crate::db::model::{
CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticFiles, CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticFiles,
}; };
use crate::s9pk::manifest::{Manifest, PackageId}; use crate::s9pk::manifest::{Manifest, PackageId};
use crate::s9pk::reader::S9pkReader; use crate::s9pk::reader::S9pkReader;
use crate::status::{DependencyErrors, MainStatus, Status}; use crate::status::{DependencyErrors, MainStatus, Status};
use crate::util::{AsyncFileExt, Version}; use crate::util::{display_none, AsyncFileExt, Version};
use crate::Error; use crate::{Error, ResultExt};
pub mod progress; pub mod progress;
pub const PKG_CACHE: &'static str = "/mnt/embassy-os/cache/packages"; pub const PKG_CACHE: &'static str = "/mnt/embassy-os/cache/packages";
pub const PKG_PUBLIC_DIR: &'static str = "/mnt/embassy-os/public/package-data"; pub const PKG_PUBLIC_DIR: &'static str = "/mnt/embassy-os/public/package-data";
#[command(display(display_none))]
pub async fn install(#[context] ctx: EitherContext, #[arg] id: String) -> Result<(), Error> {
let rpc_ctx = ctx.as_rpc().unwrap();
let (pkg_id, version_str) = if let Some(split) = id.split_once("@") {
split
} else {
(id.as_str(), "*")
};
let version: VersionRange = version_str.parse()?;
let reg_url = rpc_ctx.package_registry_url().await?;
let (man_res, s9pk) = tokio::try_join!(
reqwest::get(format!(
"{}/packages/manifest/{}?version={}",
reg_url, pkg_id, version
)),
reqwest::get(format!(
"{}/packages/{}.s9pk?version={}",
reg_url, pkg_id, version
))
)
.with_kind(crate::ErrorKind::Registry)?;
let man = man_res.json().await.with_kind(crate::ErrorKind::Registry)?;
download_install_s9pk(rpc_ctx, &man, s9pk).await
}
pub async fn download_install_s9pk( pub async fn download_install_s9pk(
ctx: RpcContext, ctx: &RpcContext,
temp_manifest: &Manifest, temp_manifest: &Manifest,
s9pk: Response, s9pk: Response,
) -> Result<(), Error> { ) -> Result<(), Error> {

View File

@@ -25,6 +25,7 @@ pub mod dependencies;
pub mod developer; pub mod developer;
pub mod error; pub mod error;
pub mod id; pub mod id;
pub mod inspect;
pub mod install; pub mod install;
pub mod migration; pub mod migration;
pub mod net; pub mod net;
@@ -53,13 +54,21 @@ pub fn echo(#[context] _ctx: EitherContext, #[arg] message: String) -> Result<St
echo, echo,
s9pk::pack, s9pk::pack,
s9pk::verify, s9pk::verify,
developer::init developer::init,
install::install,
inspect::inspect,
))] ))]
pub fn main_api(#[context] ctx: EitherContext) -> Result<EitherContext, RpcError> { pub fn main_api(#[context] ctx: EitherContext) -> Result<EitherContext, RpcError> {
Ok(ctx) Ok(ctx)
} }
#[command(subcommands(version::git_info, s9pk::pack, s9pk::verify, developer::init))] #[command(subcommands(
version::git_info,
s9pk::pack,
s9pk::verify,
developer::init,
inspect::inspect
))]
pub fn portable_api(#[context] ctx: EitherContext) -> Result<EitherContext, RpcError> { pub fn portable_api(#[context] ctx: EitherContext) -> Result<EitherContext, RpcError> {
Ok(ctx) Ok(ctx)
} }

View File

@@ -71,7 +71,6 @@ impl<R: AsyncRead + AsyncSeek + Unpin> S9pkReader<R> {
} }
pub async fn from_reader(mut rdr: R) -> Result<Self, Error> { pub async fn from_reader(mut rdr: R) -> Result<Self, Error> {
let header = Header::deserialize(&mut rdr).await?; let header = Header::deserialize(&mut rdr).await?;
let pos = rdr.stream_position().await?;
let mut hasher = Sha512::new(); let mut hasher = Sha512::new();
let mut buf = [0; 1024]; let mut buf = [0; 1024];
@@ -86,6 +85,7 @@ impl<R: AsyncRead + AsyncSeek + Unpin> S9pkReader<R> {
header header
.pubkey .pubkey
.verify_prehashed(hasher, Some(SIG_CONTEXT), &header.signature)?; .verify_prehashed(hasher, Some(SIG_CONTEXT), &header.signature)?;
let pos = rdr.stream_position().await?;
Ok(S9pkReader { Ok(S9pkReader {
hash_string: base32::encode( hash_string: base32::encode(