140 lines
5.0 KiB
Rust
140 lines
5.0 KiB
Rust
use detee_shared::app_proto::brain_app_cli_client::BrainAppCliClient;
|
|
use detee_shared::app_proto::{
|
|
AppContract, AppNodeFilters, AppNodeListResp, DelAppReq, ListAppContractsReq, NewAppReq,
|
|
NewAppRes,
|
|
};
|
|
use detee_shared::sgx::types::brain::AppDeployConfig;
|
|
use tokio_stream::StreamExt;
|
|
|
|
use crate::config::Config;
|
|
use crate::sgx::utils::calculate_nanolp_for_app;
|
|
use crate::utils::{self, sign_request};
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum Error {
|
|
#[error("Failed to connect to the brain: {0}")]
|
|
BrainConnection(#[from] tonic::transport::Error),
|
|
#[error("Received error from brain: {}", _0.message())]
|
|
ResponseStatus(#[from] tonic::Status),
|
|
#[error(transparent)]
|
|
InternalError(#[from] utils::Error),
|
|
#[error(transparent)]
|
|
ConfigError(#[from] crate::config::Error),
|
|
}
|
|
|
|
type Result<T> = std::result::Result<T, Error>;
|
|
|
|
impl crate::HumanOutput for AppNodeListResp {
|
|
fn human_cli_print(&self) {
|
|
println!("The pubkey of this node is {} and the IP is {}", self.node_pubkey, self.ip);
|
|
println!("It belongs to the operator {}", self.operator);
|
|
println!(
|
|
"This node is located in the city {}, within the region of {}, in {}",
|
|
self.city, self.region, self.country
|
|
);
|
|
println!("The price multiplier for the node is {}.", self.price);
|
|
}
|
|
}
|
|
|
|
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> {
|
|
let resource = app_deploy_config.clone().resource;
|
|
let mut req: NewAppReq = app_deploy_config.clone().into();
|
|
|
|
let locked_nano = calculate_nanolp_for_app(
|
|
resource.vcpu,
|
|
resource.memory_mb,
|
|
resource.disk_mb,
|
|
app_deploy_config.hours,
|
|
req.price_per_unit,
|
|
);
|
|
|
|
req.uuid = "".to_string();
|
|
req.locked_nano = locked_nano;
|
|
req.admin_pubkey = Config::get_detee_wallet()?;
|
|
req.hratls_pubkey = Config::get_hratls_pubkey_hex()?;
|
|
|
|
let mut daemon_serivce = BrainAppCliClient::connect(Config::get_brain_url()).await?;
|
|
let res = daemon_serivce.deploy_app(sign_request(req)?).await?;
|
|
Ok(res.into_inner())
|
|
}
|
|
|
|
pub async fn delete_app(app_uuid: String) -> Result<()> {
|
|
let admin_pubkey = Config::get_detee_wallet()?;
|
|
let delete_req = DelAppReq { uuid: app_uuid, admin_pubkey };
|
|
let mut daemon_serivce = BrainAppCliClient::connect(Config::get_brain_url()).await?;
|
|
let _ = daemon_serivce.delete_app(sign_request(delete_req)?).await?;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn list_contracts(req: ListAppContractsReq) -> Result<Vec<AppContract>> {
|
|
let mut daemon_serivce = BrainAppCliClient::connect(Config::get_brain_url()).await?;
|
|
let mut res_stream = daemon_serivce.list_app_contracts(sign_request(req)?).await?.into_inner();
|
|
|
|
let mut app_contracts = vec![];
|
|
|
|
while let Some(stream_update) = res_stream.next().await {
|
|
match stream_update {
|
|
Ok(contract) => {
|
|
app_contracts.push(contract);
|
|
}
|
|
Err(e) => {
|
|
println!("Brain disconnected from register_node: {e}");
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(app_contracts)
|
|
}
|
|
|
|
pub async fn get_one_app_node(req: AppNodeFilters) -> Result<AppNodeListResp> {
|
|
let mut daemon_serivce = BrainAppCliClient::connect(Config::get_brain_url()).await?;
|
|
let res = daemon_serivce.get_one_app_node(sign_request(req)?).await?;
|
|
|
|
Ok(res.into_inner())
|
|
}
|
|
|
|
pub async fn get_app_node_list(req: AppNodeFilters) -> Result<Vec<AppNodeListResp>> {
|
|
log::debug!("Getting app nodes from brain...");
|
|
let mut daemon_serivce = BrainAppCliClient::connect(Config::get_brain_url()).await?;
|
|
let mut nodes = Vec::new();
|
|
let mut grpc_stream = daemon_serivce.list_app_nodes(sign_request(req)?).await?.into_inner();
|
|
|
|
while let Some(stream_update) = grpc_stream.next().await {
|
|
match stream_update {
|
|
Ok(node) => {
|
|
log::debug!("Received node from brain: {node:?}");
|
|
nodes.push(node);
|
|
}
|
|
Err(e) => {
|
|
log::warn!("Received error instead of node list: {e:?}");
|
|
}
|
|
}
|
|
}
|
|
log::debug!("Brain terminated list_nodes stream.");
|
|
Ok(nodes)
|
|
}
|