From ce4c97a8bb8912167e144d5459928eb4a40e09f8 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Wed, 27 Sep 2023 12:26:31 +0200 Subject: [PATCH 01/14] Refactoring internal structure. Preparation for implementation of next subcommand --- rust/agama-cli/src/logs.rs | 67 +++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 6cb8855ebd..c3fe72688f 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -10,6 +10,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use tempdir::TempDir; +// definition of "agama logs" subcommands, see clap crate for details #[derive(Subcommand, Debug)] pub enum LogsCommands { /// Collects and stores logs in a tar archive @@ -22,10 +23,30 @@ pub enum LogsCommands { List, } +// main entry point called from agama CLI main loop pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { match subcommand { - LogsCommands::Store { verbose } => Ok(store(verbose)?), - LogsCommands::List => Err(anyhow::anyhow!("Not implemented")), + LogsCommands::Store { verbose } => { + // feed internal options structure by what was received from user + // for now we always use / add defaults if any + let options = LogOptions { + paths: DEFAULT_PATHS.iter().map(|p| p.to_string()).collect(), + commands: DEFAULT_COMMANDS.iter().map(|p| p.to_string()).collect(), + verbose: verbose, + }; + + Ok(store(options)?) + }, + LogsCommands::List => { + let options = LogOptions { + paths: Vec::new(), + commands: Vec::new(), + verbose: false, + }; + + list(options); + Err(anyhow::anyhow!("Not implemented")) + }, } } @@ -76,6 +97,14 @@ fn show(show: bool, text: &str) { print!("{}", text); } +// Configurable parameters of the "agama logs" which can be +// set by user when calling a (sub)command +struct LogOptions { + paths: Vec, + commands: Vec, + verbose: bool, +} + // Struct for log represented by a file struct LogPath { // log source @@ -181,33 +210,33 @@ impl LogItem for LogCmd { } } -// collect existing / requested paths which should already exist turns them into list of log -// sources -fn paths_to_log_sources(paths: &[&str], tmp_dir: &TempDir) -> Vec> { +// Collect existing / requested paths which should already exist in the system. +// Turns them into list of log sources +fn paths_to_log_sources(paths: &Vec, tmp_dir: &TempDir) -> Vec> { let mut log_sources: Vec> = Vec::new(); - for path in paths { + for path in paths.iter() { // assumption: path is full path if Path::new(path).try_exists().is_ok() { - log_sources.push(Box::new(LogPath::new(path, tmp_dir.path()))); + log_sources.push(Box::new(LogPath::new(path.as_str(), tmp_dir.path()))); } } log_sources } -// some info can be collected via particular commands only, turn it into log sources -fn cmds_to_log_sources(commands: &[&str], tmp_dir: &TempDir) -> Vec> { +// Some info can be collected via particular commands only, turn it into log sources +fn cmds_to_log_sources(commands: &Vec, tmp_dir: &TempDir) -> Vec> { let mut log_sources: Vec> = Vec::new(); - for cmd in commands { - log_sources.push(Box::new(LogCmd::new(cmd, tmp_dir.path()))); + for cmd in commands.iter() { + log_sources.push(Box::new(LogCmd::new(cmd.as_str(), tmp_dir.path()))); } log_sources } -// compress given directory into a tar archive +// Compress given directory into a tar archive fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { let compression = DEFAULT_COMPRESSION.0; let compress_cmd = format!( @@ -230,15 +259,16 @@ fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { } } -// handler for the "agama logs store" subcommand -fn store(verbose: bool) -> Result<(), io::Error> { +// Handler for the "agama logs store" subcommand +fn store(options: LogOptions) -> Result<(), io::Error> { if !Uid::effective().is_root() { panic!("No Root, no logs. Sorry."); } // preparation, e.g. in later features some log commands can be added / excluded per users request or - let commands = DEFAULT_COMMANDS; - let paths = DEFAULT_PATHS; + let commands = options.commands; + let paths = options.paths; + let verbose = options.verbose; let result = format!("{}.{}", DEFAULT_RESULT, DEFAULT_COMPRESSION.1); showln(verbose, "Collecting Agama logs:"); @@ -278,3 +308,8 @@ fn store(verbose: bool) -> Result<(), io::Error> { compress_logs(&tmp_dir, &result) } + +// Handler for the "agama logs list" subcommand +fn list(_options: LogOptions) +{ +} From 2051e4f7e4a6bb46c561b9b2e3fa5bb02375f504 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Wed, 27 Sep 2023 19:09:10 +0200 Subject: [PATCH 02/14] Implemented agama logs list subcommand to list logs collected by default --- rust/agama-cli/src/logs.rs | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index c3fe72688f..5f4a4dcd88 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -29,23 +29,18 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { LogsCommands::Store { verbose } => { // feed internal options structure by what was received from user // for now we always use / add defaults if any - let options = LogOptions { - paths: DEFAULT_PATHS.iter().map(|p| p.to_string()).collect(), - commands: DEFAULT_COMMANDS.iter().map(|p| p.to_string()).collect(), - verbose: verbose, - }; + let mut options = LogOptions::new(); + + options.verbose = verbose; Ok(store(options)?) }, LogsCommands::List => { - let options = LogOptions { - paths: Vec::new(), - commands: Vec::new(), - verbose: false, - }; + let options = LogOptions::new(); list(options); - Err(anyhow::anyhow!("Not implemented")) + + Ok(()) }, } } @@ -105,6 +100,16 @@ struct LogOptions { verbose: bool, } +impl LogOptions { + fn new() -> Self { + Self { + paths: DEFAULT_PATHS.iter().map(|p| p.to_string()).collect(), + commands: DEFAULT_COMMANDS.iter().map(|p| p.to_string()).collect(), + verbose: false, + } + } +} + // Struct for log represented by a file struct LogPath { // log source @@ -310,6 +315,13 @@ fn store(options: LogOptions) -> Result<(), io::Error> { } // Handler for the "agama logs list" subcommand -fn list(_options: LogOptions) +fn list(options: LogOptions) { + for list in [options.paths, options.commands] { + for item in list.iter() { + println!("{}", item); + } + + println!(); + } } From f8f89c86f56a3e9119333cf707fab1bfe8c39bfb Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 29 Sep 2023 09:35:40 +0200 Subject: [PATCH 03/14] Formatting --- rust/agama-cli/src/logs.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 5f4a4dcd88..7bc544f7ca 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -34,14 +34,14 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { options.verbose = verbose; Ok(store(options)?) - }, + } LogsCommands::List => { let options = LogOptions::new(); list(options); Ok(()) - }, + } } } @@ -315,8 +315,7 @@ fn store(options: LogOptions) -> Result<(), io::Error> { } // Handler for the "agama logs list" subcommand -fn list(options: LogOptions) -{ +fn list(options: LogOptions) { for list in [options.paths, options.commands] { for item in list.iter() { println!("{}", item); From 174afee3647e5197dd01a48adccaf3533061ee5f Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 29 Sep 2023 10:46:55 +0200 Subject: [PATCH 04/14] Change in archive - compress dir not only its content --- rust/agama-cli/src/logs.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 7bc544f7ca..452b9cc401 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -244,24 +244,28 @@ fn cmds_to_log_sources(commands: &Vec, tmp_dir: &TempDir) -> Vec io::Result<()> { let compression = DEFAULT_COMPRESSION.0; + let tmp_path = tmp_dir.path(); + let path = tmp_path.parent().unwrap().as_os_str().to_str().ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; + let dir = tmp_path.file_name().unwrap().to_str().ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; let compress_cmd = format!( - "tar -c -f {} --warning=no-file-changed --{} --dereference -C {} .", + "tar -c -f {} --warning=no-file-changed --{} --dereference -C {} {}", result, compression, - tmp_dir.path().display() + path, + dir, ); let cmd_parts = compress_cmd.split_whitespace().collect::>(); - match Command::new(cmd_parts[0]) + Command::new(cmd_parts[0]) .args(cmd_parts[1..].iter()) .status() - { - Ok(_o) => Ok(()), - Err(_e) => Err(io::Error::new( - io::ErrorKind::Other, - "Cannot create tar archive", - )), - } + .ok_or( + Ok(_o) => Ok(()), + Err(_e) => Err(io::Error::new( + io::ErrorKind::Other, + "Cannot create tar archive", + ) + )) } // Handler for the "agama logs store" subcommand From 139b1b14328497065b1276ae80bde17e2766b5d9 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 29 Sep 2023 11:55:02 +0200 Subject: [PATCH 05/14] Fixed handling of compress command result --- rust/agama-cli/src/logs.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 452b9cc401..ebe5a985ec 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -255,17 +255,19 @@ fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { dir, ); let cmd_parts = compress_cmd.split_whitespace().collect::>(); - - Command::new(cmd_parts[0]) + let res = Command::new(cmd_parts[0]) .args(cmd_parts[1..].iter()) - .status() - .ok_or( - Ok(_o) => Ok(()), - Err(_e) => Err(io::Error::new( - io::ErrorKind::Other, - "Cannot create tar archive", - ) + .status()?; + + if res.success() { + Ok(()) + } + else { + Err(io::Error::new( + io::ErrorKind::Other, + "Cannot create tar archive", )) + } } // Handler for the "agama logs store" subcommand From 379c2ac6f9647d835f096204a2695a91f7a6c826 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 29 Sep 2023 12:17:34 +0200 Subject: [PATCH 06/14] Formatting --- rust/agama-cli/src/logs.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index ebe5a985ec..b328230573 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -244,15 +244,22 @@ fn cmds_to_log_sources(commands: &Vec, tmp_dir: &TempDir) -> Vec io::Result<()> { let compression = DEFAULT_COMPRESSION.0; - let tmp_path = tmp_dir.path(); - let path = tmp_path.parent().unwrap().as_os_str().to_str().ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; - let dir = tmp_path.file_name().unwrap().to_str().ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; + let tmp_path = tmp_dir + .path() + .parent() + .unwrap() + .as_os_str() + .to_str() + .ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; + let dir = tmp_dir + .path() + .file_name() + .unwrap() + .to_str() + .ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; let compress_cmd = format!( "tar -c -f {} --warning=no-file-changed --{} --dereference -C {} {}", - result, - compression, - path, - dir, + result, compression, tmp_path, dir, ); let cmd_parts = compress_cmd.split_whitespace().collect::>(); let res = Command::new(cmd_parts[0]) @@ -261,8 +268,7 @@ fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { if res.success() { Ok(()) - } - else { + } else { Err(io::Error::new( io::ErrorKind::Other, "Cannot create tar archive", From 0e4e0ea6722c41b5f0aa9b5c5d243b2f44cf8f10 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 29 Sep 2023 21:47:13 +0200 Subject: [PATCH 07/14] Do not create files with spaces in name when storing log command --- rust/agama-cli/src/logs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index b328230573..68ac6d9ea7 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -196,7 +196,10 @@ impl LogItem for LogCmd { } fn to(&self) -> PathBuf { - self.dst_path.as_path().join(format!("{}", self.cmd)) + let mut file_name = self.cmd.clone(); + + file_name.retain(|c| c != ' '); + self.dst_path.as_path().join(format!("{}", file_name)) } fn store(&self) -> Result<(), io::Error> { From f6e27a64d03fbc59335dc2d9ad4c0c7962bc02a5 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Wed, 4 Oct 2023 08:35:47 +0200 Subject: [PATCH 08/14] Implemented default trait for LogOptions --- rust/agama-cli/src/logs.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 68ac6d9ea7..3cd38b1a4b 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -29,16 +29,12 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { LogsCommands::Store { verbose } => { // feed internal options structure by what was received from user // for now we always use / add defaults if any - let mut options = LogOptions::new(); - - options.verbose = verbose; + let options = LogOptions { verbose: verbose, ..Default::default() }; Ok(store(options)?) } LogsCommands::List => { - let options = LogOptions::new(); - - list(options); + list(LogOptions::default()); Ok(()) } @@ -100,8 +96,8 @@ struct LogOptions { verbose: bool, } -impl LogOptions { - fn new() -> Self { +impl Default for LogOptions { + fn default() -> Self { Self { paths: DEFAULT_PATHS.iter().map(|p| p.to_string()).collect(), commands: DEFAULT_COMMANDS.iter().map(|p| p.to_string()).collect(), From 5ebc18dd93529da8c8598d1231d405828031f690 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Wed, 4 Oct 2023 08:53:31 +0200 Subject: [PATCH 09/14] Modified output of agama logs list --- rust/agama-cli/src/logs.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 3cd38b1a4b..bab533fb67 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -327,9 +327,11 @@ fn store(options: LogOptions) -> Result<(), io::Error> { // Handler for the "agama logs list" subcommand fn list(options: LogOptions) { - for list in [options.paths, options.commands] { - for item in list.iter() { - println!("{}", item); + for list in [ ("Log paths: ", options.paths), ("Log commands: ", options.commands)] { + println!("{}", list.0); + + for item in list.1.iter() { + println!("\t{}", item); } println!(); From 769a32e31af3cfc81d0f718904558492d86647df Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Wed, 4 Oct 2023 10:25:37 +0200 Subject: [PATCH 10/14] Formatting --- rust/agama-cli/src/logs.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index bab533fb67..e9f02ee37e 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -29,7 +29,10 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { LogsCommands::Store { verbose } => { // feed internal options structure by what was received from user // for now we always use / add defaults if any - let options = LogOptions { verbose: verbose, ..Default::default() }; + let options = LogOptions { + verbose: verbose, + ..Default::default() + }; Ok(store(options)?) } @@ -246,16 +249,28 @@ fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { let tmp_path = tmp_dir .path() .parent() - .unwrap() + .ok_or(io::Error::new( + io::ErrorKind::InvalidInput, + "Malformed path to temporary directory", + ))? .as_os_str() .to_str() - .ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; + .ok_or(io::Error::new( + io::ErrorKind::InvalidInput, + "Malformed path to temporary directory", + ))?; let dir = tmp_dir .path() .file_name() - .unwrap() + .ok_or(io::Error::new( + io::ErrorKind::InvalidInput, + "Malformed path to temporary directory", + ))? .to_str() - .ok_or(io::Error::new(io::ErrorKind::InvalidInput, "Wrong path"))?; + .ok_or(io::Error::new( + io::ErrorKind::InvalidInput, + "Malformed path to temporary director", + ))?; let compress_cmd = format!( "tar -c -f {} --warning=no-file-changed --{} --dereference -C {} {}", result, compression, tmp_path, dir, @@ -327,7 +342,10 @@ fn store(options: LogOptions) -> Result<(), io::Error> { // Handler for the "agama logs list" subcommand fn list(options: LogOptions) { - for list in [ ("Log paths: ", options.paths), ("Log commands: ", options.commands)] { + for list in [ + ("Log paths: ", options.paths), + ("Log commands: ", options.commands), + ] { println!("{}", list.0); for item in list.1.iter() { From 8b136394d17111aa96d11c55cc1981a3a9e7b060 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 6 Oct 2023 09:31:54 +0200 Subject: [PATCH 11/14] Support for user defined filenames for logs generated by a command --- rust/agama-cli/src/logs.rs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index e9f02ee37e..7c59d6ef7b 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -44,10 +44,10 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { } } -const DEFAULT_COMMANDS: [&str; 3] = [ - "journalctl -u agama", - "journalctl -u agama-auto", - "journalctl --dmesg", +const DEFAULT_COMMANDS: [(&str,&str); 3] = [ + ("journalctl -u agama", "agama"), + ("journalctl -u agama-auto", "agama-auto"), + ("journalctl --dmesg", "dmesg"), ]; const DEFAULT_PATHS: [&str; 14] = [ @@ -95,7 +95,7 @@ fn show(show: bool, text: &str) { // set by user when calling a (sub)command struct LogOptions { paths: Vec, - commands: Vec, + commands: Vec<(String, String)>, verbose: bool, } @@ -103,7 +103,7 @@ impl Default for LogOptions { fn default() -> Self { Self { paths: DEFAULT_PATHS.iter().map(|p| p.to_string()).collect(), - commands: DEFAULT_COMMANDS.iter().map(|p| p.to_string()).collect(), + commands: DEFAULT_COMMANDS.iter().map(|p| (p.0.to_string(), p.1.to_string())).collect(), verbose: false, } } @@ -132,14 +132,18 @@ struct LogCmd { // command which stdout / stderr is logged cmd: String, + // user defined log file name (if any) + file_name: String, + // place where to collect logs dst_path: PathBuf, } impl LogCmd { - fn new(cmd: &str, dst: &Path) -> Self { + fn new(cmd: &str, file_name: &str, dst: &Path) -> Self { Self { cmd: cmd.to_string(), + file_name: file_name.to_string(), dst_path: dst.to_owned(), } } @@ -195,7 +199,13 @@ impl LogItem for LogCmd { } fn to(&self) -> PathBuf { - let mut file_name = self.cmd.clone(); + let mut file_name; + + if self.file_name.is_empty() { + file_name = self.cmd.clone(); + } else { + file_name = self.file_name.clone(); + }; file_name.retain(|c| c != ' '); self.dst_path.as_path().join(format!("{}", file_name)) @@ -233,11 +243,11 @@ fn paths_to_log_sources(paths: &Vec, tmp_dir: &TempDir) -> Vec, tmp_dir: &TempDir) -> Vec> { +fn cmds_to_log_sources(commands: &Vec<(String, String)>, tmp_dir: &TempDir) -> Vec> { let mut log_sources: Vec> = Vec::new(); for cmd in commands.iter() { - log_sources.push(Box::new(LogCmd::new(cmd.as_str(), tmp_dir.path()))); + log_sources.push(Box::new(LogCmd::new(cmd.0.as_str(), cmd.1.as_str(), tmp_dir.path()))); } log_sources @@ -344,7 +354,7 @@ fn store(options: LogOptions) -> Result<(), io::Error> { fn list(options: LogOptions) { for list in [ ("Log paths: ", options.paths), - ("Log commands: ", options.commands), + ("Log commands: ", options.commands.iter().map(|c| c.0.clone()).collect()), ] { println!("{}", list.0); From 64ea4ae23b77b0201c64c5e99450c7e5ceed6d0b Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 6 Oct 2023 09:44:00 +0200 Subject: [PATCH 12/14] Formatting --- rust/agama-cli/src/logs.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 7c59d6ef7b..bd690eb2b5 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -44,7 +44,7 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { } } -const DEFAULT_COMMANDS: [(&str,&str); 3] = [ +const DEFAULT_COMMANDS: [(&str, &str); 3] = [ ("journalctl -u agama", "agama"), ("journalctl -u agama-auto", "agama-auto"), ("journalctl --dmesg", "dmesg"), @@ -103,7 +103,10 @@ impl Default for LogOptions { fn default() -> Self { Self { paths: DEFAULT_PATHS.iter().map(|p| p.to_string()).collect(), - commands: DEFAULT_COMMANDS.iter().map(|p| (p.0.to_string(), p.1.to_string())).collect(), + commands: DEFAULT_COMMANDS + .iter() + .map(|p| (p.0.to_string(), p.1.to_string())) + .collect(), verbose: false, } } @@ -243,11 +246,18 @@ fn paths_to_log_sources(paths: &Vec, tmp_dir: &TempDir) -> Vec, tmp_dir: &TempDir) -> Vec> { +fn cmds_to_log_sources( + commands: &Vec<(String, String)>, + tmp_dir: &TempDir, +) -> Vec> { let mut log_sources: Vec> = Vec::new(); for cmd in commands.iter() { - log_sources.push(Box::new(LogCmd::new(cmd.0.as_str(), cmd.1.as_str(), tmp_dir.path()))); + log_sources.push(Box::new(LogCmd::new( + cmd.0.as_str(), + cmd.1.as_str(), + tmp_dir.path(), + ))); } log_sources @@ -354,7 +364,10 @@ fn store(options: LogOptions) -> Result<(), io::Error> { fn list(options: LogOptions) { for list in [ ("Log paths: ", options.paths), - ("Log commands: ", options.commands.iter().map(|c| c.0.clone()).collect()), + ( + "Log commands: ", + options.commands.iter().map(|c| c.0.clone()).collect(), + ), ] { println!("{}", list.0); From 7b890e04ce7f18f3d0460b8f8ac704b142f3d701 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 6 Oct 2023 12:37:22 +0200 Subject: [PATCH 13/14] Documentation and a few minor improvements --- rust/agama-cli/src/logs.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index bd690eb2b5..c84cbac3e5 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -30,7 +30,7 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { // feed internal options structure by what was received from user // for now we always use / add defaults if any let options = LogOptions { - verbose: verbose, + verbose, ..Default::default() }; @@ -45,6 +45,7 @@ pub async fn run(subcommand: LogsCommands) -> anyhow::Result<()> { } const DEFAULT_COMMANDS: [(&str, &str); 3] = [ + // (, ) ("journalctl -u agama", "agama"), ("journalctl -u agama-auto", "agama-auto"), ("journalctl --dmesg", "dmesg"), @@ -70,6 +71,8 @@ const DEFAULT_PATHS: [&str; 14] = [ ]; const DEFAULT_RESULT: &str = "/tmp/agama_logs"; +// what compression is used by default: +// (, ) const DEFAULT_COMPRESSION: (&str, &str) = ("bzip2", "tar.bz2"); const DEFAULT_TMP_DIR: &str = "agama-logs"; @@ -105,7 +108,7 @@ impl Default for LogOptions { paths: DEFAULT_PATHS.iter().map(|p| p.to_string()).collect(), commands: DEFAULT_COMMANDS .iter() - .map(|p| (p.0.to_string(), p.1.to_string())) + .map(|(cmd, name)| (cmd.to_string(), name.to_string())) .collect(), verbose: false, } From 335e9537c2f248adcb134edf7a63deafbc532b03 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Tue, 10 Oct 2023 09:00:13 +0200 Subject: [PATCH 14/14] Code cleanup as a consequence of the review --- rust/agama-cli/src/logs.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index c84cbac3e5..8a5ec1bcb8 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -272,12 +272,7 @@ fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { let tmp_path = tmp_dir .path() .parent() - .ok_or(io::Error::new( - io::ErrorKind::InvalidInput, - "Malformed path to temporary directory", - ))? - .as_os_str() - .to_str() + .and_then(|p| p.as_os_str().to_str()) .ok_or(io::Error::new( io::ErrorKind::InvalidInput, "Malformed path to temporary directory", @@ -285,11 +280,7 @@ fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { let dir = tmp_dir .path() .file_name() - .ok_or(io::Error::new( - io::ErrorKind::InvalidInput, - "Malformed path to temporary directory", - ))? - .to_str() + .and_then(|f| f.to_str()) .ok_or(io::Error::new( io::ErrorKind::InvalidInput, "Malformed path to temporary director",