You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.9 KiB
179 lines
4.9 KiB
use std::{ |
|
process::Command, |
|
time::SystemTime, |
|
cmp::PartialEq |
|
}; |
|
use serde::{ |
|
Serialize, |
|
Deserialize |
|
}; |
|
use uuid::Uuid; |
|
//use tokio::process::Command; |
|
use super::*; |
|
|
|
|
|
pub struct Job<'meta> { |
|
pub result: JobResult, |
|
pub meta: &'meta mut JobMeta, |
|
} |
|
|
|
impl<'meta> Job<'meta> { |
|
pub fn new(job_meta: &'meta mut JobMeta) -> Self { |
|
Self { |
|
result: JobResult { |
|
id: job_meta.id.clone(), |
|
state: job_meta.state.clone(), |
|
data: None, |
|
}, |
|
meta: job_meta, |
|
} |
|
} |
|
|
|
pub fn run(&mut self) { |
|
match self.meta.exec_type { |
|
JobType::Shell => { |
|
match self.meta.state { |
|
JobState::Queued | JobState::Pending => { |
|
self.meta.state = JobState::Running; |
|
}, |
|
JobState::Finished => { |
|
if self.meta.schedule == JobSchedule::Permanent { |
|
self.meta.state = JobState::Running; |
|
} else { |
|
return |
|
} |
|
}, |
|
JobState::Running => return |
|
} |
|
|
|
match &self.meta.payload { |
|
Some(box_payload) => { |
|
let payload = String::from_utf8_lossy(box_payload).into_owned(); |
|
let mut cmd_parts = payload |
|
.split(" ") |
|
.map(String::from) |
|
.collect::<Vec<String>>() |
|
.into_iter(); |
|
let cmd = cmd_parts.nth(0).unwrap(); |
|
let args = cmd_parts.collect::<Vec<_>>(); |
|
let result = Command::new(cmd) |
|
.args(args) |
|
.output(); |
|
self.result.data = Some(match result { |
|
Ok(output) => { |
|
if output.status.success() { |
|
Ok(output.stdout.to_vec()) |
|
} else { |
|
Err(output.stderr.to_vec()) |
|
} |
|
} |
|
Err(e) => Err(e.to_string().into_bytes()) |
|
}) |
|
} |
|
None => return |
|
} |
|
self.meta.state = JobState::Finished; |
|
}, |
|
_ => unimplemented!() |
|
} |
|
} |
|
|
|
fn into_result(self) -> JobResult { |
|
self.result |
|
} |
|
} |
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
pub enum ManageAction { |
|
Ping, |
|
UpdateAvailable, |
|
JobsResultsRequest, |
|
Terminate |
|
} |
|
|
|
#[derive(Serialize, Deserialize, Clone, PartialEq)] |
|
pub enum JobSchedule { |
|
Once, |
|
Permanent, |
|
Terminate // to terminate jobs obvsl |
|
//TODO: Scheduled |
|
} |
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
pub enum JobState { |
|
Queued, // server created a job, but client didn't get it yet |
|
Pending, // client got a job, but not running yet |
|
Running, // client is currently running a job |
|
// Rerunning, // if job is cycled |
|
Finished, |
|
} |
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
pub enum JobType { |
|
Manage(ManageAction), |
|
Shell, |
|
Python, |
|
Binary |
|
} |
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
pub struct JobMeta { |
|
pub id: Uuid, |
|
pub name: String, |
|
pub created: SystemTime, |
|
pub updated: SystemTime, |
|
pub state: JobState, |
|
pub exec_type: JobType, |
|
pub schedule: JobSchedule, |
|
pub append_result: bool, //true: append, false: rewrite |
|
pub payload: Option<Box<Vec<u8>>>, |
|
} |
|
|
|
impl JobMeta { |
|
pub fn from_shell(shell_cmd: Vec<u8>) -> Self { |
|
let uid = Uuid::new_v4(); |
|
//let str_payload_name: &[u8] = shell_cmd.split(|b| &[*b] == b" ").collect(); |
|
//let job_name = format!("{} {}", uid.to_string()[..6], str_payload_name[0]); |
|
Self { |
|
id: uid.clone(), |
|
name: uid.to_string(), |
|
created: SystemTime::now(), |
|
updated: SystemTime::now(), |
|
state: JobState::Pending, |
|
exec_type: JobType::Shell, |
|
schedule: JobSchedule::Once, |
|
append_result: true, |
|
payload: Some(Box::new(shell_cmd)) |
|
} |
|
} |
|
|
|
pub fn from_shell_str(shell_cmd: String) -> Self { |
|
Self::from_shell(shell_cmd.into_bytes()) |
|
} |
|
} |
|
|
|
impl ToMsg for JobMeta {} |
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
pub struct JobResult { |
|
id: Uuid, |
|
data: Option<Result<Vec<u8>, Vec<u8>>>, |
|
state: JobState |
|
} |
|
|
|
impl ToMsg for JobResult {} |
|
|
|
|
|
#[cfg(test)] |
|
mod tests { |
|
use super::*; |
|
use crate::execute_jobs; |
|
|
|
#[test] |
|
fn test_shell_job() { |
|
let mut job = JobMeta::from_shell_str("whoami".into()); |
|
let mut jobs: Vec<Job> = vec![Job::new(&mut job)]; |
|
execute_jobs(&mut jobs); |
|
assert_eq!(jobs.pop().unwrap().result.data.unwrap().unwrap(), b"plazmoid\n".to_vec()); |
|
} |
|
} |