use serde_json::{from_str, to_value, Value}; use structopt::StructOpt; use u_lib::{ api::HttpClient, messaging::AsMsg, models::*, types::Id, types::PanelResult, UError, UResult, }; #[derive(StructOpt, Debug)] pub struct Args { #[structopt(subcommand)] cmd: Cmd, #[structopt(short, long, default_value)] brief: BriefMode, } #[derive(StructOpt, Debug)] enum Cmd { Agents(RUD), Jobs(CRUD), Map(MapCRUD), Payloads(PayloadCRUD), Ping, Serve, } #[derive(StructOpt, Debug)] enum CRUD { Create { item: String, }, #[structopt(flatten)] RUD(RUD), } #[derive(StructOpt, Debug)] enum MapCRUD { Create { #[structopt(parse(try_from_str = parse_uuid))] agent_id: Id, job_idents: Vec, }, #[structopt(flatten)] RUD(RUD), } #[derive(StructOpt, Debug)] enum PayloadCRUD { Create { item: String, }, Read { id: Option, }, Update { item: String, }, Delete { #[structopt(parse(try_from_str = parse_uuid))] id: Id, }, } #[derive(StructOpt, Debug)] enum RUD { Read { #[structopt(parse(try_from_str = parse_uuid))] id: Option, }, Update { item: String, }, Delete { #[structopt(parse(try_from_str = parse_uuid))] id: Id, }, } fn parse_uuid(src: &str) -> Result { Id::parse_str(src).map_err(|e| e.to_string()) } pub fn into_value(data: M) -> Value { to_value(data).unwrap() } pub async fn process_cmd(client: HttpClient, args: Args) -> PanelResult { let catcher: UResult = (|| async { Ok(match args.cmd { Cmd::Agents(action) => match action { RUD::Read { id } => into_value(client.get_agents(id).await?), RUD::Update { item } => { let agent = from_str::(&item) .map_err(|e| UError::DeserializeError(e.to_string(), item))?; into_value(client.update_agent(&agent).await?) } RUD::Delete { id } => into_value(client.del(id).await?), }, Cmd::Jobs(action) => match action { CRUD::Create { item: job } => { let raw_job = from_str::(&job) .map_err(|e| UError::DeserializeError(e.to_string(), job))?; let mut job = raw_job.validated()?; if let Some(payload) = &mut job.payload { payload.join_payload()?; } into_value(client.upload_jobs([&job]).await?) } CRUD::RUD(RUD::Read { id }) => match id { Some(id) => into_value(vec![client.get_job(id, args.brief).await?]), None => into_value(client.get_jobs().await?), }, CRUD::RUD(RUD::Update { item }) => { let raw_job = from_str::(&item) .map_err(|e| UError::DeserializeError(e.to_string(), item))?; let mut job = raw_job.validated()?; if let Some(payload) = &mut job.payload { payload.join_payload()?; } into_value(client.update_job(&job).await?) } CRUD::RUD(RUD::Delete { id }) => into_value(client.del(id).await?), }, Cmd::Map(action) => match action { MapCRUD::Create { agent_id, job_idents, } => into_value(client.set_jobs(agent_id, &job_idents).await?), MapCRUD::RUD(RUD::Read { id }) => into_value(client.get_assigned_jobs(id).await?), MapCRUD::RUD(RUD::Update { item }) => { let assigned = from_str::(&item) .map_err(|e| UError::DeserializeError(e.to_string(), item))?; into_value(client.update_result(&assigned).await?) } MapCRUD::RUD(RUD::Delete { id }) => into_value(client.del(id).await?), }, Cmd::Payloads(action) => match action { PayloadCRUD::Create { item } => { let payload = from_str::(&item) .map_err(|e| UError::DeserializeError(e.to_string(), item))?; into_value(client.upload_payloads([&payload]).await?) } PayloadCRUD::Read { id } => match id { None => into_value(client.get_payloads().await?), Some(id) => into_value(client.get_payload(id, args.brief).await?), }, PayloadCRUD::Update { item } => { let payload = from_str::(&item) .map_err(|e| UError::DeserializeError(e.to_string(), item))?; into_value(client.update_payload(&payload).await?) } PayloadCRUD::Delete { id } => into_value(client.del(id).await?), }, Cmd::Ping => into_value(client.ping().await?), Cmd::Serve => { crate::gui::serve(client) .await .map_err(|e| UError::PanelError(format!("{e:?}")))?; Value::Null } }) })() .await; match catcher { Ok(r) => PanelResult::Ok(r), Err(e) => PanelResult::Err(e), } }