diff --git a/noxis-cli/src/cli.rs b/noxis-cli/src/cli.rs index 677e721..6c07db6 100644 --- a/noxis-cli/src/cli.rs +++ b/noxis-cli/src/cli.rs @@ -1,6 +1,6 @@ use clap::{Parser, Subcommand}; -#[derive(Debug, Parser)] +#[derive(Debug, Parser, serde::Serialize, serde::Deserialize)] pub struct Cli { #[command( subcommand, @@ -9,7 +9,7 @@ pub struct Cli { command : Commands, } -#[derive(Debug, Subcommand)] +#[derive(Debug, Subcommand, serde::Serialize, serde::Deserialize)] pub enum Commands { #[command( about = "To get info about current Noxis status", @@ -43,7 +43,7 @@ pub enum Commands { Config(ConfigCommand), } -#[derive(Debug, Parser)] +#[derive(Debug, Parser, serde::Serialize, serde::Deserialize)] pub struct StartAction { #[arg( long="with-flags", @@ -53,13 +53,13 @@ pub struct StartAction { flags : Vec, } -#[derive(Debug, Parser)] +#[derive(Debug, Parser, serde::Serialize, serde::Deserialize)] pub struct ConfigCommand { #[command(subcommand)] action : ConfigAction, } -#[derive(Debug, Subcommand)] +#[derive(Debug, Subcommand, serde::Serialize, serde::Deserialize)] pub enum ConfigAction { #[command( about = "To change current Noxis configuration", @@ -75,7 +75,7 @@ pub enum ConfigAction { Reset, } -#[derive(Debug, Parser)] +#[derive(Debug, Parser, serde::Serialize, serde::Deserialize)] pub struct LocalConfig { // flag #[arg( @@ -91,7 +91,7 @@ pub struct LocalConfig { config : String, } -#[derive(Debug, Parser)] +#[derive(Debug, Parser, serde::Serialize, serde::Deserialize)] pub struct ProcessCommand { #[arg( help = "name of needed process", @@ -104,7 +104,7 @@ pub struct ProcessCommand { action : ProcessAction, } -#[derive(Debug, Subcommand)] +#[derive(Debug, Subcommand, serde::Serialize, serde::Deserialize)] enum ProcessAction { #[command( about = "To get info about current process status", diff --git a/noxis-cli/src/main.rs b/noxis-cli/src/main.rs index 718ec2f..0b9e00f 100644 --- a/noxis-cli/src/main.rs +++ b/noxis-cli/src/main.rs @@ -9,8 +9,6 @@ use anyhow::Result; #[tokio::main] async fn main() -> Result<()>{ let cli = Cli::parse(); - dbg!(&cli); - // println!("{:?}", cli); try_send(create_tcp_stream().await, cli).await?; Ok(()) } diff --git a/noxis-cli/src/net.rs b/noxis-cli/src/net.rs index 1c2e470..2e8c43a 100644 --- a/noxis-cli/src/net.rs +++ b/noxis-cli/src/net.rs @@ -11,14 +11,17 @@ pub async fn create_tcp_stream() -> Result { } pub async fn try_send(stream: Result, params: Cli) -> Result<()> { + use serde_json::to_string; let mut stream = stream?; loop { if stream.writable().await.is_err() { sleep(Duration::from_millis(100)).await; continue; } - let msg = format!("{:?}", params); + // let msg: Cli = from_str(&format!("{:?}", params))?; + let msg= to_string(¶ms)?; // let msg = r"HTTP/1.1 POST\r\nContent-Length: 14\r\nContent-Type: text/plain\r\n\r\nHello, World!@"; + stream.write_all(msg.as_bytes()).await?; // ... break; diff --git a/noxis-rs/Cargo.toml b/noxis-rs/Cargo.toml index cf86d18..62c917f 100644 --- a/noxis-rs/Cargo.toml +++ b/noxis-rs/Cargo.toml @@ -16,3 +16,4 @@ serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.118" sysinfo = "0.32.0" tokio = { version = "1.38.0", features = ["full", "time"] } +noxis-cli = { path = "../noxis-cli" } diff --git a/noxis-rs/Dockerfile b/noxis-rs/Dockerfile deleted file mode 100644 index 5882e02..0000000 --- a/noxis-rs/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM ubuntu - -RUN mkdir -p /usr/src/kii/ - -WORKDIR /usr/src/kii/ - -RUN mkdir monitor/ -RUN mkdir -p services/temp-process/ -RUN touch services/temp-process/dep.txt -RUN touch services/temp-process/run.sh -RUN echo "./services/temp-process/temp-process &>/dev/null" >> services/temp-process/run.sh - -COPY target/x86_64-unknown-linux-gnu/release/runner-rs monitor/ -COPY settings.json . -COPY temp-process services/temp-process/ - -RUN chmod +x services/temp-process/temp-process -RUN chmod +x services/temp-process/run.sh -RUN chmod +x monitor/runner-rs - -# some troubles with execution this row-cmd -# ?: cannot get while initializing container -RUN export ENODE_CID=$(cat /proc/self/mountinfo | grep "/docker/containers/" | head -1 | awk -F '/' "{print \$6}") - -ENTRYPOINT [ "/usr/src/kii/monitor/runner-rs" ] diff --git a/noxis-rs/src/options/cli_pipeline.rs b/noxis-rs/src/options/cli_pipeline.rs index b189a36..ad6a670 100644 --- a/noxis-rs/src/options/cli_pipeline.rs +++ b/noxis-rs/src/options/cli_pipeline.rs @@ -5,10 +5,24 @@ use tokio::time::{sleep, Duration}; use std::{borrow::BorrowMut, net::{IpAddr, Ipv4Addr}}; // use std::io::BufReader; use tokio::io::{BufReader, AsyncWriteExt, AsyncBufReadExt}; +use noxis_cli::Cli; +use serde_json::from_str; - +/// # Fn `init_cli_pipeline` +/// ## for catching all input requests from CLI +/// +/// *input* : - +/// +/// *output* : `anyhow::Result<()>` to wrap errors +/// +/// *initiator* : fn `main` +/// +/// *managing* : `TcpListener` object to handle requests +/// +/// *depends on* : - +/// pub async fn init_cli_pipeline() -> DynResult<()> { - return match init_listener().await { + match init_listener().await { Some(list) => { loop { if let Ok((socket, addr)) = list.accept().await { @@ -27,8 +41,21 @@ pub async fn init_cli_pipeline() -> DynResult<()> { } } +/// # Fn `init_listener` +/// ## for creating TCP-listener for communicating with CLI +/// +/// *input* : - +/// +/// *output* : `Some` if port 7753 was opened | None if not +/// +/// *initiator* : fn `init_cli_pipeline` +/// +/// *managing* : `TcpListener` object to handle requests +/// +/// *depends on* : `tokio::net::TcpListener` +/// async fn init_listener() -> Option { - return match TcpListener::bind("127.0.0.1:7753").await { + match TcpListener::bind("127.0.0.1:7753").await { Ok(listener) => { info!("Runner is listening localhost:7753"); Some(listener) @@ -40,17 +67,36 @@ async fn init_listener() -> Option { } } +/// # Fn `process_connection` +/// ## for processing input CLI requests +/// +/// *input* : mut stream: `TcpStream` +/// +/// *output* : - +/// +/// *initiator* : fn `init_cli_pipeline` +/// +/// *managing* : mutable object of `TcpStream` +/// +/// *depends on* : `tokio::net::TcpStream` +/// async fn process_connection(mut stream: TcpStream) { - // loop{ - // stream. - // } let buf_reader = BufReader::new(stream.borrow_mut()); let mut rqst = buf_reader.lines(); while let Ok(Some(line)) = rqst.next_line().await { if line.is_empty() { - break; + break + } + match from_str::(&line) { + Ok(req) => { + // TODO: func wrapper + dbg!(req); + }, + Err(_) => { + break + }, } println!("{}", line); } diff --git a/noxis-rs/src/options/config.rs b/noxis-rs/src/options/config.rs index f7b5f26..0bc5ecc 100644 --- a/noxis-rs/src/options/config.rs +++ b/noxis-rs/src/options/config.rs @@ -1,4 +1,4 @@ -use crate::options::structs::*; +use super::structs::*; use log::{error, info, warn}; use redis::{Client, Connection}; use std::fs::OpenOptions; @@ -7,7 +7,7 @@ use std::os::unix::process::CommandExt; use std::process::Command; use std::sync::Arc; use std::{env, fs}; -use std::fmt::format; +// use std::fmt::format; use super::preboot::PrebootParams; use tokio::time::{Duration, sleep}; @@ -51,7 +51,10 @@ fn load_processes(json_filename: &str) -> Option { pub async fn get_actual_config(params : Arc) -> Option { // * if no local conf -> loop and +inf getting conf from redis server // * if local conf -> once getting conf from redis server - let config_path = params.config.to_str()?; + let config_path = params.config.to_str().unwrap_or_else(|| { + error!("Invalid character in config file. Config path was set to default"); + "settings.json" + }); info!("Configurating config module with params: no-remote-config={}, no-sub={}, local config path={:?}, remote server={}", params.no_remote_config, params.no_sub, params.config, params.remote_server_url); match load_processes(config_path) { Some(local_conf) => { @@ -198,7 +201,6 @@ fn once_get_remote_configuration(serv_info: &str) -> Option { } }, Err(_) => { - warn!("Cannot get config from Redis Server. Empty channel"); None }, } diff --git a/noxis-rs/src/options/preboot.rs b/noxis-rs/src/options/preboot.rs index 02e013f..8130e96 100644 --- a/noxis-rs/src/options/preboot.rs +++ b/noxis-rs/src/options/preboot.rs @@ -1,8 +1,23 @@ // module to handle pre-boot params of the monitor +#[allow(unused_imports)] use anyhow::{Result, Ok, Error}; use clap::Parser; use std::path::PathBuf; +const SOCKET_PATH: &str = "/var/run/enode/hostagent.sock"; + +/// # Enum `MetricsPrebootParams` +/// ## for setting up metrics mode as preboot param from command prompt +/// +/// examples: +/// ``` +/// noxis-rs ... --metrics full +/// noxis-rs ... --metrics system +/// noxis-rs ... --metrics processes +/// noxis-rs ... --metrics net +/// noxis-rs ... --metrics none +/// ``` +/// #[derive(clap::ValueEnum, Debug, Clone)] pub enum MetricsPrebootParams { Full, @@ -12,6 +27,8 @@ pub enum MetricsPrebootParams { None, } +/// # `std::fmt::Display` implementation for `MetricsPrebootParams` +/// ## to enable parsing object to String impl std::fmt::Display for MetricsPrebootParams { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { @@ -24,6 +41,71 @@ impl std::fmt::Display for MetricsPrebootParams { } } +/// # struct `PrebootParams` +/// ## to parse and set up all modes as preboot params from command prompt +/// +/// ### args : +/// +/// `--no-hagent` - to disable hagent work module and set up work mode as autonomous +/// ### usage : +/// ``` bash +/// noxis-rs ... --no-hagent ... +/// ``` +/// +/// +/// `--no-logs` - to disable logging at all +/// ### usage : +/// ``` bash +/// noxis-rs ... --no-logs ... +/// ``` +/// +/// `--refresh-logs` - to truncate logs directory +/// ### usage : +/// ``` bash +/// noxis-rs ... --refresh-logs ... +/// ``` +/// +/// `--no-remote-config` - to disable work with Redis as config producer +/// ### usage : +/// ``` bash +/// noxis-rs ... --no-remote-config ... +/// ``` +/// +/// `--no-sub` - to disable Redis subscribtion mechanism +/// ### usage : +/// ``` bash +/// noxis-rs ... --no-sub ... +/// ``` +/// +/// `--socket-path` - to set Unix Domain Socket file's directory +/// ### usage : +/// ``` bash +/// noxis-rs ... --socket-path /var/run/enode/hostagent.sock ... +/// ``` +/// +/// `--log-to` - to set directory for logs +/// ### usage : +/// ``` bash +/// noxis-rs ... --log-to /dir/to/logs/ ... +/// ``` +/// +/// `--remote-server-url` - to set Redis Server +/// ### usage : +/// ``` bash +/// noxis-rs ... --remote-server-url 192.168.28.12 ... +/// ``` +/// +/// `--config` - to set Noxis' config full path +/// ### usage : +/// ``` bash +/// noxis-rs ... --config /etc/enode/settings.json ... +/// ``` +/// +/// `--metrics` - to set metrics mode +/// ### usage : +/// ``` bash +/// noxis-rs ... --metrics full ... +/// ``` #[derive(Debug, Parser)] pub struct PrebootParams { // actions @@ -101,18 +183,36 @@ pub struct PrebootParams { pub metrics: MetricsPrebootParams, } +/// # implementation for `MetricsPrebootParams` +/// ## to enable validation mechanism impl PrebootParams { - pub fn validate(self) -> Result { + pub fn validate(mut self) -> Result { if !self.socket_path.exists() && !self.no_hostagent { - return Err(Error::msg("Socket-file not found or Noxis can't read it. Cannot start")); + 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); + } + } + // return Err(Error::msg("Socket-file not found or Noxis can't read it. Cannot start")); } // existing log dir if !self.log_to.exists() && !self.no_logs { - return Err(Error::msg("Log Directory Not Found or Noxis can't read it. Cannot start")); + eprintln!("Error: Log-Dir not found or Noxis can't read it. LogDir was set to default"); + 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() { - return Err(Error::msg("Local Config Not Found or Noxis can't read it. Cannot start")); + eprintln!("Error: Invalid character in config file. Config path was set to default"); + 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 Ok(self) @@ -127,7 +227,7 @@ mod preboot_unitests{ #[test] fn parsing_zero_args() { - assert!(PrebootParams::try_parse_from(vec!["runner-rs"]).is_ok()) + assert!(PrebootParams::try_parse_from(vec!["runner-rs"]).is_ok()) } #[test] fn parsing_hagent_valid_args() { diff --git a/noxis-rs/src/options/signals.rs b/noxis-rs/src/options/signals.rs index c107c74..7604bde 100644 --- a/noxis-rs/src/options/signals.rs +++ b/noxis-rs/src/options/signals.rs @@ -1,4 +1,4 @@ -use crate::options::structs::CustomError; +use super::structs::CustomError; use std::sync::Arc; use tokio::io; use tokio::sync::mpsc; diff --git a/noxis-rs/src/utils.rs b/noxis-rs/src/utils.rs index 86e63f5..9ead34d 100644 --- a/noxis-rs/src/utils.rs +++ b/noxis-rs/src/utils.rs @@ -156,7 +156,7 @@ async fn process_protocol_symbol(proc: Arc, val: u8) -> Result< // }, // 101 - Impermissible trigger values in JSON 101 => { - error!("Impermissible trigger values in JSON in {}'s block. Killing thread...", proc.name); + error!("Impermissible trigger values in JSON in {}'s block. Killing thread...", &proc.name); if is_active(&proc.name).await { terminate_process(&proc.name).await; } @@ -164,9 +164,10 @@ async fn process_protocol_symbol(proc: Arc, val: u8) -> Result< }, // // 121 - Cannot create valid watcher for file dependency + // todo : think about valid situation 121 => { - error!("Cannot create valid watcher for {}'s file dependency. Terminating thread...", proc.name); - let _ = terminate_process("runner-rs").await; + error!("Cannot create valid watcher for file dependency. Terminating {} process...", &proc.name); + let _ = terminate_process(&proc.name).await; return Err(CustomError::Fatal) }, // 111 - global thread termination with killing current child in a face diff --git a/noxis-rs/src/utils/files.rs b/noxis-rs/src/utils/files.rs index 28346c2..639ced2 100644 --- a/noxis-rs/src/utils/files.rs +++ b/noxis-rs/src/utils/files.rs @@ -1,5 +1,5 @@ use crate::options::structs::{CustomError, Files}; -use crate::utils::prcs::{is_active, is_frozen}; +use super::prcs::{is_active, is_frozen}; use inotify::{EventMask, Inotify, WatchMask}; use std::borrow::BorrowMut; use std::path::Path; diff --git a/noxis-rs/src/utils/metrics.rs b/noxis-rs/src/utils/metrics.rs index 0648a3e..756e44b 100644 --- a/noxis-rs/src/utils/metrics.rs +++ b/noxis-rs/src/utils/metrics.rs @@ -7,7 +7,7 @@ use crate::options::structs::TrackingProcess; use sysinfo::{Process, System}; use tokio::join; use crate::options::structs::{ProcessMetrics, ContainerMetrics}; -use crate::utils::get_container_id; +use super::get_container_id; // use pcap::{Device, Capture, Active}; // use std::net::Ipv4Addr; // use anyhow::{Result, Ok}; diff --git a/noxis-rs/src/utils/services.rs b/noxis-rs/src/utils/services.rs index d89ee6b..fb51f7d 100644 --- a/noxis-rs/src/utils/services.rs +++ b/noxis-rs/src/utils/services.rs @@ -1,5 +1,5 @@ use crate::options::structs::{CustomError, Services}; -use crate::utils::prcs::{is_active, is_frozen}; +use super::prcs::{is_active, is_frozen}; use log::{error, warn}; use std::net::{TcpStream, ToSocketAddrs}; use std::sync::Arc;