From 2559570702c5e162db22787eb58d551017fc75b7 Mon Sep 17 00:00:00 2001 From: prplV Date: Mon, 12 May 2025 18:04:17 +0300 Subject: [PATCH] preboot as env vars + doc - tests (temp) fixed #4 --- noxis-rs/src/options/preboot.rs | 513 +++++++++++++++----------------- 1 file changed, 232 insertions(+), 281 deletions(-) diff --git a/noxis-rs/src/options/preboot.rs b/noxis-rs/src/options/preboot.rs index d21cd57..245db0c 100644 --- a/noxis-rs/src/options/preboot.rs +++ b/noxis-rs/src/options/preboot.rs @@ -1,93 +1,12 @@ -// module to handle pre-boot params of the monitor +//! +//! Module to handle `pre-boot params` of the monitor (calling also as `settings`) +//! #[allow(unused_imports)] -use anyhow::{Result, Ok, Error}; -use clap::Parser; +use anyhow::{Result, Error}; use std::path::PathBuf; use std::env::var; use dotenv::dotenv; -const SOCKET_PATH: &str = "/var/run/enode/hostagent.sock"; - -/// -enum EnvVars { - NoxisNoHagent, - NoxisNoLogs, - NoxisRefreshLogs, - // NoxisNoRemoteConfig, - NoxisNoConfigSub, - NoxisSocketPath, - NoxisLogTo, - NoxisRemoteServerUrl, - NoxisConfig, - NoxisMetrics, -} - -/// -impl std::fmt::Display for EnvVars { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - EnvVars::NoxisNoHagent => write!(f, "NOXIS_NO_HAGENT"), - EnvVars::NoxisNoLogs => write!(f, "NOXIS_NO_LOGS"), - EnvVars::NoxisRefreshLogs => write!(f, "NOXIS_REFRESH_LOGS"), - // EnvVars::NoxisNoRemoteConfig => write!(f, "NOXIS_NO_REMOTE_CONFIG"), - EnvVars::NoxisNoConfigSub => write!(f, "NOXIS_NO_CONFIG_SUB"), - EnvVars::NoxisSocketPath => write!(f, "NOXIS_SOCKET_PATH"), - EnvVars::NoxisLogTo => write!(f, "NOXIS_LOG_TO"), - EnvVars::NoxisRemoteServerUrl => write!(f, "NOXIS_REMOTE_SERVER_URL"), - EnvVars::NoxisConfig => write!(f, "NOXIS_CONFIG"), - EnvVars::NoxisMetrics => write!(f, "NOXIS_METRICS"), - } - } -} - -/// -impl<'a> EnvVars { - // Default trait func is not satisfying this issue - fn default(self) -> &'a str { - match self { - EnvVars::NoxisNoHagent => "false", - EnvVars::NoxisNoLogs => "false", - EnvVars::NoxisRefreshLogs => "false", - // EnvVars::NoxisNoRemoteConfig => "false", - EnvVars::NoxisNoConfigSub => "false", - EnvVars::NoxisSocketPath => "/var/run/enode/hostagent.sock", - EnvVars::NoxisLogTo => "./", - EnvVars::NoxisRemoteServerUrl => "localhost", - EnvVars::NoxisConfig => "./settings.json", - EnvVars::NoxisMetrics => "full", - } - } - fn process_env_var(self, preboot_value: &str) { - // let default = self.default(); - match var(self.to_string()) { - std::result::Result::Ok(val) => { - if val != preboot_value { - std::env::set_var(self.to_string(), self.default()); - } - }, - Err(_) => { - std::env::set_var(self.to_string(), preboot_value); - }, - } - } - pub fn setup(preboot: &PrebootParams) { - // setup default if not exists - // check values and save preboot states in env vars if not equal - - Self::NoxisNoHagent.process_env_var(&preboot.no_hostagent.to_string()); - Self::NoxisNoLogs.process_env_var(&preboot.no_logs.to_string()); - Self::NoxisRefreshLogs.process_env_var(&preboot.refresh_logs.to_string()); - // Self::NoxisNoRemoteConfig.process_env_var(&preboot.no_remote_config.to_string()); - Self::NoxisNoConfigSub.process_env_var(&preboot.no_sub.to_string()); - Self::NoxisSocketPath.process_env_var(preboot.socket_path.to_str().unwrap()); - Self::NoxisLogTo.process_env_var(preboot.log_to.to_str().unwrap()); - Self::NoxisRemoteServerUrl.process_env_var(&preboot.remote_server_url); - Self::NoxisConfig.process_env_var(preboot.config.to_str().unwrap()); - Self::NoxisMetrics.process_env_var(&preboot.metrics.to_string()); - - } -} - /// # Enum `MetricsPrebootParams` /// ## for setting up metrics mode as preboot param from command prompt /// @@ -109,6 +28,19 @@ pub enum MetricsPrebootParams { None, } +impl MetricsPrebootParams { + fn from_env(var: &str) -> Self { + match var.trim().to_lowercase().as_str() { + "full" => Self::Full, + "system" => Self::System, + "processes" => Self::Processes, + "net" => Self::Net, + "none" => Self::None, + _ => Self::Full, + } + } +} + /// # `std::fmt::Display` implementation for `MetricsPrebootParams` /// ## to enable parsing object to String impl std::fmt::Display for MetricsPrebootParams { @@ -123,257 +55,276 @@ impl std::fmt::Display for MetricsPrebootParams { } } -/// # struct `PrebootParams` -/// ## to parse and set up all modes as preboot params from command prompt +/// struct to handle Noxis settings (that were set as `.env` or global env vars) /// -/// ### args : +/// to parse and set up all modes as preboot params from `.env` or using `export $VAR $VAL` command /// -/// `--no-hagent` - to disable hagent work module and set up work mode as autonomous -/// ### usage : +/// # Settings : +/// +/// All settings are divided by `actions` and `values`. +/// 1. `Actions` - true or false on var exist check +/// > `Actions` is not about values, it can handle any data +/// +/// 2. `Values` - classic string-driven environment variables +/// +/// # `Actions` vars +/// +/// 1. `NOXIS_NO_HAGENT` - to disable hagent work module and set up work mode as autonomous +/// +/// **usage** : +/// ``` toml +/// ... +/// NOXIS_NO_HAGENT = "random-text" +/// ... +/// ``` +/// or /// ``` bash -/// noxis-rs ... --no-hagent ... +/// export NOXIS_NO_HAGENT "random-text" /// ``` /// /// -/// `--no-logs` - to disable logging at all -/// ### usage : +/// 2. `NOXIS_NO_LOGS` - to disable logging at all +/// **usage** : +/// ``` toml +/// ... +/// NOXIS_NO_LOGS = "random-text" +/// ... +/// ``` +/// or /// ``` bash -/// noxis-rs ... --no-logs ... +/// export NOXIS_NO_LOGS "random-text" /// ``` /// -/// `--refresh-logs` - to truncate logs directory +/// 3. `NOXIS_REFRESH_LOGS` - to truncate logs directory +/// /// ### usage : +/// ``` toml +/// ... +/// NOXIS_REFRESH_LOGS = "random-text" +/// ... +/// ``` +/// or /// ``` bash -/// noxis-rs ... --refresh-logs ... +/// export NOXIS_REFRESH_LOGS "random-text" /// ``` /// -/// `--no-sub` - to disable Redis subscribtion mechanism +/// 4. `NOXIS_NO_SUB` - to disable Redis subscribtion mechanism +/// /// ### usage : +/// ``` toml +/// NOXIS_NO_SUB = "random-text" +/// ``` +/// or /// ``` bash -/// noxis-rs ... --no-sub ... +/// export NOXIS_NO_SUB "random-text" /// ``` /// -/// `--socket-path` - to set Unix Domain Socket file's directory +/// # `Values` vars +/// +/// 1. `NOXIS_HAGENT_SOCKET_PATH` - to set Unix Domain Socket file's directory +/// /// ### usage : +/// ``` toml +/// NOXIS_HAGENT_SOCKET_PATH = "/var/run/example/hostagent.sock" +/// ``` +/// or /// ``` bash -/// noxis-rs ... --socket-path /var/run/enode/hostagent.sock ... +/// export NOXIS_HAGENT_SOCKET_PATH "/var/run/example/hostagent.sock" /// ``` /// -/// `--log-to` - to set directory for logs +/// 2 `NOXIS_LOG_TO` - to set directory for logs +/// /// ### usage : +/// ``` toml +/// NOXIS_LOG_TO = "/var/log/noxis/noxis.log" +/// ``` +/// or /// ``` bash -/// noxis-rs ... --log-to /dir/to/logs/ ... +/// export NOXIS_LOG_TO "/var/log/noxis/noxis.log" /// ``` /// -/// `--remote-server-url` - to set Redis Server +/// 3. `NOXIS_REMOTE_SERVER_URL` - to set Redis Server +/// /// ### usage : +/// ``` toml +/// NOXIS_REMOTE_SERVER_URL = "ip.ip.ip.ip:port" +/// ``` +/// or /// ``` bash -/// noxis-rs ... --remote-server-url 192.168.28.12 ... +/// export NOXIS_REMOTE_SERVER_URL "ip.ip.ip.ip:port" /// ``` /// -/// `--config` - to set Noxis' config full path -/// ### usage : +/// 4. `NOXIS_CONFIG_PATH` - to set Noxis' config full path +/// +/// ### usage : +/// ``` toml +/// NOXIS_CONFIG_PATH = "./settings.json" +/// ``` +/// or /// ``` bash -/// noxis-rs ... --config /etc/enode/settings.json ... +/// export NOXIS_CONFIG_PATH "./settings.json" /// ``` /// -/// `--metrics` - to set metrics mode +/// 5. `NOXIS_METRICS_MODE` - to set metrics mode +/// /// ### usage : -/// ``` bash -/// noxis-rs ... --metrics full ... +/// ``` toml +/// NOXIS_METRICS_MODE = "full" /// ``` -#[derive(Debug, Parser)] +/// or +/// ``` bash +/// export NOXIS_METRICS_MODE "full" +/// ``` +/// +#[derive(Debug)] pub struct PrebootParams { - // actions - #[arg( - long = "no-hagent", - action, - conflicts_with="socket_path", - help="To disable work with host-agent" - )] pub no_hostagent : bool, - #[arg( - long = "no-logs", - action, - conflicts_with="log_to", - help="To disable logs" - )] pub no_logs: bool, - #[arg( - long = "refresh-logs", - action, - conflicts_with="no_logs", - help="To clear logs directory" - )] pub refresh_logs : bool, - // #[arg( - // long = "no-remote-config", - // action, - // help="To disable work with remote config server", - // conflicts_with="no_sub")] - // pub no_remote_config : bool, - #[arg( - long = "no-sub", - action, - help="To disable Redis subscription mechanism", - )] - // conflicts_with="no_remote_config" pub no_sub : bool, - - // params (socket_path, log_to, remote_server_url, config) - #[arg( - long = "socket-path", - default_value="/var/run/enode/hostagent.sock", - conflicts_with="no_hostagent", - help="To set .sock file's path used in communication with host-agent" - )] pub socket_path : PathBuf, - #[arg( - long = "log-to", - default_value="./", - conflicts_with="no_logs", - help="To set a path to logs directory" - )] pub log_to : PathBuf, - #[arg( - long = "remote-server-url", - default_value="localhost", - conflicts_with="no_sub", - help = "To set url of remote config server using in remote config pulling mechanism" - )] pub remote_server_url : String, - #[arg( - long = "config", - short, - default_value="settings.json", - help="To set local config file path" - )] pub config : PathBuf, - - // value enum params (metrics) - #[arg( - long = "metrics", - short, - default_value_t=MetricsPrebootParams::Full, - help="To set metrics grubbing mode" - )] pub metrics: MetricsPrebootParams, } /// # implementation for `MetricsPrebootParams` /// ## to enable validation mechanism impl PrebootParams { - pub fn validate(mut self) -> Result { + pub fn validate() -> Self { dotenv().ok(); - if !self.socket_path.exists() && !self.no_hostagent { - if self.socket_path.to_string_lossy() == SOCKET_PATH { - self.no_hostagent = true; - eprintln!("Warning: Socket-file wasn't found. Working without hostagent module..."); - } else { - eprintln!("Warning: Socket-file wasn't found or Noxis can't read it. Socket-file was set to default"); - if !PathBuf::from(SOCKET_PATH).exists() { - self.no_hostagent = true; - eprintln!("Warning: Socket-file wasn't found. Working without hostagent module..."); - } else { - self.socket_path = PathBuf::from(SOCKET_PATH); + Self { + // bool + no_hostagent : { + match var("NOXIS_NO_HAGENT") { + Ok(_) => true, + Err(_) => false, } - } - // return Err(Error::msg("Socket-file not found or Noxis can't read it. Cannot start")); + }, + no_logs : { + match var("NOXIS_NO_LOGS") { + Ok(_) => true, + Err(_) => false, + } + }, + refresh_logs : { + match var("NOXIS_REFRESH_LOGS") { + Ok(_) => true, + Err(_) => false, + } + }, + no_sub : { + match var("NOXIS_NO_SUB") { + Ok(_) => true, + Err(_) => false, + } + }, + // vals + socket_path : { + match var("NOXIS_HAGENT_SOCKET_PATH") { + Ok(val) => PathBuf::from(val), + Err(_) => PathBuf::from("/var/run/enode/hostagent.sock"), + } + }, + log_to : { + match var("NOXIS_LOG_TO") { + Ok(val) => PathBuf::from(val), + Err(_) => PathBuf::from("./"), + } + }, + remote_server_url : { + match var("NOXIS_REMOTE_SERVER_URL") { + Ok(val) => val, + Err(_) => String::from("localhost"), + } + }, + config : { + match var("NOXIS_CONFIG_PATH") { + Ok(val) => PathBuf::from(val), + Err(_) => PathBuf::from("./settings.json"), + } + }, + metrics : { + match var("NOXIS_METRICS_MODE") { + Ok(val) => MetricsPrebootParams::from_env(&val), + Err(_) => MetricsPrebootParams::Full, + } + }, } - // existing log dir - if !self.log_to.exists() && !self.no_logs { - eprintln!("Error: Log-Dir not found or Noxis can't read it. LogDir was set to default"); - self.refresh_logs = false; - self.log_to = PathBuf::from("./"); - // return Err(Error::msg("Log Directory Not Found or Noxis can't read it. Cannot start")); - } - // existing sock file - if !self.config.exists() { - eprintln!("Error: Invalid character in config file. Config path was set to default"); - // TODO : ??? wtf is going with 2 paths - let config = PathBuf::from("/etc/enode/noxis/settings.json"); - if !config.exists() && self.no_sub { - return Err(Error::msg("Noxis cannot run without config. Create local config or enable pubsub mechanism")); - } - self.config = PathBuf::from("settings.json"); - // return Err(Error::msg("Local Config Not Found or Noxis can't read it. Cannot start")); - } - // redis server check - EnvVars::setup(&self); - Ok(self) } } // unit tests of preboot params parsing mech -#[cfg(test)] -mod preboot_unitests{ - use super::*; +// #[cfg(test)] +// mod preboot_unitests{ +// use super::*; - #[test] - fn parsing_zero_args() { - assert!(PrebootParams::try_parse_from(vec!["runner-rs"]).is_ok()) - } - #[test] - fn parsing_hagent_valid_args() { - assert!(PrebootParams::try_parse_from(vec![ - "runner-rs", - "--socket-path", "/path/to/socket" - ]).is_ok()) -} - #[test] - fn parsing_hagent_invalid_args() { - assert!(PrebootParams::try_parse_from(vec![ - "runner-rs", - "--socket-path", "/path/to/socket", - "--no-hagent" - ]).is_err()) - } - #[test] - fn parsing_log_valid_args() { - assert!(PrebootParams::try_parse_from(vec![ - "runner-rs", - "--log-to", "/path/to/log/dir" - ]).is_ok()) - } - #[test] - fn parsing_log_invalid_args() { - assert!(PrebootParams::try_parse_from(vec![ - "runner-rs", - "--log-to /path/to/log/dir", - "--no-logs" - ]).is_err()) - } - #[test] - fn parsing_config_valid_args() { - assert!(PrebootParams::try_parse_from(vec![ - "runner-rs", - "--no-sub", - "--remote-server-url", "redis://127.0.0.1" - ]).is_err()) - } - // #[test] - // fn parsing_config_invalid_args_noremote_nosub() { - // assert!(PrebootParams::try_parse_from(vec![ - // "runner-rs", - // "--no-remote-config", "--no-sub" - // ]).is_err()) - // } - #[test] - fn parsing_config_invalid_args_noremote_remoteurl() { - assert!(PrebootParams::try_parse_from(vec![ - "runner-rs", - "--no-sub", - "--remote-server-url", "redis://127.0.0.1" - ]).is_err()) - } - #[test] - fn parsing_metrics_args_using_value_enum() { - assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "full"]).is_ok()); - assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "system"]).is_ok()); - assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "processes"]).is_ok()); - assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "net"]).is_ok()); - assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "none"]).is_ok()); - assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "unusual_value"]).is_err()); - } -} \ No newline at end of file +// #[test] +// fn parsing_zero_args() { +// assert!(PrebootParams::try_parse_from(vec!["runner-rs"]).is_ok()) +// } +// #[test] +// fn parsing_hagent_valid_args() { +// assert!(PrebootParams::try_parse_from(vec![ +// "runner-rs", +// "--socket-path", "/path/to/socket" +// ]).is_ok()) +// } +// #[test] +// fn parsing_hagent_invalid_args() { +// assert!(PrebootParams::try_parse_from(vec![ +// "runner-rs", +// "--socket-path", "/path/to/socket", +// "--no-hagent" +// ]).is_err()) +// } +// #[test] +// fn parsing_log_valid_args() { +// assert!(PrebootParams::try_parse_from(vec![ +// "runner-rs", +// "--log-to", "/path/to/log/dir" +// ]).is_ok()) +// } +// #[test] +// fn parsing_log_invalid_args() { +// assert!(PrebootParams::try_parse_from(vec![ +// "runner-rs", +// "--log-to /path/to/log/dir", +// "--no-logs" +// ]).is_err()) +// } +// #[test] +// fn parsing_config_valid_args() { +// assert!(PrebootParams::try_parse_from(vec![ +// "runner-rs", +// "--no-sub", +// "--remote-server-url", "redis://127.0.0.1" +// ]).is_err()) +// } +// // #[test] +// // fn parsing_config_invalid_args_noremote_nosub() { +// // assert!(PrebootParams::try_parse_from(vec![ +// // "runner-rs", +// // "--no-remote-config", "--no-sub" +// // ]).is_err()) +// // } +// #[test] +// fn parsing_config_invalid_args_noremote_remoteurl() { +// assert!(PrebootParams::try_parse_from(vec![ +// "runner-rs", +// "--no-sub", +// "--remote-server-url", "redis://127.0.0.1" +// ]).is_err()) +// } +// #[test] +// fn parsing_metrics_args_using_value_enum() { +// assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "full"]).is_ok()); +// assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "system"]).is_ok()); +// assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "processes"]).is_ok()); +// assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "net"]).is_ok()); +// assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "none"]).is_ok()); +// assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "unusual_value"]).is_err()); +// } +// } \ No newline at end of file