diff --git a/Cargo.lock b/Cargo.lock index 9ccfcda..0ba35ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -860,6 +860,7 @@ dependencies = [ "clap", "futures", "openssl", + "paris", "tokio", ] @@ -1063,6 +1064,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "paris" +version = "1.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fecab3723493c7851f292cb060f3ee1c42f19b8d749345d0d7eaf3fd19aa62d" + [[package]] name = "parking" version = "2.2.0" diff --git a/Cargo.toml b/Cargo.toml index b620648..567b504 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ azure_identity = "0.17.0" azure_security_keyvault = "0.17.0" clap = { version = "4.4.8", features = ["derive"] } futures = "0.3.29" +paris = { version = "1.5.15", features = ["macros"] } tokio = {version = "1.34.0", features = ["full"]} [target.'cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "arm", target_arch = "aarch64")))'.dependencies] diff --git a/src/main.rs b/src/main.rs index 55c3a1d..af80d3e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ -use anyhow::{Context, Result}; +use anyhow::Result; use azure_identity::DefaultAzureCredential; use azure_security_keyvault::prelude::KeyVaultGetSecretsResponse; use azure_security_keyvault::KeyvaultClient; use clap::Parser; use futures::stream::StreamExt; +use paris::{error, Logger}; use std::fs::File; use std::io::Write; use std::sync::Arc; @@ -34,7 +35,13 @@ async fn fetch_secrets_from_key_vault( let mut secret_pages = client.secret_client().list_secrets().into_stream(); while let Some(page) = secret_pages.next().await { - let page = page.context("Failed to fetch secrets page")?; + let page = match page { + Ok(p) => p, + Err(err) => { + error!("Failed to fetch secrets page: {}", err); + return Err(err.into()); // Convert the error into anyhow::Error + } + }; secret_values .extend(fetch_secrets_from_page(&client.secret_client(), &page, filter).await?); } @@ -75,6 +82,8 @@ async fn fetch_secrets_from_page( for handle in handles { if let Ok(result) = handle.await { secrets.push(result); + } else { + error!("Error occurred while fetching a secret."); } } @@ -97,20 +106,30 @@ async fn fetch_and_send_secret( (secret_id, bundle.value) } Err(err) => { - eprintln!("Error fetching secret: {}", err); + error!("Error fetching secret: {}", err); (secret_id, String::new()) } } } fn create_env_file(secrets: Vec<(String, String)>, output_file: &str) -> Result<()> { - let mut file = File::create(output_file).context("Failed to create output file")?; + let mut file = match File::create(output_file) { + Ok(f) => f, + Err(err) => { + error!("Failed to create output file: {}", err); + return Err(err.into()); + } + }; + for (key, value) in secrets { if let Some(secret_name) = key.split('/').last() { - writeln!(file, "{}={}", secret_name, value) - .with_context(|| format!("Failed to write to output file: {}", output_file))?; + if let Err(err) = writeln!(file, "{}={}", secret_name, value) { + error!("Failed to write to output file: {}: {}", output_file, err); + return Err(err.into()); + } } } + Ok(()) } @@ -147,18 +166,35 @@ mod tests { #[tokio::main] async fn main() -> Result<()> { let opts: Opts = Opts::parse(); + let mut log = Logger::new(); let vault_url = format!("https://{}.vault.azure.net", opts.vault_name); - println!("Fetching secrets from Key Vault: {}", opts.vault_name); + log.loading("Detecting credentials."); let credential = DefaultAzureCredential::default(); - let client = KeyvaultClient::new(&vault_url, std::sync::Arc::new(credential)) - .context("Failed to create KeyvaultClient")?; + let client = match KeyvaultClient::new(&vault_url, std::sync::Arc::new(credential)) { + Ok(c) => c, + Err(err) => { + error!("Failed to create KeyvaultClient: {}", err); + return Err(err.into()); + } + }; + log.success("Detected credentials."); + log.loading(format!( + "Fetching secrets from Key Vault: {}", + opts.vault_name + )); let secrets = fetch_secrets_from_key_vault(&client, opts.filter.as_deref()).await?; - println!("Creating output file: {}", opts.output); - create_env_file(secrets, &opts.output)?; + log.success(format!( + "Fetched secrets from Key Vault: {}", + opts.vault_name + )); - println!("Process completed successfully!"); + log.loading(format!("Creating output file: {}", opts.output)); + create_env_file(secrets, &opts.output)?; + log.success(format!("Created output file: {}", opts.output)); + + log.success("Done."); Ok(()) }