use serde_json::{from_str, to_value, Value}; use structopt::StructOpt; use u_lib::{ api::HttpClient, jobs::join_payload, messaging::AsMsg, models::{Agent, AssignedJob, RawJob}, types::Id, types::PanelResult, UError, UResult, }; #[derive(StructOpt, Debug)] pub struct Args { #[structopt(subcommand)] cmd: Cmd, } #[derive(StructOpt, Debug)] enum Cmd { Agents(RUD), Jobs(JobCRUD), Map(JobMapCRUD), Ping, Serve, } #[derive(StructOpt, Debug)] enum JobCRUD { Create { job: String, }, #[structopt(flatten)] RUD(RUD), } #[derive(StructOpt, Debug)] enum JobCmd { #[structopt(external_subcommand)] Cmd(Vec), } #[derive(StructOpt, Debug)] enum JobMapCRUD { Create { #[structopt(parse(try_from_str = parse_uuid))] agent_id: Id, job_idents: Vec, }, #[structopt(flatten)] RUD(RUD), } #[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)?; into_value(client.update_agent(&agent).await?) } RUD::Delete { id } => into_value(client.del(id).await?), }, Cmd::Jobs(action) => match action { JobCRUD::Create { job } => { let raw_job = from_str::(&job)?; let job = raw_job.validated()?; let fat_job = join_payload(job)?; into_value(client.upload_jobs(&fat_job).await?) } JobCRUD::RUD(RUD::Read { id }) => match id { //todo: use vec not to break frontend api, possibly refactor later Some(id) => into_value(vec![client.get_job(id, false).await?]), None => into_value(client.get_jobs().await?), }, JobCRUD::RUD(RUD::Update { item }) => { let raw_job = from_str::(&item)?; let job = raw_job.validated()?; into_value(client.update_job(&join_payload(job)?).await?) } JobCRUD::RUD(RUD::Delete { id }) => into_value(client.del(id).await?), }, Cmd::Map(action) => match action { JobMapCRUD::Create { agent_id, job_idents, } => into_value(client.set_jobs(agent_id, &job_idents).await?), JobMapCRUD::RUD(RUD::Read { id }) => into_value(client.get_agent_jobs(id).await?), JobMapCRUD::RUD(RUD::Update { item }) => { let assigned = from_str::(&item)?; into_value(client.update_result(&assigned).await?) } JobMapCRUD::RUD(RUD::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), } }