feat: add app inspect command with show node
refactor sgx handler imports enhanced app list
This commit is contained in:
parent
b12c8ebb4b
commit
9b3bdba70d
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1110,7 +1110,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "detee-shared"
|
name = "detee-shared"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+ssh://git@gitea.detee.cloud/testnet/proto.git?branch=main#70e83dd0e982eeb491212c4a9d265df0b148fe24"
|
source = "git+ssh://git@gitea.detee.cloud/testnet/proto.git?branch=main#3024c00b8e1c93e70902793385b92bc0a8d1f26a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"prost",
|
"prost",
|
||||||
|
@ -204,6 +204,19 @@ fn clap_cmd() -> Command {
|
|||||||
.action(clap::ArgAction::Append)
|
.action(clap::ArgAction::Append)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.subcommand(Command::new("inspect").about("list all available information about a App")
|
||||||
|
.arg(
|
||||||
|
Arg::new("uuid")
|
||||||
|
.help("supply the uuid of the App contract")
|
||||||
|
.required(true)
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("show-node")
|
||||||
|
.long("show-node")
|
||||||
|
.help("inspect the node that is runnnig this App")
|
||||||
|
.action(clap::ArgAction::SetTrue)
|
||||||
|
)
|
||||||
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
Command::new("delete")
|
Command::new("delete")
|
||||||
.about("delete deployed app")
|
.about("delete deployed app")
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
use super::grpc_brain::list_apps;
|
use crate::sgx::utils::deploy_new_app_and_update_config;
|
||||||
use super::utils::deploy_new_app_and_update_config;
|
|
||||||
use super::{get_app_node, AppContract, AppDeployResponse};
|
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
use crate::name_generator::random_app_name;
|
use crate::name_generator::random_app_name;
|
||||||
use crate::sgx;
|
|
||||||
use crate::sgx::config::{validate_yaml, DeteeCliExt};
|
use crate::sgx::config::{validate_yaml, DeteeCliExt};
|
||||||
use crate::sgx::grpc_brain::delete_app;
|
use crate::sgx::grpc_brain::{delete_app, list_contracts};
|
||||||
use crate::sgx::grpc_dtpm::{attest_and_send_config, get_config_from_enclave};
|
use crate::sgx::grpc_dtpm::{attest_and_send_config, get_config_from_enclave};
|
||||||
use crate::sgx::packaging::package_enclave;
|
use crate::sgx::packaging::package_enclave;
|
||||||
use crate::sgx::utils::{fetch_config_and_mr_enclave, override_envs_and_args_launch_config};
|
use crate::sgx::utils::{fetch_config_and_mr_enclave, override_envs_and_args_launch_config};
|
||||||
use crate::sgx::AppDeleteResponse;
|
use crate::sgx::AppDeleteResponse;
|
||||||
|
use crate::sgx::{
|
||||||
|
get_app_node, get_app_node_by_contract, get_one_contract, inspect_node, print_nodes,
|
||||||
|
};
|
||||||
|
use crate::sgx::{AppContract, AppDeployResponse};
|
||||||
use crate::utils::block_on;
|
use crate::utils::block_on;
|
||||||
use crate::{cli_print, SimpleOutput};
|
use crate::{cli_print, SimpleOutput};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
|
use detee_shared::app_proto::ListAppContractsReq;
|
||||||
use detee_shared::sgx::types::brain::AppDeployConfig;
|
use detee_shared::sgx::types::brain::AppDeployConfig;
|
||||||
use detee_shared::sgx::types::brain::Resource;
|
use detee_shared::sgx::types::brain::Resource;
|
||||||
|
|
||||||
@ -20,8 +23,9 @@ pub fn handle_app(app_matche: &ArgMatches) {
|
|||||||
match app_matche.subcommand() {
|
match app_matche.subcommand() {
|
||||||
Some(("package", subcom_args)) => cli_print(handle_package(subcom_args)),
|
Some(("package", subcom_args)) => cli_print(handle_package(subcom_args)),
|
||||||
Some(("deploy", subcom_args)) => cli_print(handle_deploy(subcom_args)),
|
Some(("deploy", subcom_args)) => cli_print(handle_deploy(subcom_args)),
|
||||||
|
Some(("inspect", subcom_args)) => handle_inspect(subcom_args),
|
||||||
Some(("delete", subcom_args)) => cli_print(handle_delete(subcom_args)),
|
Some(("delete", subcom_args)) => cli_print(handle_delete(subcom_args)),
|
||||||
Some(("list", subcom_args)) => cli_print(handle_list(subcom_args)),
|
Some(("list", _)) => cli_print(handle_list()),
|
||||||
Some(("config", subcom_args)) => handle_config(subcom_args),
|
Some(("config", subcom_args)) => handle_config(subcom_args),
|
||||||
_ => println!("No valid subcommand provided. Use --help for more information."),
|
_ => println!("No valid subcommand provided. Use --help for more information."),
|
||||||
}
|
}
|
||||||
@ -29,10 +33,10 @@ pub fn handle_app(app_matche: &ArgMatches) {
|
|||||||
|
|
||||||
pub fn handle_app_nodes(matches: &ArgMatches) {
|
pub fn handle_app_nodes(matches: &ArgMatches) {
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("search", _)) => cli_print(sgx::print_nodes().map_err(Into::into)),
|
Some(("search", _)) => cli_print(print_nodes().map_err(Into::into)),
|
||||||
Some(("inspect", subcom_args)) => {
|
Some(("inspect", subcom_args)) => {
|
||||||
let ip: String = subcom_args.get_one::<String>("ip").unwrap().clone();
|
let ip: String = subcom_args.get_one::<String>("ip").unwrap().clone();
|
||||||
cli_print(sgx::inspect_node(ip).map_err(Into::into));
|
cli_print(inspect_node(ip).map_err(Into::into));
|
||||||
}
|
}
|
||||||
Some(("report", _)) => {
|
Some(("report", _)) => {
|
||||||
// let node_pubkey: String = path_subcommand.get_one::<String>("pubkey").unwrap().clone();
|
// let node_pubkey: String = path_subcommand.get_one::<String>("pubkey").unwrap().clone();
|
||||||
@ -130,6 +134,15 @@ fn handle_deploy(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_inspect(inspect_match: &ArgMatches) {
|
||||||
|
let uuid: String = inspect_match.get_one::<String>("uuid").unwrap().clone();
|
||||||
|
if *inspect_match.get_one::<bool>("show-node").unwrap() {
|
||||||
|
cli_print(block_on(get_app_node_by_contract(&uuid)).map_err(Into::into));
|
||||||
|
} else {
|
||||||
|
cli_print(block_on(get_one_contract(&uuid)).map_err(Into::into))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_delete(
|
fn handle_delete(
|
||||||
delete_match: &ArgMatches,
|
delete_match: &ArgMatches,
|
||||||
) -> Result<AppDeleteResponse, Box<dyn std::error::Error>> {
|
) -> Result<AppDeleteResponse, Box<dyn std::error::Error>> {
|
||||||
@ -150,13 +163,13 @@ fn handle_delete(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_list(_: &ArgMatches) -> Result<Vec<crate::sgx::AppContract>, Box<dyn std::error::Error>> {
|
fn handle_list() -> Result<Vec<AppContract>, Box<dyn std::error::Error>> {
|
||||||
match block_on(list_apps()) {
|
let req =
|
||||||
Ok(app_contracts) => {
|
ListAppContractsReq { admin_pubkey: Config::get_detee_wallet()?, ..Default::default() };
|
||||||
Ok(app_contracts.into_iter().map(AppContract::from).collect::<Vec<_>>())
|
let contracts: Vec<AppContract> =
|
||||||
}
|
block_on(list_contracts(req))?.into_iter().map(|n| n.into()).collect();
|
||||||
Err(e) => Err(Box::new(e)),
|
|
||||||
}
|
Ok(contracts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_config(matches: &ArgMatches) {
|
fn handle_config(matches: &ArgMatches) {
|
||||||
|
@ -36,6 +36,30 @@ impl crate::HumanOutput for AppNodeListResp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl crate::HumanOutput for AppContract {
|
||||||
|
fn human_cli_print(&self) {
|
||||||
|
let app_resource = self.resource.clone().unwrap_or_default();
|
||||||
|
let mapped_ports = self
|
||||||
|
.mapped_ports
|
||||||
|
.clone()
|
||||||
|
.iter()
|
||||||
|
.map(|p| format!("({},{})", p.host_port, p.app_port))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
println!(
|
||||||
|
"The App {} has the UUID {}, and it runs on the node {}",
|
||||||
|
self.app_name, self.uuid, self.node_pubkey
|
||||||
|
);
|
||||||
|
println!("The app has mapped ports by the node are: {mapped_ports}");
|
||||||
|
println!(
|
||||||
|
"The App has {} vCPUS, {}MB of memory and a disk of {} MB.",
|
||||||
|
app_resource.vcpu, app_resource.memory_mb, app_resource.disk_mb
|
||||||
|
);
|
||||||
|
println!("You have locked {} nanoLP in the contract, that get collected at a rate of {} nanoLP per minute.",
|
||||||
|
self.locked_nano, self.nano_per_minute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn new_app(app_deploy_config: AppDeployConfig) -> Result<NewAppRes> {
|
pub async fn new_app(app_deploy_config: AppDeployConfig) -> Result<NewAppRes> {
|
||||||
let resource = app_deploy_config.clone().resource;
|
let resource = app_deploy_config.clone().resource;
|
||||||
let mut req: NewAppReq = app_deploy_config.clone().into();
|
let mut req: NewAppReq = app_deploy_config.clone().into();
|
||||||
@ -66,12 +90,9 @@ pub async fn delete_app(app_uuid: String) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_apps() -> Result<Vec<AppContract>> {
|
pub async fn list_contracts(req: ListAppContractsReq) -> Result<Vec<AppContract>> {
|
||||||
let admin_pubkey = Config::get_detee_wallet().unwrap();
|
|
||||||
let list_req = ListAppContractsReq { admin_pubkey };
|
|
||||||
let mut daemon_serivce = BrainAppCliClient::connect(Config::get_brain_url()).await?;
|
let mut daemon_serivce = BrainAppCliClient::connect(Config::get_brain_url()).await?;
|
||||||
let mut res_stream =
|
let mut res_stream = daemon_serivce.list_app_contracts(sign_request(req)?).await?.into_inner();
|
||||||
daemon_serivce.list_app_contracts(sign_request(list_req)?).await?.into_inner();
|
|
||||||
|
|
||||||
let mut app_contracts = vec![];
|
let mut app_contracts = vec![];
|
||||||
|
|
||||||
|
@ -5,11 +5,13 @@ pub mod grpc_dtpm;
|
|||||||
pub mod packaging;
|
pub mod packaging;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
use crate::snp;
|
use crate::snp;
|
||||||
use crate::{constants::HRATLS_APP_PORT, utils::block_on};
|
use crate::{constants::HRATLS_APP_PORT, utils::block_on};
|
||||||
use detee_shared::{
|
use detee_shared::{
|
||||||
app_proto::{
|
app_proto::{
|
||||||
AppContract as AppContractPB, AppNodeFilters, AppNodeListResp, AppResource, NewAppRes,
|
AppContract as AppContractPB, AppNodeFilters, AppNodeListResp, AppResource,
|
||||||
|
ListAppContractsReq, NewAppRes,
|
||||||
},
|
},
|
||||||
sgx::types::brain::Resource,
|
sgx::types::brain::Resource,
|
||||||
};
|
};
|
||||||
@ -17,6 +19,16 @@ use grpc_brain::get_one_app_node;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tabled::Tabled;
|
use tabled::Tabled;
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error(transparent)]
|
||||||
|
Config(#[from] crate::config::Error),
|
||||||
|
#[error("Could not find a contract with the ID {0}")]
|
||||||
|
AppContractNotFound(String),
|
||||||
|
#[error("Brain returned the following error: {0}")]
|
||||||
|
Brain(#[from] grpc_brain::Error),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Tabled, Debug, Serialize, Deserialize)]
|
#[derive(Tabled, Debug, Serialize, Deserialize)]
|
||||||
pub struct AppContract {
|
pub struct AppContract {
|
||||||
#[tabled(rename = "Location")]
|
#[tabled(rename = "Location")]
|
||||||
@ -101,6 +113,21 @@ impl From<AppContractPB> for AppContract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_one_contract(uuid: &str) -> Result<AppContractPB, Error> {
|
||||||
|
let req = ListAppContractsReq {
|
||||||
|
admin_pubkey: Config::get_detee_wallet()?,
|
||||||
|
uuid: uuid.to_string(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let contracts = grpc_brain::list_contracts(req).await?;
|
||||||
|
|
||||||
|
if contracts.is_empty() {
|
||||||
|
return Err(Error::AppContractNotFound(uuid.to_string()));
|
||||||
|
}
|
||||||
|
// let _ = write_uuid_list(&contracts);
|
||||||
|
Ok(contracts[0].clone())
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct AppDeployResponse {
|
pub struct AppDeployResponse {
|
||||||
pub status: String,
|
pub status: String,
|
||||||
@ -149,7 +176,6 @@ impl crate::HumanOutput for AppDeleteResponse {
|
|||||||
|
|
||||||
pub async fn get_app_node(
|
pub async fn get_app_node(
|
||||||
resource: Resource,
|
resource: Resource,
|
||||||
// TODO: change this to utils or something
|
|
||||||
location: snp::deploy::Location,
|
location: snp::deploy::Location,
|
||||||
) -> Result<AppNodeListResp, grpc_brain::Error> {
|
) -> Result<AppNodeListResp, grpc_brain::Error> {
|
||||||
let app_node_filter = AppNodeFilters {
|
let app_node_filter = AppNodeFilters {
|
||||||
@ -211,3 +237,9 @@ pub fn print_nodes() -> Result<Vec<AppNodeListResp>, grpc_brain::Error> {
|
|||||||
let req = AppNodeFilters { ..Default::default() };
|
let req = AppNodeFilters { ..Default::default() };
|
||||||
block_on(grpc_brain::get_app_node_list(req))
|
block_on(grpc_brain::get_app_node_list(req))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_app_node_by_contract(uuid: &str) -> Result<AppNodeListResp, Error> {
|
||||||
|
let contract = get_one_contract(uuid).await?;
|
||||||
|
Ok(get_one_app_node(AppNodeFilters { node_pubkey: contract.node_pubkey, ..Default::default() })
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::grpc_brain::new_app;
|
use super::grpc_brain::new_app;
|
||||||
use crate::constants::HRATLS_APP_PORT;
|
use crate::constants::HRATLS_APP_PORT;
|
||||||
use crate::sgx::grpc_brain::list_apps;
|
use crate::sgx::get_one_contract;
|
||||||
use crate::sgx::grpc_dtpm::attest_and_send_config;
|
use crate::sgx::grpc_dtpm::attest_and_send_config;
|
||||||
use detee_shared::app_proto::NewAppRes;
|
use detee_shared::app_proto::NewAppRes;
|
||||||
use detee_shared::sgx::types::brain::AppDeployConfig;
|
use detee_shared::sgx::types::brain::AppDeployConfig;
|
||||||
@ -27,9 +27,8 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn hratls_url_and_mr_enclave_from_app_id(app_id: &str) -> (String, Option<[u8; 32]>) {
|
pub async fn hratls_url_and_mr_enclave_from_app_id(app_id: &str) -> (String, Option<[u8; 32]>) {
|
||||||
let app_contracts = list_apps().await.expect("Could not get App contracts");
|
let app_contract = get_one_contract(app_id).await;
|
||||||
let app_contract = app_contracts.iter().find(|contract| contract.uuid == app_id);
|
if app_contract.is_err() {
|
||||||
if app_contract.is_none() {
|
|
||||||
eprintln!("Could not find App contract with ID: {}", app_id);
|
eprintln!("Could not find App contract with ID: {}", app_id);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
@ -98,6 +97,7 @@ pub fn calculate_nanolp_for_app(
|
|||||||
let total_units =
|
let total_units =
|
||||||
(vcpus as f64 * 5f64) + (memory_mb as f64 / 200f64) + (disk_size_mb as f64 / 10000f64);
|
(vcpus as f64 * 5f64) + (memory_mb as f64 / 200f64) + (disk_size_mb as f64 / 10000f64);
|
||||||
let locked_nano = (hours as f64 * 60f64 * total_units * node_price as f64) as u64;
|
let locked_nano = (hours as f64 * 60f64 * total_units * node_price as f64) as u64;
|
||||||
|
// TODO: change all println to eprintln
|
||||||
println!(
|
println!(
|
||||||
"Node price: {}/unit/minute. Total Units for hardware requested: {:.4}. Locking {} LP (offering the App for {} hours).",
|
"Node price: {}/unit/minute. Total Units for hardware requested: {:.4}. Locking {} LP (offering the App for {} hours).",
|
||||||
node_price as f64 / 1_000_000_000.0,
|
node_price as f64 / 1_000_000_000.0,
|
||||||
|
Loading…
Reference in New Issue
Block a user