feat: add filtering and listing functionality for app nodes
This commit is contained in:
parent
1fa37a0bb9
commit
952c62c218
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -420,7 +420,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/noormohammedb/detee-shared?branch=stable_01#8230e1f831d0f88fe5203646e323bf215a825574"
|
source = "git+ssh://git@gitea.detee.cloud/noormohammedb/detee-shared?branch=stable_01#a9dcfbe9fec5a86cd69aa2853db124aae9b85598"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"prost",
|
"prost",
|
||||||
|
52
src/data.rs
52
src/data.rs
@ -15,6 +15,8 @@ use tokio::sync::oneshot::Sender as OneshotSender;
|
|||||||
|
|
||||||
use detee_shared::sgx::pb::brain::brain_message_app;
|
use detee_shared::sgx::pb::brain::brain_message_app;
|
||||||
use detee_shared::sgx::pb::brain::AppContract as AppContractPB;
|
use detee_shared::sgx::pb::brain::AppContract as AppContractPB;
|
||||||
|
use detee_shared::sgx::pb::brain::AppNodeFilters;
|
||||||
|
use detee_shared::sgx::pb::brain::AppNodeListResp;
|
||||||
use detee_shared::sgx::pb::brain::AppNodeResources;
|
use detee_shared::sgx::pb::brain::AppNodeResources;
|
||||||
use detee_shared::sgx::pb::brain::AppResource as AppResourcePB;
|
use detee_shared::sgx::pb::brain::AppResource as AppResourcePB;
|
||||||
use detee_shared::sgx::pb::brain::BrainMessageApp;
|
use detee_shared::sgx::pb::brain::BrainMessageApp;
|
||||||
@ -266,6 +268,21 @@ pub struct AppNode {
|
|||||||
pub offline_minutes: u64,
|
pub offline_minutes: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<AppNode> for AppNodeListResp {
|
||||||
|
fn from(value: AppNode) -> Self {
|
||||||
|
Self {
|
||||||
|
operator: value.operator_wallet,
|
||||||
|
node_pubkey: value.node_pubkey,
|
||||||
|
country: value.country,
|
||||||
|
region: value.region,
|
||||||
|
city: value.city,
|
||||||
|
ip: value.ip,
|
||||||
|
price: value.price,
|
||||||
|
reports: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize)]
|
#[derive(Default, Serialize, Deserialize)]
|
||||||
pub struct BrainData {
|
pub struct BrainData {
|
||||||
accounts: DashMap<String, AccountData>,
|
accounts: DashMap<String, AccountData>,
|
||||||
@ -1199,6 +1216,41 @@ impl BrainData {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_app_nodes_by_filters(&self, filters: &AppNodeFilters) -> Vec<AppNode> {
|
||||||
|
let nodes = self.app_nodes.read().unwrap();
|
||||||
|
nodes
|
||||||
|
.iter()
|
||||||
|
.filter(|n| {
|
||||||
|
n.avail_vcpus >= filters.vcpus
|
||||||
|
&& n.avail_mem_mb >= filters.memory_mb
|
||||||
|
&& n.avail_storage_mb >= filters.storage_mb
|
||||||
|
&& (filters.country.is_empty() || (n.country == filters.country))
|
||||||
|
&& (filters.city.is_empty() || (n.city == filters.city))
|
||||||
|
&& (filters.region.is_empty() || (n.region == filters.region))
|
||||||
|
&& (filters.ip.is_empty() || (n.ip == filters.ip))
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: sort by rating
|
||||||
|
pub fn get_one_app_node_by_filters(&self, filters: &AppNodeFilters) -> Option<AppNode> {
|
||||||
|
let nodes = self.app_nodes.read().unwrap();
|
||||||
|
nodes
|
||||||
|
.iter()
|
||||||
|
.find(|n| {
|
||||||
|
n.avail_vcpus >= filters.vcpus
|
||||||
|
&& n.avail_mem_mb >= filters.memory_mb
|
||||||
|
&& n.avail_storage_mb >= filters.storage_mb
|
||||||
|
&& (filters.country.is_empty() || (n.country == filters.country))
|
||||||
|
&& (filters.city.is_empty() || (n.city == filters.city))
|
||||||
|
&& (filters.region.is_empty() || (n.region == filters.region))
|
||||||
|
&& (filters.ip.is_empty() || (n.ip == filters.ip))
|
||||||
|
&& (filters.node_pubkey.is_empty() || (n.node_pubkey == filters.node_pubkey))
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_app_contract_by_uuid(&self, uuid: &str) -> Result<AppContract, Error> {
|
pub fn find_app_contract_by_uuid(&self, uuid: &str) -> Result<AppContract, Error> {
|
||||||
let contracts = self.app_contracts.read().unwrap();
|
let contracts = self.app_contracts.read().unwrap();
|
||||||
contracts
|
contracts
|
||||||
|
37
src/grpc.rs
37
src/grpc.rs
@ -17,8 +17,8 @@ use tonic::{Request, Response, Status, Streaming};
|
|||||||
use detee_shared::sgx::pb::brain::brain_app_cli_server::BrainAppCli;
|
use detee_shared::sgx::pb::brain::brain_app_cli_server::BrainAppCli;
|
||||||
use detee_shared::sgx::pb::brain::brain_app_daemon_server::BrainAppDaemon;
|
use detee_shared::sgx::pb::brain::brain_app_daemon_server::BrainAppDaemon;
|
||||||
use detee_shared::sgx::pb::brain::{
|
use detee_shared::sgx::pb::brain::{
|
||||||
AppContract, BrainMessageApp, DaemonMessageApp, DelAppReq, ListAppContractsReq, NewAppReq,
|
AppContract, AppNodeFilters, AppNodeListResp, BrainMessageApp, DaemonMessageApp, DelAppReq,
|
||||||
NewAppRes, RegisterAppNodeReq,
|
ListAppContractsReq, NewAppReq, NewAppRes, RegisterAppNodeReq,
|
||||||
};
|
};
|
||||||
const ADMIN_ACCOUNTS: &[&str] = &[
|
const ADMIN_ACCOUNTS: &[&str] = &[
|
||||||
"x52w7jARC5erhWWK65VZmjdGXzBK6ZDgfv1A283d8XK",
|
"x52w7jARC5erhWWK65VZmjdGXzBK6ZDgfv1A283d8XK",
|
||||||
@ -457,6 +457,7 @@ trait PubkeyGetter {
|
|||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl BrainAppCli for BrainAppCliMock {
|
impl BrainAppCli for BrainAppCliMock {
|
||||||
type ListAppContractsStream = Pin<Box<dyn Stream<Item = Result<AppContract, Status>> + Send>>;
|
type ListAppContractsStream = Pin<Box<dyn Stream<Item = Result<AppContract, Status>> + Send>>;
|
||||||
|
type ListAppNodesStream = Pin<Box<dyn Stream<Item = Result<AppNodeListResp, Status>> + Send>>;
|
||||||
|
|
||||||
async fn deploy_app(
|
async fn deploy_app(
|
||||||
&self,
|
&self,
|
||||||
@ -516,6 +517,37 @@ impl BrainAppCli for BrainAppCliMock {
|
|||||||
Box::pin(output_stream) as Self::ListAppContractsStream
|
Box::pin(output_stream) as Self::ListAppContractsStream
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn list_app_nodes(
|
||||||
|
&self,
|
||||||
|
req: tonic::Request<AppNodeFilters>,
|
||||||
|
) -> Result<tonic::Response<Self::ListAppNodesStream>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
info!("CLI requested ListAppNodes: {req:?}");
|
||||||
|
let nodes = self.data.find_app_nodes_by_filters(&req);
|
||||||
|
let (tx, rx) = mpsc::channel(6);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
for node in nodes {
|
||||||
|
let _ = tx.send(Ok(node.into())).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let output_stream = ReceiverStream::new(rx);
|
||||||
|
Ok(Response::new(Box::pin(output_stream)))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_one_app_node(
|
||||||
|
&self,
|
||||||
|
req: tonic::Request<AppNodeFilters>,
|
||||||
|
) -> Result<tonic::Response<AppNodeListResp>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
info!("CLI requested GetOneAppNode: {req:?}");
|
||||||
|
match self.data.get_one_app_node_by_filters(&req) {
|
||||||
|
Some(node) => Ok(Response::new(node.into())),
|
||||||
|
None => Err(Status::not_found(
|
||||||
|
"Could not find any node based on your search criteria",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
@ -681,6 +713,7 @@ impl_pubkey_getter!(DelAppReq, admin_pubkey);
|
|||||||
impl_pubkey_getter!(ListAppContractsReq, admin_pubkey);
|
impl_pubkey_getter!(ListAppContractsReq, admin_pubkey);
|
||||||
|
|
||||||
impl_pubkey_getter!(RegisterAppNodeReq);
|
impl_pubkey_getter!(RegisterAppNodeReq);
|
||||||
|
impl_pubkey_getter!(AppNodeFilters);
|
||||||
|
|
||||||
fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Result<T, Status> {
|
fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Result<T, Status> {
|
||||||
let time = match req.metadata().get("timestamp") {
|
let time = match req.metadata().get("timestamp") {
|
||||||
|
Loading…
Reference in New Issue
Block a user