163 lines
4.9 KiB
163 lines
4.9 KiB
use super::JobType; |
|
use crate::{models::schema::*, UError, UResult}; |
|
use diesel::{Identifiable, Insertable, Queryable}; |
|
use guess_host_triple::guess_host_triple; |
|
use serde::{Deserialize, Serialize}; |
|
use std::fmt; |
|
use uuid::Uuid; |
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug, Queryable, Identifiable, Insertable)] |
|
#[table_name = "jobs"] |
|
pub struct JobMeta { |
|
pub alias: Option<String>, |
|
/// string like `bash -c {} -a 1 --arg2`, |
|
/// where {} is replaced by executable's tmp path |
|
pub argv: String, |
|
pub id: Uuid, |
|
pub exec_type: JobType, |
|
//pub schedule: JobSchedule, |
|
pub platform: String, |
|
pub payload: Option<Vec<u8>>, |
|
} |
|
|
|
impl JobMeta { |
|
pub fn builder() -> JobMetaBuilder { |
|
JobMetaBuilder::default() |
|
} |
|
|
|
pub fn from_shell<S: Into<String>>(cmd: S) -> UResult<Self> { |
|
Self::builder().with_shell(cmd).build() |
|
} |
|
} |
|
|
|
impl fmt::Display for JobMeta { |
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
let mut out = format!("Job: {}", self.id); |
|
if self.alias.is_some() { |
|
out += &format!(" ({})", self.alias.as_ref().unwrap()); |
|
} |
|
out += &format!("\nArgv: {}", self.argv); |
|
out += &format!("\nExecutable type: {}", self.exec_type); |
|
out += &format!("\nPlatform: {}", self.platform); |
|
if self.exec_type == JobType::Shell && self.payload.is_some() { |
|
let payload = self.payload.as_ref().unwrap(); |
|
let (pld_len, large) = { |
|
let pl = payload.len(); |
|
if pl > 20 { |
|
(20, true) |
|
} else { |
|
(pl, false) |
|
} |
|
}; |
|
let pld_beginning = payload |
|
.iter() |
|
.take(pld_len) |
|
.map(|u| *u) |
|
.collect::<Vec<u8>>(); |
|
out += &format!( |
|
"\nPayload: {}{}", |
|
String::from_utf8_lossy(&pld_beginning), |
|
if large { "" } else { " <...>" } |
|
); |
|
} |
|
write!(f, "{}", out) |
|
} |
|
} |
|
|
|
impl Default for JobMeta { |
|
fn default() -> Self { |
|
Self { |
|
id: Uuid::new_v4(), |
|
alias: None, |
|
argv: String::new(), |
|
exec_type: JobType::Shell, |
|
platform: guess_host_triple().unwrap_or("unknown").to_string(), |
|
payload: None, |
|
} |
|
} |
|
} |
|
|
|
pub struct JobMetaBuilder { |
|
inner: JobMeta, |
|
} |
|
|
|
impl Default for JobMetaBuilder { |
|
fn default() -> Self { |
|
Self { |
|
inner: JobMeta::default(), |
|
} |
|
} |
|
} |
|
|
|
impl JobMetaBuilder { |
|
pub fn with_shell<S: Into<String>>(mut self, shell_cmd: S) -> Self { |
|
self.inner.argv = shell_cmd.into(); |
|
self |
|
} |
|
|
|
pub fn with_payload<C: Into<Vec<u8>>>(mut self, payload: C) -> Self { |
|
self.inner.payload = Some(payload.into()); |
|
self |
|
} |
|
|
|
pub fn with_alias<S: Into<String>>(mut self, alias: S) -> Self { |
|
self.inner.alias = Some(alias.into()); |
|
self |
|
} |
|
|
|
pub fn with_type(mut self, e_type: JobType) -> Self { |
|
self.inner.exec_type = e_type; |
|
self |
|
} |
|
|
|
pub fn build(self) -> UResult<JobMeta> { |
|
let mut inner = self.inner; |
|
match inner.exec_type { |
|
JobType::Shell => { |
|
if inner.argv == "" { |
|
inner.argv = String::from("/bin/bash -c {}") |
|
} |
|
let argv_parts = |
|
shlex::split(&inner.argv).ok_or(UError::JobArgsError("Shlex failed".into()))?; |
|
let empty_err = UError::JobArgsError("Empty argv".into()); |
|
if argv_parts.get(0).ok_or(empty_err.clone())?.len() == 0 { |
|
return Err(empty_err); |
|
} |
|
match inner.payload.as_ref() { |
|
Some(_) => { |
|
if !inner.argv.contains("{}") { |
|
return Err(UError::JobArgsError( |
|
"Argv contains no executable placeholder".into(), |
|
)); |
|
} else { |
|
() |
|
} |
|
} |
|
None => { |
|
if inner.argv.contains("{}") { |
|
return Err(UError::JobArgsError( |
|
"No payload provided, but argv contains executable placeholder" |
|
.into(), |
|
)); |
|
} else { |
|
() |
|
} |
|
} |
|
}; |
|
Ok(inner) |
|
} |
|
JobType::Manage => Ok(inner), |
|
_ => todo!(), |
|
} |
|
} |
|
/* |
|
pub fn from_file(path: PathBuf) -> UResult<Self> { |
|
let data = fs::read(path) |
|
.map_err(|e| UError::FilesystemError( |
|
path.to_string_lossy().to_string(), |
|
e.to_string() |
|
))?; |
|
let filename = path.file_name().unwrap().to_str().unwrap(); |
|
|
|
}*/ |
|
}
|
|
|