|
|
|
@ -1,39 +1,65 @@ |
|
|
|
|
use std::{ |
|
|
|
|
process::Command, |
|
|
|
|
time::SystemTime |
|
|
|
|
time::SystemTime, |
|
|
|
|
cmp::PartialEq |
|
|
|
|
}; |
|
|
|
|
use serde::{ |
|
|
|
|
Serialize, |
|
|
|
|
Deserialize |
|
|
|
|
}; |
|
|
|
|
use uuid::Uuid; |
|
|
|
|
//use tokio::process::Command;
|
|
|
|
|
use super::*; |
|
|
|
|
|
|
|
|
|
pub type JobPool = Vec<ShellJob>; |
|
|
|
|
pub type JobResult = Result<Vec<u8>, Vec<u8>>; |
|
|
|
|
|
|
|
|
|
pub struct ShellJob { |
|
|
|
|
pub struct Job<'meta> { |
|
|
|
|
pub result: JobResult, |
|
|
|
|
pub cmd: String, |
|
|
|
|
pub args: Vec<String> |
|
|
|
|
pub meta: &'meta mut JobMeta, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl ShellJob { |
|
|
|
|
pub fn from_raw(raw_cmd: String) -> Self { |
|
|
|
|
let mut cmd_parts = raw_cmd |
|
|
|
|
.split(" ") |
|
|
|
|
.map(String::from) |
|
|
|
|
.collect::<Vec<String>>(); |
|
|
|
|
let args: Vec<_> = cmd_parts.drain(1..).collect(); |
|
|
|
|
impl<'meta> Job<'meta> { |
|
|
|
|
pub fn new(job_meta: &'meta mut JobMeta) -> Self { |
|
|
|
|
Self { |
|
|
|
|
cmd: cmd_parts.into_iter().nth(1).unwrap(), |
|
|
|
|
args, |
|
|
|
|
result: Err(b"Did not run".to_vec()) |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn run(&mut self) { |
|
|
|
|
let result = Command::new(&self.cmd) |
|
|
|
|
.args(&self.args) |
|
|
|
|
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 = match result { |
|
|
|
|
self.result.data = Some(match result { |
|
|
|
|
Ok(output) => { |
|
|
|
|
if output.status.success() { |
|
|
|
|
Ok(output.stdout.to_vec()) |
|
|
|
@ -42,14 +68,22 @@ impl ShellJob { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Err(e) => Err(e.to_string().into_bytes()) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
None => return |
|
|
|
|
} |
|
|
|
|
self.meta.state = JobState::Finished; |
|
|
|
|
}, |
|
|
|
|
_ => unimplemented!() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn get_result(&self) -> &JobResult { |
|
|
|
|
&self.result |
|
|
|
|
fn into_result(self) -> JobResult { |
|
|
|
|
self.result |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
|
pub enum ManageAction { |
|
|
|
|
Ping, |
|
|
|
|
UpdateAvailable, |
|
|
|
@ -57,21 +91,24 @@ pub enum ManageAction { |
|
|
|
|
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 { |
|
|
|
|
Dummy, |
|
|
|
|
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
|
|
|
|
|
// Rerunning, // if job is cycled
|
|
|
|
|
Finished, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
|
pub enum JobType { |
|
|
|
|
Manage(ManageAction), |
|
|
|
|
Shell, |
|
|
|
@ -79,33 +116,64 @@ pub enum JobType { |
|
|
|
|
Binary |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)] |
|
|
|
|
pub struct JobMeta { |
|
|
|
|
id: Uuid, |
|
|
|
|
name: String, |
|
|
|
|
created: SystemTime, |
|
|
|
|
updated: SystemTime, |
|
|
|
|
state: JobState, |
|
|
|
|
exec_type: JobType, |
|
|
|
|
append_result: bool, //true: append, false: rewrite
|
|
|
|
|
payload: Option<Vec<u8>>, |
|
|
|
|
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 = shell_cmd.split(b" ").collect(); |
|
|
|
|
let job_name = format!("{} {}", uid.to_string()[..6], str_payload_name[0]); |
|
|
|
|
//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, |
|
|
|
|
name: job_name, |
|
|
|
|
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(shell_cmd) |
|
|
|
|
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()); |
|
|
|
|
} |
|
|
|
|
} |