Page MenuHomePhorge

No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/.maid/build.toml b/.maid/build.toml
index adc8969..f1f38fa 100644
--- a/.maid/build.toml
+++ b/.maid/build.toml
@@ -1,44 +1,44 @@
[env]
-VERSION='1.7.0'
+VERSION='1.6.4'
[tasks.build_all]
info = "build all"
script = [
# install packages
"apt-get update -yqq",
"apt-get install zip clang llvm -yqq",
# setup build
"mkdir build",
"export CC=\"/usr/bin/clang\"",
"export CXX=\"/usr/bin/clang++\"",
# build linux (x86_64)
"cargo zigbuild -r --color always",
"mv target/release/pmc build/pmc",
"zip build/pmc_%{env.VERSION}_linux_amd64.zip build/pmc",
"rm build/pmc",
# build macos (x86_64)
"cargo zigbuild -r --target x86_64-apple-darwin --color always",
"mv target/x86_64-apple-darwin/release/pmc build/pmc",
"zip build/pmc_%{env.VERSION}_darwin_amd64.zip build/pmc",
"rm build/pmc",
# build macos (aarch64)
"cargo zigbuild -r --target aarch64-apple-darwin --color always",
"mv target/aarch64-apple-darwin/release/pmc build/pmc",
"zip build/pmc_%{env.VERSION}_darwin_arm.zip build/pmc",
"rm build/pmc",
# post build
"ls -sh build",
]
[tasks.build_all.remote]
silent = false
exclusive = true
shell = "/bin/bash"
image = "themackabu/rust:zigbuild-1.75.0"
push = ["src", "lib", "Cargo.toml", "Cargo.lock", "build.rs"]
pull = "build"
diff --git a/Cargo.toml b/Cargo.toml
index 96aa675..4cbd930 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,50 +1,50 @@
[package]
name = "pmc"
-version = "1.7.0"
+version = "1.6.4"
edition = "2021"
license = "MIT"
repository = "https://lab.themackabu.dev/self/pmc"
description = "PMC is a simple and easy to use PM2 alternative"
[dependencies]
log = "0.4.20"
toml = "0.8.8"
home = "0.5.9"
warp = "0.3.6"
ryu = "1.0.16"
clap = "4.4.12"
cxx = "1.0.112"
bytes = "1.5.0"
regex = "1.10.2"
libc = "0.2.151"
anyhow = "1.0.78"
colored = "2.1.0"
macros-rs = "0.5.0"
termcolor = "1.4.0"
rmp-serde = "1.1.2"
once_cell = "1.19.0"
static_dir = "0.2.0"
env_logger = "0.10.1"
merkle_hash = "3.5.0"
lazy_static = "1.4.0"
prometheus = "0.13.3"
serde_json = "1.0.109"
simple-logging = "2.0.2"
utoipa-rapidoc = "2.0.0"
pretty_env_logger = "0.5.0"
utoipa-swagger-ui = "5.0.0"
clap-verbosity-flag = "2.1.1"
global_placeholders = "0.1.0"
tokio = { version = "1.35.1", features = ["full"] }
psutil = { version = "3.2.2", features = ["serde"] }
tabled = { version = "0.15.0", features = ["ansi"] }
chrono = { version = "0.4.31", features = ["serde"] }
serde = { version = "1.0.193", features = ["derive"] }
utoipa = { version = "4.1.0", features = ["serde_yaml"] }
[build-dependencies]
tar = "0.4.40"
chrono = "0.4.31"
flate2 = "1.0.28"
cxx-build = "1.0.112"
reqwest = { version = "0.11.23", features = ["blocking"] }
diff --git a/Maidfile.toml b/Maidfile.toml
index 83ca431..240a302 100644
--- a/Maidfile.toml
+++ b/Maidfile.toml
@@ -1,29 +1,29 @@
import = [".maid/build.toml", ".maid/server.toml"]
[project]
name = "pmc"
-version = "1.7.0"
+version = "1.6.4"
[tasks]
clean = { script = ["rm -rf bin", "mkdir bin"] }
api = { script = ["maid install -q", "pmc daemon start --api"] }
webui = { script = ["maid install -q", "pmc daemon start --webui"] }
[tasks.build]
depends = ["clean"]
script = [
"cargo zigbuild --release",
"cp target/release/pmc bin/pmc"
]
[tasks.build.cache]
path = "src"
target = ["bin/pmc"]
[tasks.install]
script = [
"killall pmc",
"maid build -q",
"sudo cp bin/pmc /usr/local/bin",
"echo Copied binary!"
]
\ No newline at end of file
diff --git a/src/daemon/api/mod.rs b/src/daemon/api/mod.rs
index bed7f1a..245b64e 100644
--- a/src/daemon/api/mod.rs
+++ b/src/daemon/api/mod.rs
@@ -1,182 +1,182 @@
mod routes;
use bytes::Bytes;
use lazy_static::lazy_static;
use macros_rs::fmtstr;
use pmc::{config, process};
use prometheus::{opts, register_counter, register_gauge, register_histogram, register_histogram_vec};
use prometheus::{Counter, Gauge, Histogram, HistogramVec};
use routes::{action_handler, env_handler, info_handler, list_handler, log_handler, log_handler_raw, metrics_handler, prometheus_handler, rename_handler};
use serde::Serialize;
use serde_json::json;
use static_dir::static_dir;
use std::{convert::Infallible, str::FromStr};
use utoipa::{OpenApi, ToSchema};
use utoipa_rapidoc::RapiDoc;
use warp::{
body, filters, get, header,
http::{StatusCode, Uri},
path, post, redirect, reject,
reply::{self, html, json},
serve, Filter, Rejection, Reply,
};
#[derive(Serialize, ToSchema)]
struct ErrorMessage {
#[schema(example = 404)]
code: u16,
#[schema(example = "NOT_FOUND")]
message: String,
}
#[inline]
async fn convert_to_string(bytes: Bytes) -> Result<String, Rejection> { String::from_utf8(bytes.to_vec()).map_err(|_| reject()) }
#[inline]
fn string_filter(limit: u64) -> impl Filter<Extract = (String,), Error = Rejection> + Clone { body::content_length_limit(limit).and(body::bytes()).and_then(convert_to_string) }
lazy_static! {
pub static ref HTTP_COUNTER: Counter = register_counter!(opts!("http_requests_total", "Number of HTTP requests made.")).unwrap();
pub static ref DAEMON_START_TIME: Gauge = register_gauge!(opts!("process_start_time_seconds", "The uptime of the daemon.")).unwrap();
pub static ref DAEMON_MEM_USAGE: Histogram = register_histogram!("daemon_memory_usage", "The memory usage graph of the daemon.").unwrap();
pub static ref DAEMON_CPU_PERCENTAGE: Histogram = register_histogram!("daemon_cpu_percentage", "The cpu usage graph of the daemon.").unwrap();
pub static ref HTTP_REQ_HISTOGRAM: HistogramVec = register_histogram_vec!("http_request_duration_seconds", "The HTTP request latencies in seconds.", &["route"]).unwrap();
}
pub async fn start(webui: bool) {
const DOCS: &str = include_str!("docs/index.html");
let config = config::read().daemon.web;
- let s_path = config::read().get_path().trim_end_matches('/').to_string();
+ let s_path = config::read().get_path();
- let docs_path = fmtstr!("{}/docs.json", s_path);
+ let docs_path = fmtstr!("{}/docs.json", s_path.trim_end_matches('/').to_string());
let auth = header::exact("authorization", fmtstr!("token {}", config.secure.token));
#[derive(OpenApi)]
#[openapi(
paths(
routes::action_handler,
routes::env_handler,
routes::info_handler,
routes::list_handler,
routes::log_handler,
routes::log_handler_raw,
routes::metrics_handler,
routes::prometheus_handler,
routes::rename_handler
),
components(schemas(
ErrorMessage,
process::Log,
process::Raw,
process::Info,
process::Stats,
process::Watch,
process::ItemSingle,
process::ProcessItem,
routes::Stats,
routes::Daemon,
routes::Version,
routes::ActionBody,
routes::MetricsRoot,
routes::LogResponse,
routes::DocMemoryInfo,
routes::ActionResponse,
))
)]
struct ApiDoc;
let app_metrics = path!("metrics").and(get()).and_then(metrics_handler);
let app_prometheus = path!("prometheus").and(get()).and_then(prometheus_handler);
let app_docs_json = path!("docs.json").and(get()).map(|| json(&ApiDoc::openapi()));
let app_docs = path!("docs").and(get()).map(|| html(RapiDoc::new(docs_path).custom_html(DOCS).to_html()));
let process_list = path!("list").and(get()).and_then(list_handler);
let process_env = path!("process" / usize / "env").and(get()).and_then(env_handler);
let process_info = path!("process" / usize / "info").and(get()).and_then(info_handler);
let process_logs = path!("process" / usize / "logs" / String).and(get()).and_then(log_handler);
let process_raw_logs = path!("process" / usize / "logs" / String / "raw").and(get()).and_then(log_handler_raw);
let process_action = path!("process" / usize / "action").and(post()).and(body::json()).and_then(action_handler);
let process_rename = path!("process" / usize / "rename").and(post()).and(string_filter(1024 * 16)).and_then(rename_handler);
let log = warp::log::custom(|info| {
log!(
"[api] {} (method={}, status={}, ms={:?}, ver={:?})",
info.path(),
info.method(),
info.status().as_u16(),
info.elapsed(),
info.version()
)
});
let base = s_path
.split('/')
.enumerate()
.filter(|(_, p)| !p.is_empty() || *p == s_path)
.fold(warp::any().boxed(), |f, (_, path)| f.and(warp::path(path.to_owned())).boxed());
let index = match webui {
true => static_dir!("src/webui/dist/").boxed(),
false => path::end().map(|| json(&json!({"healthy": true})).into_response()).boxed(),
};
let routes = process_list
.or(process_env)
.or(process_info)
.or(process_logs)
.or(process_raw_logs)
.or(process_action)
.or(process_rename)
.or(app_metrics)
.or(app_prometheus);
let routes = match config.secure.enabled {
true => routes.and(auth).or(root_redirect()).or(index).or(app_docs_json).or(app_docs).boxed(),
false => routes.or(root_redirect()).or(index).or(app_docs_json).or(app_docs).boxed(),
};
serve(base.and(routes).recover(handle_rejection).with(log)).run(config::read().get_address()).await
}
async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
let code;
let message;
HTTP_COUNTER.inc();
if err.is_not_found() {
code = StatusCode::NOT_FOUND;
message = "NOT_FOUND";
} else if let Some(_) = err.find::<reject::MissingHeader>() {
code = StatusCode::UNAUTHORIZED;
message = "UNAUTHORIZED";
} else if let Some(_) = err.find::<reject::MethodNotAllowed>() {
code = StatusCode::METHOD_NOT_ALLOWED;
message = "METHOD_NOT_ALLOWED";
} else {
log!("[api] unhandled rejection (err={:?})", err);
code = StatusCode::INTERNAL_SERVER_ERROR;
message = "INTERNAL_SERVER_ERROR";
}
let json = json(&ErrorMessage {
code: code.as_u16(),
message: message.into(),
});
Ok(reply::with_status(json, code))
}
fn root_redirect() -> filters::BoxedFilter<(impl Reply,)> {
warp::path::full()
.and_then(move |path: path::FullPath| async move {
let path = path.as_str();
if path.ends_with("/") || path.contains(".") {
return Err(warp::reject());
}
Ok(redirect::redirect(Uri::from_str(&[path, "/"].concat()).unwrap()))
})
.boxed()
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Feb 1, 10:04 PM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
494942
Default Alt Text
(10 KB)

Event Timeline