136 lines
3.9 KiB

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<String>),
}
#[derive(StructOpt, Debug)]
enum JobMapCRUD {
Create {
#[structopt(parse(try_from_str = parse_uuid))]
agent_id: Id,
job_idents: Vec<String>,
},
#[structopt(flatten)]
RUD(RUD),
}
#[derive(StructOpt, Debug)]
enum RUD {
Read {
#[structopt(parse(try_from_str = parse_uuid))]
id: Option<Id>,
},
Update {
item: String,
},
Delete {
#[structopt(parse(try_from_str = parse_uuid))]
id: Id,
},
}
fn parse_uuid(src: &str) -> Result<Id, String> {
Id::parse_str(src).map_err(|e| e.to_string())
}
pub fn into_value<M: AsMsg>(data: M) -> Value {
to_value(data).unwrap()
}
pub async fn process_cmd(client: HttpClient, args: Args) -> PanelResult<Value> {
let catcher: UResult<Value> = (|| 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::<Agent>(&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::<RawJob>(&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::<RawJob>(&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::<AssignedJob>(&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),
}
}