> {
- self.component_conf.get_component_args()
- }
-
- pub fn daemon(&self) -> &DaemonConfig {
- &self.daemon
- }
-
- #[allow(dead_code)]
- pub fn rpc(&mut self) -> RpcConfig {
- mem::take(&mut self.remote.rpc)
- }
-
- pub fn take_token(&mut self) -> String {
- mem::take(&mut self.auth.token)
- }
+#[derive(Deserialize)]
+pub struct OtlpConfig {
+ pub enable: bool,
+ pub addr: String,
}
-#[cfg(test)]
-mod tests {
- use crate::config::{AuthConfig, ComponentConfig, PshConfig};
- use crate::daemon::DaemonConfig;
- use crate::otlp::config::OtlpConfig;
- use crate::services::config::RpcConfig;
-
- const CONFIG_STR: &str = r#"[auth]
-token = ""
-
-[component]
-path = "cpu.wasm"
-args = ["1", "2", "3"]
-
-[daemon]
-pid_file = "/tmp/psh.pid"
-stdout_file = "/tmp/psh.stdout"
-stderr_file = "/tmp/psh.stderr"
-working_directory = "/"
-
-[remote]
-enable = true
-
-[remote.rpc]
-addr = "https://rpc.optimatist.com"
-duration = 1
-instance_id_file = "/etc/psh/instance.id"
-
-[remote.otlp]
-endpoint = "https://otel-col.optimatist.com"
-protocol = "Grpc"
-
-[remote.otlp.timeout]
-secs = 3
-nanos = 0
-"#;
-
- const TEST_CONF_PATH: &str = "./target/config.toml";
-
- #[test]
- fn conf_str_convert_work() {
- let cf = PshConfig::new(
- ComponentConfig::new(
- "cpu.wasm".to_owned(),
- vec!["1".to_owned(), "2".to_owned(), "3".to_owned()],
- ),
- OtlpConfig::default(),
- DaemonConfig::default(),
- RpcConfig::default(),
- AuthConfig::default(),
- true,
- );
- let s = toml::to_string(&cf).unwrap();
- assert_eq!(s, CONFIG_STR);
-
- let str_to_cf: PshConfig = toml::from_str(CONFIG_STR).unwrap();
- assert_eq!(cf, str_to_cf);
+pub fn read_or_gen(path: P) -> Result
+where
+ P: AsRef,
+{
+ let path = path.as_ref();
+ if !path.exists() {
+ fs::write(path, TEMPLATE)?;
}
+ let cfg = fs::read_to_string(path)?;
+ let cfg: Config = toml::from_str(&cfg)?;
+ Ok(cfg)
+}
- #[test]
- fn generate_config_work() {
- let cf = PshConfig::new(
- ComponentConfig::new(
- "cpu.wasm".to_owned(),
- vec!["1".to_owned(), "2".to_owned(), "3".to_owned()],
- ),
- OtlpConfig::default(),
- DaemonConfig::default(),
- RpcConfig::default(),
- AuthConfig::default(),
- false,
- );
- cf.generate_config(TEST_CONF_PATH, true).unwrap();
- let conf = PshConfig::read_config(TEST_CONF_PATH).unwrap();
- assert_eq!(conf, cf);
- }
+#[test]
+fn parse_config_template() {
+ toml::from_str::(TEMPLATE).unwrap();
}
diff --git a/src/daemon.rs b/src/daemon.rs
index eae3499..1c493ad 100644
--- a/src/daemon.rs
+++ b/src/daemon.rs
@@ -14,74 +14,37 @@
use std::fs::File;
+use anyhow::Result;
use daemonize::Daemonize;
-use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Daemon {
- pid_file: String,
- stdout_file: String,
- stderr_file: String,
- working_directory: String,
-}
+use crate::config::{DaemonConfig, DaemonWasmConfig};
-impl Default for Daemon {
- fn default() -> Self {
- Self {
- pid_file: "/tmp/psh.pid".to_owned(),
- stdout_file: "/tmp/psh.stdout".to_owned(),
- stderr_file: "/tmp/psh.stderr".to_owned(),
- working_directory: "/".to_owned(),
- }
- }
-}
+/// run the process as daemon
+pub fn spawn_daemon(cfg: DaemonConfig) -> Result<()> {
+ let stdout = File::create(cfg.stdout)?;
+ let stderr = File::create(cfg.stderr)?;
-#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct DaemonConfig {
- pid_file: String,
- stdout_file: String,
- stderr_file: String,
- working_directory: String,
-}
+ let daemonize = Daemonize::new()
+ .pid_file(cfg.pid_file)
+ .chown_pid_file(true) // is optional, see `Daemonize` documentation
+ .working_directory(cfg.workdir)
+ .user("root")
+ .group("root")
+ .umask(0o027) // Set umask, `0o027` by default.
+ .stdout(stdout) // by default, stdout is redirect to `/tmp/psh.stdout`.
+ .stderr(stderr); // by default, stderr is redirect to `/tmp/psh.stderr`.
-impl Default for DaemonConfig {
- fn default() -> Self {
- Self {
- pid_file: "/tmp/psh.pid".to_owned(),
- stdout_file: "/tmp/psh.stdout".to_owned(),
- stderr_file: "/tmp/psh.stderr".to_owned(),
- working_directory: "/".to_owned(),
- }
- }
-}
+ daemonize.start()?;
-impl Daemon {
- pub fn new(config: DaemonConfig) -> Self {
- Self {
- pid_file: config.pid_file,
- stdout_file: config.stdout_file,
- stderr_file: config.stderr_file,
- working_directory: config.working_directory,
- }
- }
-
- /// run the process as daemon
- pub fn daemon(self) -> anyhow::Result<()> {
- let stdout = File::create(self.stdout_file)?;
- let stderr = File::create(self.stderr_file)?;
-
- let daemonize = Daemonize::new()
- .pid_file(self.pid_file)
- .chown_pid_file(true) // is optional, see `Daemonize` documentation
- .working_directory(self.working_directory)
- .user("root")
- .group("root")
- .umask(0o027) // Set umask, `0o027` by default.
- .stdout(stdout) // by default, stdout is redirect to `/tmp/psh.stdout`.
- .stderr(stderr); // by default, stderr is redirect to `/tmp/psh.stderr`.
-
- daemonize.start()?;
+ Ok(())
+}
- Ok(())
+pub fn get_daemon_wasm_args(cfg: DaemonWasmConfig) -> Option> {
+ if !cfg.enable {
+ return None;
}
+ let mut vec = Vec::with_capacity(cfg.args.len() + 1);
+ vec.push(cfg.path);
+ vec.extend(cfg.args);
+ Some(vec)
}
diff --git a/src/main.rs b/src/main.rs
index 4452579..0abd60b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -31,7 +31,8 @@ use args::Args;
use chrono::offset::LocalResult;
use chrono::{TimeZone, Utc};
use clap::Parser;
-use config::{PshConfig, RemoteConfig};
+use config::RemoteConfig;
+use daemon::{get_daemon_wasm_args, spawn_daemon};
use log::log_init;
use opentelemetry_otlp::ExportConfig;
use runtime::{Task, TaskRuntime};
@@ -48,20 +49,17 @@ fn main() -> Result<()> {
}
let mut args = Args::parse();
- let mut psh_config = PshConfig::read_config(&args.config).unwrap_or_else(|e| {
- tracing::warn!("{e}, use default Psh config.");
- PshConfig::default()
- });
+ let cfg = config::read_or_gen(args.config.clone())?;
// When running as a daemon, it ignores all other cli arguments
let component_args = if args.systemd() || args.daemon() {
- psh_config.get_component_args()
+ get_daemon_wasm_args(cfg.daemon.wasm.clone())
} else {
args.get_component_args()
};
if args.daemon() {
- daemon::Daemon::new(psh_config.daemon().clone()).daemon()?;
+ spawn_daemon(cfg.daemon)?;
}
let mut task_rt = TaskRuntime::new()?;
@@ -78,7 +76,7 @@ fn main() -> Result<()> {
thread::spawn(move || -> Result<()> {
let rt = tokio::runtime::Runtime::new()?;
- let tasks = async_tasks(psh_config.remote.clone(), psh_config.take_token(), task_rt);
+ let tasks = async_tasks(cfg.remote, task_rt);
rt.block_on(tasks)?;
Ok(())
})
@@ -88,22 +86,17 @@ fn main() -> Result<()> {
Ok(())
}
-async fn async_tasks(
- remote_cfg: RemoteConfig,
- token: String,
- mut task_rt: TaskRuntime,
-) -> Result<()> {
- let token_ = token.clone();
-
+async fn async_tasks(remote_cfg: RemoteConfig, mut task_rt: TaskRuntime) -> Result<()> {
+ let token_cloned = remote_cfg.token.clone();
let rpc_task = async move {
- if !remote_cfg.enable {
+ if !remote_cfg.rpc.enable {
let handle = task_rt.spawn(None)?;
handle.join().expect("TaskRuntime has panicked");
return Ok(());
}
- let duration = Duration::from_secs(remote_cfg.rpc.duration);
- let mut client = RpcClient::new(remote_cfg.rpc, token_).await?;
+ let duration = Duration::from_secs(remote_cfg.rpc.heartbeat_interval);
+ let mut client = RpcClient::new(remote_cfg.rpc, token_cloned).await?;
task_rt.spawn(Some(client.clone()))?;
client.send_info().await?;
loop {
@@ -131,12 +124,15 @@ async fn async_tasks(
};
let otlp_task = async {
- if !remote_cfg.enable {
+ if !remote_cfg.otlp.enable {
return Ok(());
}
- let export_conf: ExportConfig = remote_cfg.otlp_conf.into();
- otlp::otlp_tasks(export_conf, token).await?;
+ let export_conf = ExportConfig {
+ endpoint: Some(remote_cfg.otlp.addr),
+ ..Default::default()
+ };
+ otlp::otlp_tasks(export_conf, remote_cfg.token).await?;
Ok::<(), Error>(())
};
diff --git a/src/services/config.rs b/src/services/config.rs
deleted file mode 100644
index 889b16a..0000000
--- a/src/services/config.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2023-2024 Optimatist Technology Co., Ltd. All rights reserved.
-// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-//
-// This file is part of PSH.
-//
-// PSH is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
-// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-//
-// PSH is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
-// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Performance Savior Home (PSH). If not,
-// see .
-
-use serde::{Deserialize, Serialize};
-
-#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct RpcConfig {
- pub addr: String,
- pub duration: u64,
- pub instance_id_file: String,
-}
-
-impl Default for RpcConfig {
- fn default() -> Self {
- Self {
- addr: "https://rpc.optimatist.com".to_owned(),
- duration: 1,
- instance_id_file: "/etc/psh/instance.id".to_string(),
- }
- }
-}
diff --git a/src/services/mod.rs b/src/services/mod.rs
index a79ab36..1985e45 100644
--- a/src/services/mod.rs
+++ b/src/services/mod.rs
@@ -15,6 +15,5 @@
pub mod pb {
tonic::include_proto!("psh");
}
-pub mod config;
pub mod host_info;
pub mod rpc;
diff --git a/src/services/rpc.rs b/src/services/rpc.rs
index 596d80b..380477f 100644
--- a/src/services/rpc.rs
+++ b/src/services/rpc.rs
@@ -16,8 +16,8 @@ use anyhow::Result;
use tonic::transport::{Channel, ClientTlsConfig, Endpoint};
use tonic::Request;
-use super::config::RpcConfig;
use super::pb::{self, DataRequest};
+use crate::config::RpcConfig;
use crate::services::host_info::RawInfo;
use crate::services::pb::psh_service_client::PshServiceClient;
use crate::services::pb::HostInfoRequest;