cosmetics, remove backtrace

pull/1/head
plazmoid 2 years ago
parent c60890fd67
commit 83252b6f95
  1. 1
      .env
  2. 9
      Makefile.toml
  3. 6
      bin/u_panel/src/argparse.rs
  4. 38
      bin/u_server/src/db.rs
  5. 22
      bin/u_server/src/errors.rs
  6. 99
      bin/u_server/src/handlers.rs
  7. 41
      bin/u_server/src/init.rs
  8. 2
      bin/u_server/src/main.rs
  9. 8
      bin/u_server/src/u_server.rs
  10. 1
      integration/Cargo.toml
  11. 6
      integration/docker-compose.yml
  12. 38
      integration/tests/helpers/panel.rs
  13. 4
      integration/tests/lib.rs
  14. 12
      lib/u_api_proc_macro/src/lib.rs
  15. 3
      lib/u_lib/Cargo.toml
  16. 8
      lib/u_lib/src/builder.rs
  17. 6
      lib/u_lib/src/datatypes.rs
  18. 8
      lib/u_lib/src/errors/chan.rs
  19. 52
      lib/u_lib/src/errors/variants.rs
  20. 2
      lib/u_lib/src/lib.rs
  21. 5
      lib/u_lib/src/messaging/base.rs
  22. 6
      lib/u_lib/src/models/jobs/assigned.rs
  23. 4
      lib/u_lib/src/utils/combined_result.rs

@ -2,3 +2,4 @@ DB_HOST=u_db
DB_NAME=u_db DB_NAME=u_db
DB_USER=postgres DB_USER=postgres
RUST_BACKTRACE=1 RUST_BACKTRACE=1
U_SERVER=u_server

@ -4,11 +4,12 @@ default_to_workspace = false
[env] [env]
TARGET = "x86_64-unknown-linux-musl" TARGET = "x86_64-unknown-linux-musl"
CARGO = "cargo" CARGO = "cargo"
PREFIX = "${CARGO_MAKE_WORKING_DIRECTORY}/static" ROOTDIR = "${CARGO_MAKE_WORKING_DIRECTORY}"
STATIC_PREFIX = "${ROOTDIR}/static"
PQ_LIB_STATIC_X86_64_UNKNOWN_LINUX_MUSL = "true" PQ_LIB_STATIC_X86_64_UNKNOWN_LINUX_MUSL = "true"
PG_CONFIG_X86_64_UNKNOWN_LINUX_GNU = "${PREFIX}/bin/pg_config" PG_CONFIG_X86_64_UNKNOWN_LINUX_GNU = "${STATIC_PREFIX}/bin/pg_config"
OPENSSL_STATIC = "true" OPENSSL_STATIC = "true"
OPENSSL_DIR = "${PREFIX}" OPENSSL_DIR = "${STATIC_PREFIX}"
[tasks.build_static_libs] [tasks.build_static_libs]
script = "./scripts/build_musl_libs.sh" script = "./scripts/build_musl_libs.sh"
@ -32,7 +33,7 @@ args = ["build", "--target", "${TARGET}", "${@}"]
script = ''' script = '''
if [[ "${@}" =~ "--release" ]]; then if [[ "${@}" =~ "--release" ]]; then
echo "Creating symlink to release dir..." echo "Creating symlink to release dir..."
ln -s ./target/${TARGET}/release ./release || true ln -s ${ROOTDIR}/target/${TARGET}/release ${ROOTDIR}/release || true
BINS=$(ls ./release/u_* -1 | grep -v ".d") BINS=$(ls ./release/u_* -1 | grep -v ".d")
echo "Stripping..." echo "Stripping..."
strip $BINS strip $BINS

@ -1,7 +1,7 @@
use std::fmt; use std::fmt;
use structopt::StructOpt; use structopt::StructOpt;
use u_lib::{ use u_lib::{
api::ClientHandler, datatypes::DataResult, messaging::AsMsg, models::JobMeta, UError, UResult, api::ClientHandler, datatypes::PanelResult, messaging::AsMsg, models::JobMeta, UError, UResult,
}; };
use uuid::Uuid; use uuid::Uuid;
@ -92,8 +92,8 @@ pub async fn process_cmd(client: ClientHandler, args: Args) -> UResult<()> {
pub fn print<Msg: AsMsg + fmt::Display>(&self, data: UResult<Msg>) { pub fn print<Msg: AsMsg + fmt::Display>(&self, data: UResult<Msg>) {
if self.json { if self.json {
let data = match data { let data = match data {
Ok(r) => DataResult::Ok(r), Ok(r) => PanelResult::Ok(r),
Err(e) => DataResult::Err(e), Err(e) => PanelResult::Err(e),
}; };
println!("{}", serde_json::to_string_pretty(&data).unwrap()); println!("{}", serde_json::to_string_pretty(&data).unwrap());
} else { } else {

@ -1,3 +1,4 @@
use crate::errors::{Error, SResult};
use diesel::{pg::PgConnection, prelude::*, result::Error as DslError}; use diesel::{pg::PgConnection, prelude::*, result::Error as DslError};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use serde::Deserialize; use serde::Deserialize;
@ -5,7 +6,6 @@ use std::sync::{Arc, Mutex, MutexGuard};
use u_lib::{ use u_lib::{
models::{schema, Agent, AgentError, AssignedJob, JobMeta, JobState}, models::{schema, Agent, AgentError, AssignedJob, JobMeta, JobState},
utils::load_env, utils::load_env,
ULocalError, ULocalResult,
}; };
use uuid::Uuid; use uuid::Uuid;
@ -39,7 +39,7 @@ impl UDB {
.unwrap() .unwrap()
} }
pub fn report_error(&self, error: &AgentError) -> ULocalResult<()> { pub fn report_error(&self, error: &AgentError) -> SResult<()> {
use schema::errors; use schema::errors;
diesel::insert_into(errors::table) diesel::insert_into(errors::table)
.values(error) .values(error)
@ -47,7 +47,7 @@ impl UDB {
Ok(()) Ok(())
} }
pub fn insert_jobs(&self, job_metas: &[JobMeta]) -> ULocalResult<()> { pub fn insert_jobs(&self, job_metas: &[JobMeta]) -> SResult<()> {
use schema::jobs; use schema::jobs;
diesel::insert_into(jobs::table) diesel::insert_into(jobs::table)
.values(job_metas) .values(job_metas)
@ -55,7 +55,7 @@ impl UDB {
Ok(()) Ok(())
} }
pub fn get_jobs(&self, uid: Option<Uuid>) -> ULocalResult<Vec<JobMeta>> { pub fn get_jobs(&self, uid: Option<Uuid>) -> SResult<Vec<JobMeta>> {
use schema::jobs; use schema::jobs;
let result = if uid.is_some() { let result = if uid.is_some() {
jobs::table jobs::table
@ -67,7 +67,7 @@ impl UDB {
Ok(result) Ok(result)
} }
pub fn find_job_by_alias(&self, alias: &str) -> ULocalResult<JobMeta> { pub fn find_job_by_alias(&self, alias: &str) -> SResult<JobMeta> {
use schema::jobs; use schema::jobs;
let result = jobs::table let result = jobs::table
.filter(jobs::alias.eq(alias)) .filter(jobs::alias.eq(alias))
@ -75,7 +75,7 @@ impl UDB {
Ok(result) Ok(result)
} }
pub fn insert_agent(&self, agent: &Agent) -> ULocalResult<()> { pub fn insert_agent(&self, agent: &Agent) -> SResult<()> {
use schema::agents; use schema::agents;
diesel::insert_into(agents::table) diesel::insert_into(agents::table)
.values(agent) .values(agent)
@ -86,7 +86,7 @@ impl UDB {
Ok(()) Ok(())
} }
pub fn get_agents(&self, uid: Option<Uuid>) -> ULocalResult<Vec<Agent>> { pub fn get_agents(&self, uid: Option<Uuid>) -> SResult<Vec<Agent>> {
use schema::agents; use schema::agents;
let result = if uid.is_some() { let result = if uid.is_some() {
agents::table agents::table
@ -98,7 +98,7 @@ impl UDB {
Ok(result) Ok(result)
} }
pub fn update_job_status(&self, uid: Uuid, status: JobState) -> ULocalResult<()> { pub fn update_job_status(&self, uid: Uuid, status: JobState) -> SResult<()> {
use schema::results; use schema::results;
diesel::update(results::table) diesel::update(results::table)
.filter(results::id.eq(uid)) .filter(results::id.eq(uid))
@ -108,11 +108,7 @@ impl UDB {
} }
//TODO: filters possibly could work in a wrong way, check //TODO: filters possibly could work in a wrong way, check
pub fn get_exact_jobs( pub fn get_exact_jobs(&self, uid: Option<Uuid>, personal: bool) -> SResult<Vec<AssignedJob>> {
&self,
uid: Option<Uuid>,
personal: bool,
) -> ULocalResult<Vec<AssignedJob>> {
use schema::results; use schema::results;
let mut q = results::table.into_boxed(); let mut q = results::table.into_boxed();
/*if uid.is_some() { /*if uid.is_some() {
@ -134,14 +130,10 @@ impl UDB {
Ok(result) Ok(result)
} }
pub fn set_jobs_for_agent( pub fn set_jobs_for_agent(&self, agent_uid: &Uuid, job_uids: &[Uuid]) -> SResult<Vec<Uuid>> {
&self,
agent_uid: &Uuid,
job_uids: &[Uuid],
) -> ULocalResult<Vec<Uuid>> {
use schema::{agents::dsl::agents, jobs::dsl::jobs, results}; use schema::{agents::dsl::agents, jobs::dsl::jobs, results};
if let Err(DslError::NotFound) = agents.find(agent_uid).first::<Agent>(&self.conn) { if let Err(DslError::NotFound) = agents.find(agent_uid).first::<Agent>(&self.conn) {
return Err(ULocalError::NotFound(agent_uid.to_string())); return Err(Error::NotFound(agent_uid.to_string()));
} }
let not_found_jobs = job_uids let not_found_jobs = job_uids
.iter() .iter()
@ -154,7 +146,7 @@ impl UDB {
}) })
.collect::<Vec<String>>(); .collect::<Vec<String>>();
if !not_found_jobs.is_empty() { if !not_found_jobs.is_empty() {
return Err(ULocalError::NotFound(not_found_jobs.join(", "))); return Err(Error::NotFound(not_found_jobs.join(", ")));
} }
let job_requests = job_uids let job_requests = job_uids
.iter() .iter()
@ -174,7 +166,7 @@ impl UDB {
Ok(assigned_uids) Ok(assigned_uids)
} }
pub fn del_jobs(&self, uids: &[Uuid]) -> ULocalResult<usize> { pub fn del_jobs(&self, uids: &[Uuid]) -> SResult<usize> {
use schema::jobs; use schema::jobs;
let mut affected = 0; let mut affected = 0;
for &uid in uids { for &uid in uids {
@ -186,7 +178,7 @@ impl UDB {
Ok(affected) Ok(affected)
} }
pub fn del_results(&self, uids: &[Uuid]) -> ULocalResult<usize> { pub fn del_results(&self, uids: &[Uuid]) -> SResult<usize> {
use schema::results; use schema::results;
let mut affected = 0; let mut affected = 0;
for &uid in uids { for &uid in uids {
@ -198,7 +190,7 @@ impl UDB {
Ok(affected) Ok(affected)
} }
pub fn del_agents(&self, uids: &[Uuid]) -> ULocalResult<usize> { pub fn del_agents(&self, uids: &[Uuid]) -> SResult<usize> {
use schema::agents; use schema::agents;
let mut affected = 0; let mut affected = 0;
for &uid in uids { for &uid in uids {

@ -0,0 +1,22 @@
use diesel::result::Error as DslError;
use thiserror::Error;
use warp::reject::Reject;
pub type SResult<T> = Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("{0} is not found")]
NotFound(String),
#[error("Error processing {0}")]
ProcessingError(String),
#[error(transparent)]
DBError(#[from] DslError),
#[error("General error: {0}")]
Other(String),
}
impl Reject for Error {}

@ -1,19 +1,17 @@
use crate::db::UDB; use crate::db::UDB;
use crate::errors::Error;
use diesel::SaveChangesDsl; use diesel::SaveChangesDsl;
use hyper::Body;
use serde::Serialize;
use u_lib::{ use u_lib::{
messaging::{AsMsg, BaseMessage, Reportable}, messaging::{AsMsg, BaseMessage, Reportable},
models::*, models::*,
utils::{OneOrVec, Stripped}, utils::{OneOrVec, Stripped},
ULocalError,
}; };
use uuid::Uuid; use uuid::Uuid;
use warp::{ use warp::{
http::{Response, StatusCode}, http::{Response, StatusCode},
Rejection, Reply, Rejection, Reply,
}; };
/*
pub fn build_response(code: StatusCode, body: impl Into<Body>) -> Response<Body> { pub fn build_response(code: StatusCode, body: impl Into<Body>) -> Response<Body> {
Response::builder().status(code).body(body.into()).unwrap() Response::builder().status(code).body(body.into()).unwrap()
} }
@ -29,116 +27,86 @@ pub fn build_err(body: impl ToString) -> Response<Body> {
pub fn build_message<M: AsMsg + Serialize>(m: M) -> Response<Body> { pub fn build_message<M: AsMsg + Serialize>(m: M) -> Response<Body> {
warp::reply::json(&m.as_message()).into_response() warp::reply::json(&m.as_message()).into_response()
} }
*/
pub struct Endpoints; pub struct Endpoints;
impl Endpoints { impl Endpoints {
pub async fn add_agent(msg: Agent) -> Result<Response<Body>, Rejection> { pub async fn add_agent(msg: Agent) -> Result<(), Rejection> {
info!("hnd: add_agent"); UDB::lock_db().insert_agent(&msg).map_err(From::from)
UDB::lock_db()
.insert_agent(&msg)
.map(|_| build_ok(""))
.or_else(|e| Ok(build_err(e)))
} }
pub async fn get_agents(uid: Option<Uuid>) -> Result<Response<Body>, Rejection> { pub async fn get_agents(uid: Option<Uuid>) -> Result<Vec<Agent>, Rejection> {
info!("hnd: get_agents"); UDB::lock_db().get_agents(uid).map_err(From::from)
UDB::lock_db()
.get_agents(uid)
.map(build_message)
.or_else(|e| Ok(build_err(e)))
} }
pub async fn get_jobs(uid: Option<Uuid>) -> Result<Response<Body>, Rejection> { pub async fn get_jobs(uid: Option<Uuid>) -> Result<Vec<JobMeta>, Rejection> {
info!("hnd: get_jobs"); UDB::lock_db().get_jobs(uid).map_err(From::from)
UDB::lock_db()
.get_jobs(uid)
.map(build_message)
.or_else(|e| Ok(build_err(e)))
} }
pub async fn get_agent_jobs(uid: Option<Uuid>) -> Result<Response<Body>, Rejection> { pub async fn get_agent_jobs(uid: Option<Uuid>) -> Result<Vec<AssignedJob>, Rejection> {
info!("hnd: get_agent_jobs");
UDB::lock_db() UDB::lock_db()
.get_exact_jobs(uid, false) .get_exact_jobs(uid, false)
.map(build_message) .map_err(From::from)
.or_else(|e| Ok(build_err(e)))
} }
pub async fn get_personal_jobs(uid: Option<Uuid>) -> Result<Response<Body>, Rejection> { pub async fn get_personal_jobs(uid: Option<Uuid>) -> Result<Vec<AssignedJob>, Rejection> {
info!("hnd: get_personal_jobs"); let agents = UDB::lock_db().get_agents(uid)?;
let agents = UDB::lock_db().get_agents(uid).unwrap();
if agents.is_empty() { if agents.is_empty() {
let db = UDB::lock_db(); let db = UDB::lock_db();
db.insert_agent(&Agent::with_id(uid.unwrap())).unwrap(); db.insert_agent(&Agent::with_id(uid.unwrap()))?;
let job = db.find_job_by_alias("agent_hello").unwrap(); let job = db.find_job_by_alias("agent_hello")?;
if let Err(e) = db.set_jobs_for_agent(&uid.unwrap(), &[job.id]) { db.set_jobs_for_agent(&uid.unwrap(), &[job.id])?;
return Ok(build_err(e));
}
} }
let result = UDB::lock_db().get_exact_jobs(uid, true); let result = UDB::lock_db().get_exact_jobs(uid, true);
match result { match result {
Ok(r) => { Ok(r) => {
let db = UDB::lock_db(); let db = UDB::lock_db();
for j in r.iter() { for j in r.iter() {
db.update_job_status(j.id, JobState::Running).unwrap(); db.update_job_status(j.id, JobState::Running)?;
} }
Ok(build_message(r)) Ok(r)
} }
Err(e) => Ok(build_err(e)), Err(e) => Err(e.into()),
} }
} }
pub async fn upload_jobs( pub async fn upload_jobs(msg: BaseMessage<'static, Vec<JobMeta>>) -> Result<(), Rejection> {
msg: BaseMessage<'static, Vec<JobMeta>>,
) -> Result<Response<Body>, Rejection> {
info!("hnd: upload_jobs");
UDB::lock_db() UDB::lock_db()
.insert_jobs(&msg.into_inner()) .insert_jobs(&msg.into_inner())
.map(|_| build_ok("")) .map_err(From::from)
.or_else(|e| Ok(build_err(e)))
} }
pub async fn del(uid: Uuid) -> Result<Response<Body>, Rejection> { pub async fn del(uid: Uuid) -> Result<usize, Rejection> {
info!("hnd: del");
let db = UDB::lock_db(); let db = UDB::lock_db();
let del_fns = &[UDB::del_agents, UDB::del_jobs, UDB::del_results]; let del_fns = &[UDB::del_agents, UDB::del_jobs, UDB::del_results];
for del_fn in del_fns { for del_fn in del_fns {
let affected = del_fn(&db, &[uid]).unwrap(); let affected = del_fn(&db, &[uid]).unwrap();
if affected > 0 { if affected > 0 {
return Ok(build_message(affected as i32)); return Ok(affected);
} }
} }
Ok(build_message(0)) Ok(0)
} }
pub async fn set_jobs( pub async fn set_jobs(
agent_uid: Uuid, agent_uid: Uuid,
msg: BaseMessage<'static, Vec<String>>, msg: BaseMessage<'static, Vec<String>>,
) -> Result<Response<Body>, Rejection> { ) -> Result<Vec<Uuid>, Rejection> {
info!("hnd: set_jobs_by_alias, agent: {}", agent_uid); msg.into_inner()
let jobs: Result<Vec<Uuid>, ULocalError> = msg
.into_inner()
.into_iter() .into_iter()
.map(|ident| { .map(|ident| {
info!("hnd: set_jobs_by_alias, job: {}", ident);
Uuid::parse_str(&ident) Uuid::parse_str(&ident)
.or_else(|_| UDB::lock_db().find_job_by_alias(&ident).map(|j| j.id)) .or_else(|_| UDB::lock_db().find_job_by_alias(&ident).map(|j| j.id))
}) })
.collect(); .collect::<Result<Vec<Uuid>, Error>>()
match jobs { .and_then(|j| UDB::lock_db().set_jobs_for_agent(&agent_uid, &j))
Ok(j) => UDB::lock_db() .map_err(From::from)
.set_jobs_for_agent(&agent_uid, &j)
.map(build_message)
.or_else(|e| Ok(build_err(e))),
Err(e) => Ok(build_err(e)),
}
} }
pub async fn report<Data: OneOrVec<Reportable> + AsMsg + 'static>( pub async fn report<Data: OneOrVec<Reportable> + AsMsg + 'static>(
msg: BaseMessage<'static, Data>, msg: BaseMessage<'static, Data>,
) -> Result<Response<Body>, Rejection> { ) -> Result<(), Rejection> {
info!("hnd: report");
let id = msg.id; let id = msg.id;
let mut failed = vec![]; let mut failed = vec![];
for entry in msg.into_inner().into_vec() { for entry in msg.into_inner().into_vec() {
@ -150,7 +118,7 @@ impl Endpoints {
let db = UDB::lock_db(); let db = UDB::lock_db();
if let Err(e) = res if let Err(e) = res
.save_changes::<AssignedJob>(&db.conn) .save_changes::<AssignedJob>(&db.conn)
.map_err(ULocalError::from) .map_err(Error::from)
{ {
failed.push(e.to_string()) failed.push(e.to_string())
} }
@ -172,9 +140,8 @@ impl Endpoints {
} }
} }
if !failed.is_empty() { if !failed.is_empty() {
let err_msg = ULocalError::ProcessingError(failed.join(", ")); return Err(Error::ProcessingError(failed.join(", ")).into());
return Ok(build_err(err_msg));
} }
Ok(build_ok("")) Ok(())
} }
} }

@ -1,5 +1,5 @@
use crate::db::UDB;
use crate::handlers::Endpoints; use crate::handlers::Endpoints;
use crate::{db::UDB, errors::SResult};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use std::path::PathBuf; use std::path::PathBuf;
use u_lib::{ use u_lib::{
@ -7,7 +7,11 @@ use u_lib::{
models::*, models::*,
}; };
use uuid::Uuid; use uuid::Uuid;
use warp::{body, Filter, Rejection, Reply}; use warp::{
body,
reply::{json, reply, Json},
Filter, Rejection, Reply,
};
fn get_content<M>() -> impl Filter<Extract = (BaseMessage<'static, M>,), Error = Rejection> + Clone fn get_content<M>() -> impl Filter<Extract = (BaseMessage<'static, M>,), Error = Rejection> + Clone
where where
@ -16,6 +20,10 @@ where
body::content_length_limit(1024 * 64).and(body::json::<BaseMessage<M>>()) body::content_length_limit(1024 * 64).and(body::json::<BaseMessage<M>>())
} }
fn into_message<M: AsMsg>(msg: M) -> Json {
json(&msg.as_message())
}
pub fn init_filters( pub fn init_filters(
auth_token: &str, auth_token: &str,
) -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone { ) -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
@ -28,12 +36,14 @@ pub fn init_filters(
.map(Some) .map(Some)
.or_else(infallible_none), .or_else(infallible_none),
) )
.and_then(Endpoints::get_agents); .and_then(Endpoints::get_agents)
.map(into_message);
let upload_jobs = warp::post() let upload_jobs = warp::post()
.and(warp::path("upload_jobs")) .and(warp::path("upload_jobs"))
.and(get_content::<Vec<JobMeta>>()) .and(get_content::<Vec<JobMeta>>())
.and_then(Endpoints::upload_jobs); .and_then(Endpoints::upload_jobs)
.map(|_| reply());
let get_jobs = warp::get() let get_jobs = warp::get()
.and(warp::path("get_jobs")) .and(warp::path("get_jobs"))
@ -42,7 +52,8 @@ pub fn init_filters(
.map(Some) .map(Some)
.or_else(infallible_none), .or_else(infallible_none),
) )
.and_then(Endpoints::get_jobs); .and_then(Endpoints::get_jobs)
.map(into_message);
let get_agent_jobs = warp::get() let get_agent_jobs = warp::get()
.and(warp::path("get_agent_jobs")) .and(warp::path("get_agent_jobs"))
@ -51,27 +62,33 @@ pub fn init_filters(
.map(Some) .map(Some)
.or_else(infallible_none), .or_else(infallible_none),
) )
.and_then(Endpoints::get_agent_jobs); .and_then(Endpoints::get_agent_jobs)
.map(into_message);
let get_personal_jobs = warp::get() let get_personal_jobs = warp::get()
.and(warp::path("get_personal_jobs")) .and(warp::path("get_personal_jobs"))
.and(warp::path::param::<Uuid>().map(Some)) .and(warp::path::param::<Uuid>().map(Some))
.and_then(Endpoints::get_personal_jobs); .and_then(Endpoints::get_personal_jobs)
.map(into_message);
let del = warp::get() let del = warp::get()
.and(warp::path("del")) .and(warp::path("del"))
.and(warp::path::param::<Uuid>()) .and(warp::path::param::<Uuid>())
.and_then(Endpoints::del); .and_then(Endpoints::del)
.map(|_| reply());
let set_jobs = warp::post() let set_jobs = warp::post()
.and(warp::path("set_jobs")) .and(warp::path("set_jobs"))
.and(warp::path::param::<Uuid>()) .and(warp::path::param::<Uuid>())
.and(get_content::<Vec<String>>()) .and(get_content::<Vec<String>>())
.and_then(Endpoints::set_jobs); .and_then(Endpoints::set_jobs)
.map(into_message);
let report = warp::post() let report = warp::post()
.and(warp::path("report")) .and(warp::path("report"))
.and(get_content::<Vec<Reportable>>().and_then(Endpoints::report)); .and(get_content::<Vec<Reportable>>())
.and_then(Endpoints::report)
.map(|_| reply());
let auth_token = format!("Bearer {auth_token}",).into_boxed_str(); let auth_token = format!("Bearer {auth_token}",).into_boxed_str();
let auth_header = warp::header::exact("authorization", Box::leak(auth_token)); let auth_header = warp::header::exact("authorization", Box::leak(auth_token));
@ -89,13 +106,13 @@ pub fn init_filters(
auth_zone.or(agent_zone) auth_zone.or(agent_zone)
} }
pub fn prefill_jobs() { pub fn prefill_jobs() -> SResult<()> {
let agent_hello = JobMeta::builder() let agent_hello = JobMeta::builder()
.with_type(misc::JobType::Manage) .with_type(misc::JobType::Manage)
.with_alias("agent_hello") .with_alias("agent_hello")
.build() .build()
.unwrap(); .unwrap();
UDB::lock_db().insert_jobs(&[agent_hello]).unwrap(); UDB::lock_db().insert_jobs(&[agent_hello])
} }
pub fn init_logger() { pub fn init_logger() {

@ -2,5 +2,5 @@ use u_server_lib::serve;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), String> { async fn main() -> Result<(), String> {
serve().await serve().await.map_err(|e| e.to_string())
} }

@ -12,9 +12,11 @@ extern crate diesel;
// in this block // in this block
mod db; mod db;
mod errors;
mod handlers; mod handlers;
mod init; mod init;
use errors::{Error, SResult};
use init::*; use init::*;
use serde::Deserialize; use serde::Deserialize;
use std::path::PathBuf; use std::path::PathBuf;
@ -27,11 +29,11 @@ struct ServEnv {
} }
//TODO: tracing-subscriber //TODO: tracing-subscriber
pub async fn serve() -> Result<(), String> { pub async fn serve() -> SResult<()> {
init_logger(); init_logger();
prefill_jobs(); prefill_jobs()?;
let env = load_env::<ServEnv>().map_err(|e| e.to_string())?; let env = load_env::<ServEnv>().map_err(|e| Error::Other(e.to_string()))?;
let routes = init_filters(&env.admin_auth_token); let routes = init_filters(&env.admin_auth_token);
let certs_dir = PathBuf::from("certs"); let certs_dir = PathBuf::from("certs");
warp::serve(routes.with(warp::log("warp"))) warp::serve(routes.with(warp::log("warp")))

@ -14,7 +14,6 @@ uuid = { version = "0.6.5", features = ["serde", "v4"] }
reqwest = { version = "0.11", features = ["json"] } reqwest = { version = "0.11", features = ["json"] }
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0.114", features = ["derive"] } serde = { version = "1.0.114", features = ["derive"] }
futures = "0.3.5"
shlex = "1.0.0" shlex = "1.0.0"
rstest = "0.12" rstest = "0.12"
once_cell = "1.10.0" once_cell = "1.10.0"

@ -6,13 +6,14 @@ networks:
services: services:
u_server: u_server:
user: "${DOCKER_UID:-1000}:${DOCKER_GID:-1000}"
image: unki/u_server image: unki/u_server
networks: networks:
- u_net - u_net
volumes: volumes:
- ../release/u_server:/unki/u_server - ../release/u_server:/unki/u_server
- ../certs:/unki/certs - ../certs:/unki/certs
- ../logs:/unki/logs - ../logs:/unki/logs:rw
working_dir: /unki working_dir: /unki
command: /unki/u_server command: /unki/u_server
depends_on: depends_on:
@ -52,6 +53,7 @@ services:
retries: 3 retries: 3
u_agent: u_agent:
user: "${DOCKER_UID:-1000}:${DOCKER_GID:-1000}"
image: unki/u_agent image: unki/u_agent
networks: networks:
- u_net - u_net
@ -67,7 +69,7 @@ services:
condition: service_healthy condition: service_healthy
tests_runner: tests_runner:
user: "${DOCKER_UID}:${DOCKER_GID}" user: "${DOCKER_UID:-1000}:${DOCKER_GID:-1000}"
image: unki/tests_runner image: unki/tests_runner
networks: networks:
- u_net - u_net

@ -1,17 +1,14 @@
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde_json::{from_slice, Value}; use serde_json::{from_slice, Value};
use shlex::split; use std::fmt::{Debug, Display};
use std::fmt::Display;
use std::process::{Command, Output}; use std::process::{Command, Output};
use u_lib::{ use u_lib::{
datatypes::DataResult, datatypes::PanelResult,
utils::{bytes_to_string, ProcOutput}, utils::{bytes_to_string, ProcOutput},
}; };
const PANEL_BINARY: &str = "/u_panel"; const PANEL_BINARY: &str = "/u_panel";
type PanelResult<T> = Result<DataResult<T>, String>;
pub struct Panel; pub struct Panel;
impl Panel { impl Panel {
@ -26,31 +23,40 @@ impl Panel {
pub fn output_argv<T: DeserializeOwned>(argv: &[&str]) -> PanelResult<T> { pub fn output_argv<T: DeserializeOwned>(argv: &[&str]) -> PanelResult<T> {
let result = Self::run(argv); let result = Self::run(argv);
let output = ProcOutput::from_output(&result).to_appropriate(); let output = ProcOutput::from_output(&result).to_appropriate();
from_slice(&output).map_err(|e| { from_slice(&output)
.map_err(|e| {
eprintln!( eprintln!(
"Failed to decode panel response: '{}'", "Failed to decode panel response: '{}'",
bytes_to_string(&output) bytes_to_string(&output)
); );
e.to_string() e.to_string()
}) })
.unwrap()
} }
pub fn output<T: DeserializeOwned>(args: impl Into<String> + Display) -> PanelResult<T> { pub fn output<T: DeserializeOwned + Debug>(
println!("Executing '{PANEL_BINARY} {}'", &args); args: impl Into<String> + Display,
let splitted = split(args.into().as_ref()).unwrap(); ) -> PanelResult<T> {
Self::output_argv( eprintln!("EXEC >>> {PANEL_BINARY} {}", &args);
let splitted = shlex::split(args.into().as_ref()).unwrap();
let result = Self::output_argv(
splitted splitted
.iter() .iter()
.map(|s| s.as_ref()) .map(|s| s.as_ref())
.collect::<Vec<&str>>() .collect::<Vec<&str>>()
.as_ref(), .as_ref(),
) );
match &result {
PanelResult::Ok(r) => eprintln!("<<<+ {r:?}"),
PanelResult::Err(e) => eprintln!("<<<! {e:?}"),
}
result
} }
fn status_is_ok<T: DeserializeOwned>(data: PanelResult<T>) -> T { fn status_is_ok<T: DeserializeOwned + Debug>(data: PanelResult<T>) -> T {
match data.unwrap() { match data {
DataResult::Ok(r) => r, PanelResult::Ok(r) => r,
DataResult::Err(e) => panic!("Panel failed: {}", e), PanelResult::Err(e) => panic!("Panel failed: {}", e),
} }
} }
@ -59,7 +65,7 @@ impl Panel {
Self::status_is_ok(result); Self::status_is_ok(result);
} }
pub fn check_output<T: DeserializeOwned>(args: impl Into<String> + Display) -> T { pub fn check_output<T: DeserializeOwned + Debug>(args: impl Into<String> + Display) -> T {
let result = Self::output(args); let result = Self::output(args);
Self::status_is_ok(result) Self::status_is_ok(result)
} }

@ -20,7 +20,9 @@ async fn test_non_auth_connection_dropped() {
.await .await
{ {
Err(e) => { Err(e) => {
assert!(e.to_string().contains("channel closed")) let err = e.to_string();
println!("{err}");
assert!(err.contains("channel closed"))
} }
_ => panic!("no error occured on foreign client connection"), _ => panic!("no error occured on foreign client connection"),
} }

@ -69,20 +69,22 @@ pub fn api_route(args: TokenStream, item: TokenStream) -> TokenStream {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(e) => Err(UError::from(e)) Err(e) => Err(UError::from(e))
}; };
let resp = response.text().await?;
let result = match is_success { let result = match is_success {
Ok(_) => response.json::<BaseMessage<#return_ty>>() Ok(_) => {
.await serde_json::from_str::<BaseMessage<#return_ty>>(&resp)
.map(|msg| msg.into_inner()) .map(|msg| msg.into_inner())
.or_else(|e| { .or_else(|e| {
match content_len { match content_len {
Some(0) => Ok(Default::default()), Some(0) => Ok(Default::default()),
_ => Err(UError::from(e)) _ => Err(UError::NetError(e.to_string(), resp.clone()))
} }
}), })
},
Err(UError::NetError(err_src, _)) => Err( Err(UError::NetError(err_src, _)) => Err(
UError::NetError( UError::NetError(
err_src, err_src,
response.text().await? resp
) )
), ),
_ => unreachable!() _ => unreachable!()

@ -24,15 +24,14 @@ once_cell = "1.7.2"
shlex = "1.0.0" shlex = "1.0.0"
u_api_proc_macro = { version = "*", path = "../u_api_proc_macro" } u_api_proc_macro = { version = "*", path = "../u_api_proc_macro" }
crossbeam = "0.8.1" crossbeam = "0.8.1"
backtrace = "0.3.61"
diesel = { version = "1.4.5", features = ["postgres", "uuid"] } diesel = { version = "1.4.5", features = ["postgres", "uuid"] }
envy = "0.4.2" envy = "0.4.2"
serde_json = "1.0.81"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
reqwest = { version = "0.11", features = ["json", "native-tls"] } reqwest = { version = "0.11", features = ["json", "native-tls"] }
tokio = { version = "1.2.0", features = ["rt-multi-thread", "sync", "macros", "process", "time"] } tokio = { version = "1.2.0", features = ["rt-multi-thread", "sync", "macros", "process", "time"] }
guess_host_triple = "0.1.2" guess_host_triple = "0.1.2"
openssl = "*"
[dev-dependencies] [dev-dependencies]
rstest = "0.12" rstest = "0.12"

@ -4,7 +4,7 @@ use crate::{
messaging::Reportable, messaging::Reportable,
models::{Agent, AssignedJob, JobMeta, JobType}, models::{Agent, AssignedJob, JobMeta, JobType},
utils::{CombinedResult, OneOrVec}, utils::{CombinedResult, OneOrVec},
UError, UErrorBt, UResult, UError, UResult,
}; };
use guess_host_triple::guess_host_triple; use guess_host_triple::guess_host_triple;
use std::collections::HashMap; use std::collections::HashMap;
@ -17,11 +17,11 @@ impl JobBuilder {
pub fn from_request(job_requests: impl OneOrVec<AssignedJob>) -> CombinedResult<Self> { pub fn from_request(job_requests: impl OneOrVec<AssignedJob>) -> CombinedResult<Self> {
let job_requests = job_requests.into_vec(); let job_requests = job_requests.into_vec();
let mut prepared: Vec<DynFut> = vec![]; let mut prepared: Vec<DynFut> = vec![];
let mut result = CombinedResult::<JobBuilder, UErrorBt>::new(); let mut result = CombinedResult::<JobBuilder, UError>::new();
for req in job_requests { for req in job_requests {
let job_meta = JobCache::get(req.job_id); let job_meta = JobCache::get(req.job_id);
if job_meta.is_none() { if job_meta.is_none() {
result.err(UError::NoJob(req.job_id).into_bt()); result.err(UError::NoJob(req.job_id));
continue; continue;
} }
let job_meta = job_meta.unwrap(); let job_meta = job_meta.unwrap();
@ -288,7 +288,7 @@ mod tests {
job = job.with_payload(p); job = job.with_payload(p);
} }
let err = job.build().unwrap_err(); let err = job.build().unwrap_err();
let err_msg = unwrap_enum!(err.err, UError::JobArgsError); let err_msg = unwrap_enum!(err, UError::JobArgsError);
assert!(err_msg.contains(err_str)); assert!(err_msg.contains(err_str));
Ok(()) Ok(())
} }

@ -1,10 +1,10 @@
use crate::UErrorBt; use crate::UError;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
#[serde(tag = "status", content = "data")] #[serde(tag = "status", content = "data")]
pub enum DataResult<M> { pub enum PanelResult<M> {
Ok(M), Ok(M),
Err(UErrorBt), Err(UError),
} }

@ -1,8 +1,8 @@
use crate::UErrorBt; use crate::UError;
use crossbeam::channel::{self, Receiver, Sender}; use crossbeam::channel::{self, Receiver, Sender};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
type ChanError = UErrorBt; type ChanError = UError;
static ERR_CHAN: OnceCell<ErrChan> = OnceCell::new(); static ERR_CHAN: OnceCell<ErrChan> = OnceCell::new();
pub struct ErrChan { pub struct ErrChan {
@ -18,8 +18,8 @@ impl ErrChan {
}) })
} }
pub fn send(msg: impl Into<UErrorBt>) { pub fn send(msg: ChanError) {
Self::get().tx.send(msg.into()).unwrap() Self::get().tx.send(msg).unwrap()
} }
pub fn recv() -> ChanError { pub fn recv() -> ChanError {

@ -1,35 +1,10 @@
use backtrace::Backtrace as CrateBacktrace;
use diesel::result::Error as DslError;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use reqwest::Error as ReqError; use reqwest::Error as ReqError;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt;
use thiserror::Error; use thiserror::Error;
use uuid::Uuid; use uuid::Uuid;
pub type UResult<T> = std::result::Result<T, UErrorBt>; pub type UResult<T> = std::result::Result<T, UError>;
pub type ULocalResult<T> = std::result::Result<T, ULocalError>;
#[derive(Error, Debug, Serialize, Deserialize, Clone)]
pub struct UErrorBt {
pub err: UError,
pub backtrace: String,
}
impl fmt::Display for UErrorBt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}\nBACKTRACE: \n{:?}", self.err, self.backtrace)
}
}
impl From<UError> for UErrorBt {
fn from(err: UError) -> UErrorBt {
UErrorBt {
err,
backtrace: format!("{:?}", CrateBacktrace::new()),
}
}
}
#[derive(Error, Debug, Serialize, Deserialize, Clone)] #[derive(Error, Debug, Serialize, Deserialize, Clone)]
pub enum UError { pub enum UError {
@ -70,34 +45,9 @@ pub enum UError {
PanelError(String), PanelError(String),
} }
impl UError {
pub fn into_bt(self) -> UErrorBt {
UErrorBt::from(self)
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<ReqError> for UErrorBt {
fn from(e: ReqError) -> Self {
UError::from(e).into_bt()
}
}
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
impl From<ReqError> for UError { impl From<ReqError> for UError {
fn from(e: ReqError) -> Self { fn from(e: ReqError) -> Self {
UError::NetError(e.to_string(), String::new()) UError::NetError(e.to_string(), String::new())
} }
} }
#[derive(Error, Debug)]
pub enum ULocalError {
#[error("{0} is not found")]
NotFound(String),
#[error("Error processing {0}")]
ProcessingError(String),
#[error(transparent)]
DBError(#[from] DslError),
}

@ -25,7 +25,7 @@ pub mod exports {
} }
pub use config::UID; pub use config::UID;
pub use errors::{UError, UErrorBt, ULocalError, ULocalResult, UResult}; pub use errors::{UError, UResult};
pub use exports::*; pub use exports::*;
pub mod schema_exports { pub mod schema_exports {

@ -8,10 +8,7 @@ use uuid::Uuid;
pub struct Moo<'cow, T: AsMsg + Clone>(pub Cow<'cow, T>); pub struct Moo<'cow, T: AsMsg + Clone>(pub Cow<'cow, T>);
pub trait AsMsg: Clone + Serialize { pub trait AsMsg: Clone + Serialize {
fn as_message<'m>(&'m self) -> BaseMessage<'m, Self> fn as_message(&self) -> BaseMessage<'_, Self> {
where
Moo<'m, Self>: From<&'m Self>,
{
BaseMessage::new(self) BaseMessage::new(self)
} }
} }

@ -84,11 +84,7 @@ impl AssignedJob {
if let Some(ref payload) = meta.payload { if let Some(ref payload) = meta.payload {
let extracted_payload = match TempFile::write_exec(payload) { let extracted_payload = match TempFile::write_exec(payload) {
Ok(p) => p, Ok(p) => p,
Err(e) => { Err(e) => return Reportable::Error(UError::Runtime(e.to_string()).to_string()),
return Reportable::Error(
UError::Runtime(e.to_string()).into_bt().to_string(),
)
}
}; };
( (
meta.argv.replace("{}", &extracted_payload.get_path()), meta.argv.replace("{}", &extracted_payload.get_path()),

@ -1,7 +1,7 @@
use crate::utils::OneOrVec; use crate::utils::OneOrVec;
use crate::UErrorBt; use crate::UError;
pub struct CombinedResult<T, E = UErrorBt> { pub struct CombinedResult<T, E = UError> {
ok: Vec<T>, ok: Vec<T>,
err: Vec<E>, err: Vec<E>,
} }

Loading…
Cancel
Save