Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2708376
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Feb 1, 10:04 PM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
494942
Default Alt Text
(10 KB)
Attached To
Mode
rPMC Process Management Controller
Attached
Detach File
Event Timeline
Log In to Comment