almost reworked errors, cli rpc methods build macro

4-update-check
plazmoid 4 years ago
parent cb0c10e064
commit 6ad5c306e4
  1. 1
      bin/u_server/src/main.rs
  2. 2
      build_static_docker.sh
  3. 8
      cargo_static_docker.sh
  4. 11
      lib/u_lib/src/client/client.rs
  5. 109
      lib/u_lib/src/client/network.rs
  6. 61
      lib/u_lib/src/contracts/jobs.rs
  7. 5
      lib/u_lib/src/contracts/messaging.rs
  8. 11
      lib/u_lib/src/contracts/mod.rs
  9. 76
      lib/u_lib/src/errors.rs
  10. 5
      lib/u_lib/src/utils.rs

@ -37,7 +37,6 @@ async fn main() {
.and_then(handlers::listing); .and_then(handlers::listing);
let auth_token = warp::header::exact("authorization", "Bearer 123qwe"); let auth_token = warp::header::exact("authorization", "Bearer 123qwe");
//.and_then(handlers::check_token);
let auth_zone = auth_token.and(ls); let auth_zone = auth_token.and(ls);

@ -1,2 +0,0 @@
#!/bin/bash
docker run -v $PWD:/volume -w /volume -it clux/muslrust cargo build

@ -0,0 +1,8 @@
#!/bin/bash
docker run \
-v $PWD:/volume \
-v cargo-cache:/root/.cargo/registry \
-w /volume \
-it \
clux/muslrust \
cargo $@

@ -1,6 +1,5 @@
use std::{ use std::{
collections::HashMap, collections::HashMap
fmt
}; };
use serde::{ use serde::{
@ -39,7 +38,7 @@ impl ClientInfo {
let job_result = exec_job(&mut job_meta); let job_result = exec_job(&mut job_meta);
let job_data = match job_result.data { let job_data = match job_result.data {
Ok(output) => output.multiline(), Ok(output) => output.multiline(),
Err(e) => e.description() Err(e) => e.to_string()
}; };
info.insert(job.0.into(), job_data); info.insert(job.0.into(), job_data);
} }
@ -67,14 +66,16 @@ const DEFAULT_JOBS: &[(&str, &str)] = &[
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::utils::vec_to_string;
#[test] #[test]
fn test_gather() { fn test_gather() {
let cli_info = ClientInfo::gather(); let cli_info = ClientInfo::gather();
let field = cli_info.get_field("username").unwrap(); let field = cli_info.get_field("username").unwrap();
let stdout = JobOutput::from_multiline(field).unwrap().stdout;
assert_eq!( assert_eq!(
JobOutput::from_multiline(field).unwrap().stdout, &vec_to_string(&stdout),
b"plazmoid".to_vec() "plazmoid"
) )
} }

@ -2,6 +2,7 @@ use crate::{
MASTER_SERVER, MASTER_SERVER,
MASTER_PORT, MASTER_PORT,
contracts::*, contracts::*,
UResult
}; };
use reqwest::{ use reqwest::{
Client, Client,
@ -11,13 +12,24 @@ use reqwest::{
}; };
use std::{ use std::{
net::Ipv4Addr, net::Ipv4Addr,
str::FromStr str::FromStr,
any::Any
}; };
pub struct Paths;
impl Paths {
pub const LIST: &'static str = "list";
pub const NEW: &'static str = "new";
//pub const DEL: &'static str = "del";
pub const JOB_REQ: &'static str = "job_req";
pub const JOB_ANS: &'static str = "job_ans";
}
pub struct ClientHandler { pub struct ClientHandler {
base_url: Url, base_url: Url,
client: Client, client: Client,
cli_info: ClientInfo,
password: Option<String> password: Option<String>
} }
@ -28,7 +40,6 @@ impl ClientHandler {
.unwrap_or(MASTER_SERVER); .unwrap_or(MASTER_SERVER);
Self { Self {
client: Client::new(), client: Client::new(),
cli_info: ClientInfo::gather(),
base_url: Url::parse( base_url: Url::parse(
&format!("http://{}:{}", master_server, MASTER_PORT) &format!("http://{}:{}", master_server, MASTER_PORT)
).unwrap(), ).unwrap(),
@ -58,28 +69,90 @@ impl ClientHandler {
self.set_pwd(rb) self.set_pwd(rb)
} }
pub async fn init(&self) -> RawMsg { // move to result pub async fn init(&self, param: &ClientInfo) -> UResult<RawMsg> {
let response: Response = self.build_post("/new") let response: Response = self.build_post(Paths::NEW)
.json(&self.cli_info.as_message()) .json(&param.as_message())
.send() .send()
.await .await?;
.unwrap();
let msg = response let msg = response
.json::<Message<RawMsg>>() .json::<Message<RawMsg>>()
.await .await?;
.unwrap(); Ok(msg.into_item().into_owned())
msg.into_item().into_owned()
} }
pub async fn list(&self) -> Vec<ClientInfo> { pub async fn list(&self) -> UResult<Vec<ClientInfo>> {
let response: Response = self.build_get("/ls") let response: Response = self.build_get(Paths::LIST)
.send() .send()
.await .await?;
.unwrap();
let msg = response let msg = response
.json::<Message<Vec<ClientInfo>>>() .json::<Message<Vec<ClientInfo>>>()
.await .await?;
.unwrap(); Ok(msg.into_item().into_owned())
msg.into_item().into_owned() }
/*
pub async fn del(&self) -> UResult<()> {
self.build_post(Paths::DEL).send().await?;
Ok(())
}*/
} }
// build_handler![path = new, method = "post", param = ClientInfo, result = RawMsg]
// param and result must impl ToMsg
macro_rules! build_handler {
(
path = $path:tt,
method = $method:literal,
param = $param:ty,
result = $result:ty
) => {
impl ClientHandler {
pub async fn $path(&self, param: &$param) -> UResult<$result> {
let builder = match $method {
"post" => ClientHandler::build_post,
"get" => ClientHandler::build_get,
_ => panic!("Method '{}' is not allowed", $method)
};
let base_request = builder(self, stringify!($path));
let request = if let Some(p) = (param as &dyn Any).downcast_ref::<EmptyMsg>() {
base_request
} else {
base_request.json(&param.as_message())
};
let response = request.send().await?;
let msg = response
.json::<Message<$result>>()
.await?;
Ok(msg.into_item().into_owned())
} }
}
impl Paths {
pub const $path: &'static str = stringify!($path);
}
};
(
path = $path:tt,
method = $method:literal
) => (
build_handler!(path = $path, method = $method, param = EmptyMsg, result = EmptyMsg);
);
(
path = $path:tt,
method = $method:literal,
param = $param:ty
) => (
build_handler!(path = $path, method = $method, param = $param, result = EmptyMsg);
);
(
path = $path:tt,
method = $method:literal,
result = $result:ty
) => (
build_handler!(path = $path, method = $method, param = EmptyMsg, result = $result);
);
}
build_handler!(path = del, method = "post");

@ -10,7 +10,7 @@ use serde::{
use uuid::Uuid; use uuid::Uuid;
//use tokio::process::Command; //use tokio::process::Command;
use super::*; use super::*;
use crate::UError; use crate::{UError, UErrType};
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
@ -61,10 +61,9 @@ pub struct JobMeta {
impl JobMeta { impl JobMeta {
pub fn from_shell(shell_cmd: String) -> Self { pub fn from_shell(shell_cmd: String) -> Self {
let uid = Uuid::new_v4();
let job_name = shell_cmd.split(" ").nth(0).unwrap(); let job_name = shell_cmd.split(" ").nth(0).unwrap();
Self { Self {
id: uid.clone(), id: Uuid::new_v4(),
name: job_name.to_string(), name: job_name.to_string(),
created: SystemTime::now(), created: SystemTime::now(),
updated: SystemTime::now(), updated: SystemTime::now(),
@ -154,8 +153,8 @@ impl ToMsg for JobResult {}
pub struct Job<'meta> { pub struct Job<'meta> {
pub result: JobResult, result: JobResult,
pub meta: &'meta mut JobMeta, meta: &'meta mut JobMeta,
} }
impl<'meta> Job<'meta> { impl<'meta> Job<'meta> {
@ -210,7 +209,7 @@ impl<'meta> Job<'meta> {
} }
Err(e) => { Err(e) => {
self.result.data = Err( self.result.data = Err(
UError::Raw(e.to_string()) UError::new(UErrType::JobError, Some(e))
); );
self.result.retcode = None; self.result.retcode = None;
} }
@ -248,7 +247,10 @@ impl<'meta> Job<'meta> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::execute_jobs; use crate::{
execute_jobs,
utils::vec_to_string
};
#[test] #[test]
fn test_shell_job() { fn test_shell_job() {
@ -257,8 +259,8 @@ mod tests {
execute_jobs(&mut jobs); execute_jobs(&mut jobs);
let job_result = jobs.pop().unwrap().into_result(); let job_result = jobs.pop().unwrap().into_result();
assert_eq!( assert_eq!(
job_result.data.unwrap().stdout, &vec_to_string(&job_result.data.unwrap().stdout),
b"plazmoid\n".to_vec() "plazmoid"
); );
} }
@ -271,4 +273,45 @@ mod tests {
assert!(job_result.data.is_err()); assert!(job_result.data.is_err());
assert_eq!(job_result.retcode, None); assert_eq!(job_result.retcode, None);
} }
#[test]
fn test_to_multiline() {
let mut output = JobOutput::new();
output.stdout = b"lol".to_vec();
output.stderr = b"kek".to_vec();
assert_eq!(
output.multiline(),
String::from(
"*** STDOUT ***\n\
lol\n\
*** STDERR ***\n\
kek\n"
)
)
}
#[test]
fn test_to_multiline_stderr_only() {
let mut output = JobOutput::new();
output.stderr = b"kek".to_vec();
assert_eq!(
output.multiline(),
String::from(
"*** STDERR ***\n\
kek\n"
)
)
}
#[test]
fn test_from_multiline() {
let txt = "*** STDOUT ***\n\
puk\n".to_string();
let output = JobOutput::from_multiline(&txt).unwrap();
assert_eq!(
output.stdout,
b"puk".to_vec()
);
assert_eq!(output.stderr.len(), 0);
}
} }

@ -54,7 +54,10 @@ where I: Clone {
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RawMsg(pub String); pub struct RawMsg(pub String);
impl ToMsg for RawMsg {}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct EmptyMsg;
/* /*
#[cfg(test)] #[cfg(test)]

@ -13,9 +13,11 @@ use std::{
borrow::Cow borrow::Cow
}; };
macro_rules! to_message {
($($type:ty),+) => { $(
impl ToMsg for $type {}
macro_rules! to_cow {
($type:ty) => {
impl<'cow> From<$type> for Cow<'cow, $type> { impl<'cow> From<$type> for Cow<'cow, $type> {
#[inline] #[inline]
fn from(obj: $type) -> Cow<'cow, $type> { fn from(obj: $type) -> Cow<'cow, $type> {
@ -28,9 +30,8 @@ macro_rules! to_cow {
fn from(obj: &'cow $type) -> Cow<'cow, $type> { fn from(obj: &'cow $type) -> Cow<'cow, $type> {
Cow::Borrowed(obj) Cow::Borrowed(obj)
} }
} } )+
} }
} }
to_cow!(ClientInfo); to_message!(ClientInfo, RawMsg, EmptyMsg);
to_cow!(RawMsg);

@ -1,27 +1,87 @@
use std::fmt; use std::fmt;
use std::error::Error as StdError;
use reqwest::Error as ReqError;
use serde::{ use serde::{
Serialize, Serialize,
Deserialize Deserialize
}; };
#[derive(Serialize, Deserialize, Clone)] pub type BoxError = Box<(dyn StdError + Send + Sync + 'static)>;
pub enum UError { pub type UResult<T> = std::result::Result<T, UError>;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum UErrType {
ConnectionError,
ParseError,
JobError,
Unknown,
Raw(String) Raw(String)
} }
#[derive(Serialize, Deserialize, Clone, Debug)]
struct Inner {
err_type: UErrType,
source: Option<BoxError>
}
#[derive(Serialize, Deserialize, Clone)]
pub struct UError {
inner: Box<Inner>
}
impl UError { impl UError {
pub fn description(&self) -> String { pub fn new<E: Into<BoxError>>(err_type: UErrType, source: Option<E>) -> Self {
match self { Self {
UError::Raw(msg) => msg.clone() inner: Box::new(Inner {
source: source.map(Into::into),
err_type
})
} }
} }
} }
impl fmt::Debug for UError { impl fmt::Debug for UError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let msg = match self { let mut builder = f.debug_struct("errors::UError");
UError::Raw(msg) => msg
builder.field("kind", &self.inner.err_type);
if let Some(ref source) = self.inner.source {
builder.field("source", source);
}
builder.finish()
}
}
impl fmt::Display for UError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let e_type = match self.inner.err_type {
UErrType::Raw(ref msg) => msg,
UErrType::ConnectionError => "Connection error",
UErrType::ParseError => "Parse error",
UErrType::JobError => "Job error",
UErrType::Unknown => "Unknown error",
};
f.write_str(e_type)?;
if let Some(ref e) = self.inner.source {
write!(f, ": {}", e)
} else {
Ok(())
}
}
}
impl From<ReqError> for UError {
fn from(e: ReqError) -> Self {
let err_type = if e.is_request() {
UErrType::ConnectionError
} else if e.is_decode() {
UErrType::ParseError
} else {
UErrType::Unknown
}; };
write!(f, "{}", msg) UError::new(err_type, Some(e))
} }
} }

@ -45,6 +45,11 @@ pub fn setsig(sig: Signal, hnd: SigHandler) {
signal(sig, hnd).unwrap(); signal(sig, hnd).unwrap();
} }
} }
pub fn vec_to_string(v: &Vec<u8>) -> String {
String::from_utf8_lossy(v).to_string()
}
/* /*
pub fn generate_auth_token() -> String { pub fn generate_auth_token() -> String {

Loading…
Cancel
Save