From c1b3511c062fdf4b2cd2e36887be90014328112a Mon Sep 17 00:00:00 2001 From: veeso Date: Sun, 16 May 2021 22:26:16 +0200 Subject: [PATCH] Working on logging --- src/filetransfer/mod.rs | 4 +- src/host/mod.rs | 212 +++++++++++++++++++++++---------- src/system/bookmarks_client.rs | 81 ++++++++++--- src/system/config_client.rs | 41 +++++-- src/system/sshkey_storage.rs | 7 +- 5 files changed, 258 insertions(+), 87 deletions(-) diff --git a/src/filetransfer/mod.rs b/src/filetransfer/mod.rs index 028e2ff..fff23c4 100644 --- a/src/filetransfer/mod.rs +++ b/src/filetransfer/mod.rs @@ -319,14 +319,14 @@ impl std::string::ToString for FileTransferProtocol { } impl std::str::FromStr for FileTransferProtocol { - type Err = (); + type Err = String; fn from_str(s: &str) -> Result { match s.to_ascii_uppercase().as_str() { "FTP" => Ok(FileTransferProtocol::Ftp(false)), "FTPS" => Ok(FileTransferProtocol::Ftp(true)), "SCP" => Ok(FileTransferProtocol::Scp), "SFTP" => Ok(FileTransferProtocol::Sftp), - _ => Err(()), + _ => Err(s.to_string()), } } } diff --git a/src/host/mod.rs b/src/host/mod.rs index dcb6162..f3215bc 100644 --- a/src/host/mod.rs +++ b/src/host/mod.rs @@ -125,12 +125,17 @@ impl Localhost { /// /// Instantiates a new Localhost struct pub fn new(wrkdir: PathBuf) -> Result { + debug!("Initializing localhost at {}", wrkdir.display()); let mut host: Localhost = Localhost { wrkdir, files: Vec::new(), }; // Check if dir exists if !host.file_exists(host.wrkdir.as_path()) { + error!( + "Failed to initialize localhost: {} doesn't exist", + host.wrkdir.display() + ); return Err(HostError::new( HostErrorType::NoSuchFileOrDirectory, None, @@ -140,8 +145,15 @@ impl Localhost { // Retrieve files for provided path host.files = match host.scan_dir(host.wrkdir.as_path()) { Ok(files) => files, - Err(err) => return Err(err), + Err(err) => { + error!( + "Failed to initialize localhost: could not scan wrkdir: {}", + err + ); + return Err(err); + } }; + info!("Localhost initialized with success"); Ok(host) } @@ -165,8 +177,10 @@ impl Localhost { /// Change working directory with the new provided directory pub fn change_wrkdir(&mut self, new_dir: &Path) -> Result { let new_dir: PathBuf = self.to_abs_path(new_dir); + info!("Changing localhost directory to {}...", new_dir.display()); // Check whether directory exists if !self.file_exists(new_dir.as_path()) { + error!("Could not change directory: No such file or directory"); return Err(HostError::new( HostErrorType::NoSuchFileOrDirectory, None, @@ -174,10 +188,11 @@ impl Localhost { )); } // Change directory - if std::env::set_current_dir(new_dir.as_path()).is_err() { + if let Err(err) = std::env::set_current_dir(new_dir.as_path()) { + error!("Could not enter directory: {}", err); return Err(HostError::new( HostErrorType::NoSuchFileOrDirectory, - None, + Some(err), new_dir.as_path(), )); } @@ -189,11 +204,13 @@ impl Localhost { self.files = match self.scan_dir(self.wrkdir.as_path()) { Ok(files) => files, Err(err) => { + error!("Could not scan new directory: {}", err); // Restore directory self.wrkdir = prev_dir; return Err(err); } }; + debug!("Changed directory to {}", self.wrkdir.display()); Ok(self.wrkdir.clone()) } @@ -210,6 +227,7 @@ impl Localhost { /// ignex: don't report error if directory already exists pub fn mkdir_ex(&mut self, dir_name: &Path, ignex: bool) -> Result<(), HostError> { let dir_path: PathBuf = self.to_abs_path(dir_name); + info!("Making directory {}", dir_path.display()); // If dir already exists, return Error if dir_path.exists() { match ignex { @@ -229,13 +247,17 @@ impl Localhost { if dir_name.is_relative() { self.files = self.scan_dir(self.wrkdir.as_path())?; } + info!("Created directory {}", dir_path.display()); Ok(()) } - Err(err) => Err(HostError::new( - HostErrorType::CouldNotCreateFile, - Some(err), - dir_path.as_path(), - )), + Err(err) => { + error!("Could not make directory: {}", err); + Err(HostError::new( + HostErrorType::CouldNotCreateFile, + Some(err), + dir_path.as_path(), + )) + } } } @@ -246,7 +268,9 @@ impl Localhost { match entry { FsEntry::Directory(dir) => { // If file doesn't exist; return error + debug!("Removing directory {}", dir.abs_path.display()); if !dir.abs_path.as_path().exists() { + error!("Directory doesn't exist"); return Err(HostError::new( HostErrorType::NoSuchFileOrDirectory, None, @@ -258,18 +282,24 @@ impl Localhost { Ok(_) => { // Update dir self.files = self.scan_dir(self.wrkdir.as_path())?; + info!("Removed directory {}", dir.abs_path.display()); Ok(()) } - Err(err) => Err(HostError::new( - HostErrorType::DeleteFailed, - Some(err), - dir.abs_path.as_path(), - )), + Err(err) => { + error!("Could not remove directory: {}", err); + Err(HostError::new( + HostErrorType::DeleteFailed, + Some(err), + dir.abs_path.as_path(), + )) + } } } FsEntry::File(file) => { // If file doesn't exist; return error + debug!("Removing file {}", file.abs_path.display()); if !file.abs_path.as_path().exists() { + error!("File doesn't exist"); return Err(HostError::new( HostErrorType::NoSuchFileOrDirectory, None, @@ -281,13 +311,17 @@ impl Localhost { Ok(_) => { // Update dir self.files = self.scan_dir(self.wrkdir.as_path())?; + info!("Removed file {}", file.abs_path.display()); Ok(()) } - Err(err) => Err(HostError::new( - HostErrorType::DeleteFailed, - Some(err), - file.abs_path.as_path(), - )), + Err(err) => { + error!("Could not remove file: {}", err); + Err(HostError::new( + HostErrorType::DeleteFailed, + Some(err), + file.abs_path.as_path(), + )) + } } } } @@ -302,13 +336,26 @@ impl Localhost { Ok(_) => { // Scan dir self.files = self.scan_dir(self.wrkdir.as_path())?; + debug!( + "Moved file {} to {}", + entry.get_abs_path().display(), + dst_path.display() + ); Ok(()) } - Err(err) => Err(HostError::new( - HostErrorType::CouldNotCreateFile, - Some(err), - abs_path.as_path(), - )), + Err(err) => { + error!( + "Failed to move {} to {}: {}", + entry.get_abs_path().display(), + dst_path.display(), + err + ); + Err(HostError::new( + HostErrorType::CouldNotCreateFile, + Some(err), + abs_path.as_path(), + )) + } } } @@ -318,6 +365,11 @@ impl Localhost { pub fn copy(&mut self, entry: &FsEntry, dst: &Path) -> Result<(), HostError> { // Get absolute path of dest let dst: PathBuf = self.to_abs_path(dst); + info!( + "Copying file {} to {}", + entry.get_abs_path().display(), + dst.display() + ); // Match entry match entry { FsEntry::File(file) => { @@ -333,16 +385,19 @@ impl Localhost { }; // Copy entry path to dst path if let Err(err) = std::fs::copy(file.abs_path.as_path(), dst.as_path()) { + error!("Failed to copy file: {}", err); return Err(HostError::new( HostErrorType::CouldNotCreateFile, Some(err), file.abs_path.as_path(), )); } + info!("File copied"); } FsEntry::Directory(dir) => { // If destination path doesn't exist, create destination if !dst.exists() { + debug!("Directory {} doesn't exist; creating it", dst.display()); self.mkdir(dst.as_path())?; } // Scan dir @@ -386,15 +441,17 @@ impl Localhost { /// Stat file and create a FsEntry #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] pub fn stat(&self, path: &Path) -> Result { + info!("Stating file {}", path.display()); let path: PathBuf = self.to_abs_path(path); let attr: Metadata = match fs::metadata(path.as_path()) { Ok(metadata) => metadata, Err(err) => { + error!("Could not read file metadata: {}", err); return Err(HostError::new( HostErrorType::FileNotAccessible, Some(err), path.as_path(), - )) + )); } }; let file_name: String = String::from(path.file_name().unwrap().to_str().unwrap_or("")); @@ -454,14 +511,16 @@ impl Localhost { #[cfg(not(tarpaulin_include))] pub fn stat(&self, path: &Path) -> Result { let path: PathBuf = self.to_abs_path(path); + info!("Stating file {}", path.display()); let attr: Metadata = match fs::metadata(path.as_path()) { Ok(metadata) => metadata, Err(err) => { + error!("Could not read file metadata: {}", err); return Err(HostError::new( HostErrorType::FileNotAccessible, Some(err), path.as_path(), - )) + )); } }; let file_name: String = String::from(path.file_name().unwrap().to_str().unwrap_or("")); @@ -523,16 +582,23 @@ impl Localhost { let args: Vec<&str> = cmd.split(' ').collect(); let cmd: &str = args.first().unwrap(); let argv: &[&str] = &args[1..]; + info!("Executing command: {} {:?}", cmd, argv); match std::process::Command::new(cmd).args(argv).output() { Ok(output) => match std::str::from_utf8(&output.stdout) { - Ok(s) => Ok(s.to_string()), + Ok(s) => { + info!("Command output: {}", s); + Ok(s.to_string()) + } Err(_) => Ok(String::new()), }, - Err(err) => Err(HostError::new( - HostErrorType::ExecutionFailed, - Some(err), - self.wrkdir.as_path(), - )), + Err(err) => { + error!("Failed to run command: {}", err); + Err(HostError::new( + HostErrorType::ExecutionFailed, + Some(err), + self.wrkdir.as_path(), + )) + } } } @@ -548,19 +614,32 @@ impl Localhost { let mut mpex = metadata.permissions(); mpex.set_mode(self.mode_to_u32(pex)); match set_permissions(path.as_path(), mpex) { - Ok(_) => Ok(()), - Err(err) => Err(HostError::new( - HostErrorType::FileNotAccessible, - Some(err), - path.as_path(), - )), + Ok(_) => { + info!("Changed mode for {} to {:?}", path.display(), pex); + Ok(()) + } + Err(err) => { + error!("Could not change mode for file {}: {}", path.display(), err); + Err(HostError::new( + HostErrorType::FileNotAccessible, + Some(err), + path.as_path(), + )) + } } } - Err(err) => Err(HostError::new( - HostErrorType::FileNotAccessible, - Some(err), - path.as_path(), - )), + Err(err) => { + error!( + "Chmod failed; could not read metadata for file {}: {}", + path.display(), + err + ); + Err(HostError::new( + HostErrorType::FileNotAccessible, + Some(err), + path.as_path(), + )) + } } } @@ -569,7 +648,9 @@ impl Localhost { /// Open file for read pub fn open_file_read(&self, file: &Path) -> Result { let file: PathBuf = self.to_abs_path(file); + info!("Opening file {} for read", file.display()); if !self.file_exists(file.as_path()) { + error!("File doesn't exist!"); return Err(HostError::new( HostErrorType::NoSuchFileOrDirectory, None, @@ -583,11 +664,14 @@ impl Localhost { .open(file.as_path()) { Ok(f) => Ok(f), - Err(err) => Err(HostError::new( - HostErrorType::FileNotAccessible, - Some(err), - file.as_path(), - )), + Err(err) => { + error!("Could not open file for read: {}", err); + Err(HostError::new( + HostErrorType::FileNotAccessible, + Some(err), + file.as_path(), + )) + } } } @@ -596,6 +680,7 @@ impl Localhost { /// Open file for write pub fn open_file_write(&self, file: &Path) -> Result { let file: PathBuf = self.to_abs_path(file); + info!("Opening file {} for write", file.display()); match OpenOptions::new() .create(true) .write(true) @@ -603,18 +688,21 @@ impl Localhost { .open(file.as_path()) { Ok(f) => Ok(f), - Err(err) => match self.file_exists(file.as_path()) { - true => Err(HostError::new( - HostErrorType::ReadonlyFile, - Some(err), - file.as_path(), - )), - false => Err(HostError::new( - HostErrorType::FileNotAccessible, - Some(err), - file.as_path(), - )), - }, + Err(err) => { + error!("Failed to open file: {}", err); + match self.file_exists(file.as_path()) { + true => Err(HostError::new( + HostErrorType::ReadonlyFile, + Some(err), + file.as_path(), + )), + false => Err(HostError::new( + HostErrorType::FileNotAccessible, + Some(err), + file.as_path(), + )), + } + } } } @@ -629,13 +717,15 @@ impl Localhost { /// /// Get content of the current directory as a list of fs entry pub fn scan_dir(&self, dir: &Path) -> Result, HostError> { + info!("Reading directory {}", dir.display()); match std::fs::read_dir(dir) { Ok(e) => { let mut fs_entries: Vec = Vec::new(); for entry in e.flatten() { // NOTE: 0.4.1, don't fail if stat for one file fails - if let Ok(entry) = self.stat(entry.path().as_path()) { - fs_entries.push(entry); + match self.stat(entry.path().as_path()) { + Ok(entry) => fs_entries.push(entry), + Err(e) => error!("Failed to stat {}: {}", entry.path().display(), e), } } Ok(fs_entries) diff --git a/src/system/bookmarks_client.rs b/src/system/bookmarks_client.rs index 530aea8..fdff0c9 100644 --- a/src/system/bookmarks_client.rs +++ b/src/system/bookmarks_client.rs @@ -68,9 +68,11 @@ impl BookmarksClient { ) -> Result { // Create default hosts let default_hosts: UserHosts = Default::default(); + debug!("Setting up bookmarks client..."); // Make a key storage (windows / macos) #[cfg(any(target_os = "windows", target_os = "macos"))] let (key_storage, service_id): (Box, &str) = { + debug!("Setting up KeyStorage"); let username: String = whoami::username(); let storage: KeyringStorage = KeyringStorage::new(username.as_str()); // Check if keyring storage is supported @@ -79,8 +81,14 @@ impl BookmarksClient { #[cfg(test)] // NOTE: when running test, add -test let app_name: &str = "termscp-test"; match storage.is_supported() { - true => (Box::new(storage), app_name), - false => (Box::new(FileStorage::new(storage_path)), "bookmarks"), + true => { + debug!("Using KeyringStorage"); + (Box::new(storage), app_name) + } + false => { + warn!("KeyringStorage is not supported; using FileStorage"); + (Box::new(FileStorage::new(storage_path)), "bookmarks") + } } }; // Make a key storage (linux / unix) @@ -90,16 +98,22 @@ impl BookmarksClient { let app_name: &str = "bookmarks"; #[cfg(test)] // NOTE: when running test, add -test let app_name: &str = "bookmarks-test"; + debug!("Using FileStorage"); (Box::new(FileStorage::new(storage_path)), app_name) }; // Load key let key: String = match key_storage.get_key(service_id) { - Ok(k) => k, + Ok(k) => { + debug!("Key loaded with success"); + k + } Err(e) => match e { KeyStorageError::NoSuchKey => { // If no such key, generate key and set it into the storage let key: String = Self::generate_key(); + debug!("Key doesn't exist yet or could not be loaded; generated a new key"); if let Err(e) = key_storage.set_key(service_id, key.as_str()) { + error!("Failed to set new key into storage: {}", e); return Err(SerializerError::new_ex( SerializerErrorKind::IoError, format!("Could not write key to storage: {}", e), @@ -109,10 +123,11 @@ impl BookmarksClient { key } _ => { + error!("Failed to get key from storage: {}", e); return Err(SerializerError::new_ex( SerializerErrorKind::IoError, format!("Could not get key from storage: {}", e), - )) + )); } }, }; @@ -124,15 +139,19 @@ impl BookmarksClient { }; // If bookmark file doesn't exist, initialize it if !bookmarks_file.exists() { + info!("Bookmarks file doesn't exist yet; creating it..."); if let Err(err) = client.write_bookmarks() { + error!("Failed to create bookmarks file: {}", err); return Err(err); } } else { // Load bookmarks from file if let Err(err) = client.read_bookmarks() { + error!("Failed to load bookmarks: {}", err); return Err(err); } } + info!("Bookmarks client initialized"); // Load key Ok(client) } @@ -152,19 +171,29 @@ impl BookmarksClient { key: &str, ) -> Option<(String, u16, FileTransferProtocol, String, Option)> { let entry: &Bookmark = self.hosts.bookmarks.get(key)?; + debug!("Getting bookmark {}", key); Some(( entry.address.clone(), entry.port, match FileTransferProtocol::from_str(entry.protocol.as_str()) { Ok(proto) => proto, - Err(_) => FileTransferProtocol::Sftp, // Default + Err(err) => { + error!( + "Found invalid protocol in bookmarks: {}; defaulting to SFTP", + err + ); + FileTransferProtocol::Sftp // Default + } }, entry.username.clone(), match &entry.password { // Decrypted password if Some; if decryption fails return None Some(pwd) => match self.decrypt_str(pwd.as_str()) { Ok(decrypted_pwd) => Some(decrypted_pwd), - Err(_) => None, + Err(err) => { + error!("Failed to decrypt password for bookmark: {}", err); + None + } }, None => None, }, @@ -184,9 +213,11 @@ impl BookmarksClient { password: Option, ) { if name.is_empty() { + error!("Fatal error; bookmark name is empty"); panic!("Bookmark name can't be empty"); } // Make bookmark + info!("Added bookmark {} with address {}", name, addr); let host: Bookmark = self.make_bookmark(addr, port, protocol, username, password); self.hosts.bookmarks.insert(name, host); } @@ -196,6 +227,7 @@ impl BookmarksClient { /// Delete entry from bookmarks pub fn del_bookmark(&mut self, name: &str) { let _ = self.hosts.bookmarks.remove(name); + info!("Removed bookmark {}", name); } /// ### iter_recents /// @@ -209,13 +241,20 @@ impl BookmarksClient { /// Get recent associated to key pub fn get_recent(&self, key: &str) -> Option<(String, u16, FileTransferProtocol, String)> { // NOTE: password is not decrypted; recents will never have password + info!("Getting bookmark {}", key); let entry: &Bookmark = self.hosts.recents.get(key)?; Some(( entry.address.clone(), entry.port, match FileTransferProtocol::from_str(entry.protocol.as_str()) { Ok(proto) => proto, - Err(_) => FileTransferProtocol::Sftp, // Default + Err(err) => { + error!( + "Found invalid protocol in bookmarks: {}; defaulting to SFTP", + err + ); + FileTransferProtocol::Sftp // Default + } }, entry.username.clone(), )) @@ -236,6 +275,7 @@ impl BookmarksClient { // Check if duplicated for recent_host in self.hosts.recents.values() { if *recent_host == host { + debug!("Discarding recent since duplicated ({})", host.address); // Don't save duplicates return; } @@ -252,6 +292,7 @@ impl BookmarksClient { // Delete keys starting from the last one for key in keys.iter() { let _ = self.hosts.recents.remove(key); + debug!("Removed recent bookmark {}", key); // If length is < self.recents_size; break if self.hosts.recents.len() < self.recents_size { break; @@ -259,6 +300,7 @@ impl BookmarksClient { } } let name: String = fmt_time(SystemTime::now(), "ISO%Y%m%dT%H%M%S"); + info!("Saved recent host {} ({})", name, host.address); self.hosts.recents.insert(name, host); } @@ -267,6 +309,7 @@ impl BookmarksClient { /// Delete entry from recents pub fn del_recent(&mut self, name: &str) { let _ = self.hosts.recents.remove(name); + info!("Removed recent host {}", name); } /// ### write_bookmarks @@ -274,6 +317,7 @@ impl BookmarksClient { /// Write bookmarks to file pub fn write_bookmarks(&self) -> Result<(), SerializerError> { // Open file + debug!("Writing bookmarks"); match OpenOptions::new() .create(true) .write(true) @@ -284,10 +328,13 @@ impl BookmarksClient { let serializer: BookmarkSerializer = BookmarkSerializer {}; serializer.serialize(Box::new(writer), &self.hosts) } - Err(err) => Err(SerializerError::new_ex( - SerializerErrorKind::IoError, - err.to_string(), - )), + Err(err) => { + error!("Failed to write bookmarks: {}", err); + Err(SerializerError::new_ex( + SerializerErrorKind::IoError, + err.to_string(), + )) + } } } @@ -296,6 +343,7 @@ impl BookmarksClient { /// Read bookmarks from file fn read_bookmarks(&mut self) -> Result<(), SerializerError> { // Open bookmarks file for read + debug!("Reading bookmarks"); match OpenOptions::new() .read(true) .open(self.bookmarks_file.as_path()) @@ -311,10 +359,13 @@ impl BookmarksClient { Err(err) => Err(err), } } - Err(err) => Err(SerializerError::new_ex( - SerializerErrorKind::IoError, - err.to_string(), - )), + Err(err) => { + error!("Failed to read bookmarks: {}", err); + Err(SerializerError::new_ex( + SerializerErrorKind::IoError, + err.to_string(), + )) + } } } diff --git a/src/system/config_client.rs b/src/system/config_client.rs index d85decf..b0919b8 100644 --- a/src/system/config_client.rs +++ b/src/system/config_client.rs @@ -58,6 +58,11 @@ impl ConfigClient { pub fn new(config_path: &Path, ssh_key_dir: &Path) -> Result { // Initialize a default configuration let default_config: UserConfig = UserConfig::default(); + info!( + "Setting up config client with config path {} and SSH key directory {}", + config_path.display(), + ssh_key_dir.display() + ); // Create client let mut client: ConfigClient = ConfigClient { config: default_config, @@ -67,6 +72,7 @@ impl ConfigClient { // If ssh key directory doesn't exist, create it if !ssh_key_dir.exists() { if let Err(err) = create_dir(ssh_key_dir) { + error!("Failed to create SSH key dir: {}", err); return Err(SerializerError::new_ex( SerializerErrorKind::IoError, format!( @@ -76,17 +82,22 @@ impl ConfigClient { ), )); } + debug!("Created SSH key directory"); } // If Config file doesn't exist, create it if !config_path.exists() { if let Err(err) = client.write_config() { + error!("Couldn't create configuration file: {}", err); return Err(err); } + debug!("Config file didn't exist; created file"); } else { // otherwise Load configuration from file if let Err(err) = client.read_config() { + error!("Couldn't read configuration file: {}", err); return Err(err); } + debug!("Read configuration file"); } Ok(client) } @@ -230,12 +241,18 @@ impl ConfigClient { p.push(format!("{}.key", host_name)); p }; + info!( + "Writing SSH file to {} for host {}", + ssh_key_path.display(), + host_name + ); // Write key to file let mut f: File = match File::create(ssh_key_path.as_path()) { Ok(f) => f, Err(err) => return Self::make_io_err(err), }; if let Err(err) = f.write_all(ssh_key.as_bytes()) { + error!("Failed to write SSH key to file: {}", err); return Self::make_io_err(err); } // Add host to keys @@ -251,6 +268,7 @@ impl ConfigClient { /// and also commits changes to configuration, to prevent incoerent data pub fn del_ssh_key(&mut self, host: &str, username: &str) -> Result<(), SerializerError> { // Remove key from configuration and get key path + info!("Removing key for {}@{}", host, username); let key_path: PathBuf = match self .config .remote @@ -262,6 +280,7 @@ impl ConfigClient { }; // Remove file if let Err(err) = remove_file(key_path.as_path()) { + error!("Failed to remove key file {}: {}", key_path.display(), err); return Self::make_io_err(err); } // Commit changes to configuration @@ -310,10 +329,13 @@ impl ConfigClient { let serializer: ConfigSerializer = ConfigSerializer {}; serializer.serialize(Box::new(writer), &self.config) } - Err(err) => Err(SerializerError::new_ex( - SerializerErrorKind::IoError, - err.to_string(), - )), + Err(err) => { + error!("Failed to write configuration file: {}", err); + Err(SerializerError::new_ex( + SerializerErrorKind::IoError, + err.to_string(), + )) + } } } @@ -337,10 +359,13 @@ impl ConfigClient { Err(err) => Err(err), } } - Err(err) => Err(SerializerError::new_ex( - SerializerErrorKind::IoError, - err.to_string(), - )), + Err(err) => { + error!("Failed to read configuration: {}", err); + Err(SerializerError::new_ex( + SerializerErrorKind::IoError, + err.to_string(), + )) + } } } diff --git a/src/system/sshkey_storage.rs b/src/system/sshkey_storage.rs index fe5b4a1..ea6cfb4 100644 --- a/src/system/sshkey_storage.rs +++ b/src/system/sshkey_storage.rs @@ -42,6 +42,7 @@ impl SshKeyStorage { pub fn storage_from_config(cfg_client: &ConfigClient) -> Self { let mut hosts: HashMap = HashMap::with_capacity(cfg_client.iter_ssh_keys().count()); + debug!("Setting up SSH key storage"); // Iterate over keys for key in cfg_client.iter_ssh_keys() { match cfg_client.get_ssh_key(key) { @@ -52,8 +53,12 @@ impl SshKeyStorage { } None => continue, }, - Err(_) => continue, + Err(err) => { + error!("Failed to get SSH key for {}: {}", key, err); + continue; + } } + info!("Got SSH key for {}", key); } // Return storage SshKeyStorage { hosts }