diff --git a/src/inspect.rs b/src/inspect.rs index 1e22269..cd1b3d5 100644 --- a/src/inspect.rs +++ b/src/inspect.rs @@ -10,7 +10,7 @@ use anyhow::{Context, Result}; use console::style; use dialoguer::{Confirm, theme::ColorfulTheme}; use sanitize_filename::sanitize; -use std::collections::HashMap; +use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use std::sync::Arc; use tokio::fs; @@ -41,7 +41,7 @@ pub async fn run( realms_to_inspect.to_vec() }; - let all_secrets = Arc::new(Mutex::new(HashMap::new())); + let all_secrets = Arc::new(Mutex::new(BTreeMap::new())); let prompt_mutex = Arc::new(Mutex::new(())); let mut set = tokio::task::JoinSet::new(); @@ -83,10 +83,8 @@ pub async fn run( if !secrets_lock.is_empty() { let env_path = workspace_dir.join(".secrets"); let mut env_content = String::new(); - let mut keys: Vec<&String> = secrets_lock.keys().collect(); - keys.sort(); - for key in keys { - env_content.push_str(&format!("{}={}\n", key, secrets_lock[key])); + for (key, value) in secrets_lock.iter() { + env_content.push_str(&format!("{}={}\n", key, value)); } let mut existing_env = String::new(); @@ -187,7 +185,7 @@ async fn inspect_resources( client: &KeycloakClient, realm_name: &str, target_dir: Arc, - all_secrets: Arc>>, + all_secrets: Arc>>, yes: bool, prompt_mutex: Arc>, ) -> Result<()> @@ -223,7 +221,7 @@ where set.spawn(async move { let filename = format!("{}.yaml", sanitize(res.get_filename())); let path = target_dir.join(filename); - let mut local_secrets = HashMap::new(); + let mut local_secrets = BTreeMap::new(); let prefix = format!("realm_{}_{}", realm_name, T::SECRET_PREFIX); let yaml = to_sorted_yaml_with_secrets(&res, &prefix, &mut local_secrets).context( format!("Failed to serialize {} {}", T::LABEL, res.get_name()), @@ -257,7 +255,7 @@ async fn inspect_realm( client: &KeycloakClient, realm_name: &str, workspace_dir: PathBuf, - all_secrets: Arc>>, + all_secrets: Arc>>, yes: bool, prompt_mutex: Arc>, ) -> Result<()> { @@ -282,7 +280,7 @@ async fn inspect_realm( let prompt_mutex = Arc::clone(&prompt_mutex); set.spawn(async move { let realm = client.get_realm().await.context("Failed to fetch realm")?; - let mut local_secrets = HashMap::new(); + let mut local_secrets = BTreeMap::new(); let realm_prefix = format!("realm_{}", realm_name); let realm_yaml = to_sorted_yaml_with_secrets(&realm, &realm_prefix, &mut local_secrets) .context("Failed to serialize realm")?; @@ -402,7 +400,7 @@ fn spawn_inspect( client: &KeycloakClient, realm_name: &str, workspace_dir: &Arc, - all_secrets: &Arc>>, + all_secrets: &Arc>>, yes: bool, prompt_mutex: &Arc>, ) where diff --git a/src/utils.rs b/src/utils.rs index 50200ca..b1c2751 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -85,7 +85,7 @@ pub fn recursive_sort(value: &mut serde_json::Value) { pub fn to_sorted_yaml_with_secrets( value: &T, prefix: &str, - secrets: &mut std::collections::HashMap, + secrets: &mut std::collections::BTreeMap, ) -> anyhow::Result { let mut json_value = serde_json::to_value(value).context("Failed to serialize to JSON value")?; @@ -309,7 +309,7 @@ mod tests { #[test] fn test_to_sorted_yaml_with_secrets() { - let mut secrets = std::collections::HashMap::new(); + let mut secrets = std::collections::BTreeMap::new(); let val = serde_json::json!({ "clientId": "myclient", "secret": "very-secret", diff --git a/src/utils/secrets/mod.rs b/src/utils/secrets/mod.rs index 998212f..13da22a 100644 --- a/src/utils/secrets/mod.rs +++ b/src/utils/secrets/mod.rs @@ -129,7 +129,11 @@ fn format_env_var_name(prefix: &str, key: &str) -> String { } /// Recursively extract secrets and replace them with ${ENV_VAR} -pub fn extract_secrets(value: &mut Value, prefix: &str, secrets: &mut HashMap) { +pub fn extract_secrets( + value: &mut Value, + prefix: &str, + secrets: &mut std::collections::BTreeMap, +) { match value { Value::Object(map) => { let id = get_object_identifier(map); @@ -276,7 +280,7 @@ mod tests { "clientSecret": "my_super_secret", "storeToken": "true" }); - let mut secrets = HashMap::new(); + let mut secrets = std::collections::BTreeMap::new(); extract_secrets(&mut val, "client", &mut secrets); assert_eq!( @@ -290,7 +294,7 @@ mod tests { ); let mut val2 = json!({"clientSecret": "secret_value_2"}); - let mut secrets2 = HashMap::new(); + let mut secrets2 = std::collections::BTreeMap::new(); extract_secrets(&mut val2, "", &mut secrets2); assert_eq!(val2["clientSecret"], "${KEYCLOAK_CLIENTSECRET}"); assert_eq!( @@ -299,7 +303,7 @@ mod tests { ); let mut val3 = json!({"clientSecret-special": "secret_value_3"}); - let mut secrets3 = HashMap::new(); + let mut secrets3 = std::collections::BTreeMap::new(); extract_secrets(&mut val3, "prefix", &mut secrets3); assert_eq!( val3["clientSecret-special"], diff --git a/tests_tarpaulin/mod.rs b/tests_tarpaulin/mod.rs index 9bdad4c..c6ec8ca 100644 --- a/tests_tarpaulin/mod.rs +++ b/tests_tarpaulin/mod.rs @@ -120,7 +120,7 @@ fn format_env_var_name(prefix: &str, key: &str) -> String { } /// Recursively extract secrets and replace them with ${ENV_VAR} -pub fn extract_secrets(value: &mut Value, prefix: &str, secrets: &mut HashMap) { +pub fn extract_secrets(value: &mut Value, prefix: &str, secrets: &mut std::collections::BTreeMap) { match value { Value::Object(map) => { let mut keys_to_update = Vec::new(); @@ -291,7 +291,7 @@ mod tests { "clientSecret": "my_super_secret", "storeToken": "true" }); - let mut secrets = HashMap::new(); + let mut secrets = std::collections::BTreeMap::new(); extract_secrets(&mut val, "client", &mut secrets); assert_eq!( @@ -305,13 +305,13 @@ mod tests { ); let mut val2 = json!({"clientSecret": "secret_value_2"}); - let mut secrets2 = HashMap::new(); + let mut secrets2 = std::collections::BTreeMap::new(); extract_secrets(&mut val2, "", &mut secrets2); assert_eq!(val2["clientSecret"], "${KEYCLOAK_CLIENTSECRET}"); assert_eq!(secrets2.get("KEYCLOAK_CLIENTSECRET").unwrap(), "secret_value_2"); let mut val3 = json!({"clientSecret-special": "secret_value_3"}); - let mut secrets3 = HashMap::new(); + let mut secrets3 = std::collections::BTreeMap::new(); extract_secrets(&mut val3, "prefix", &mut secrets3); assert_eq!(val3["clientSecret-special"], "${KEYCLOAK_PREFIX_CLIENTSECRET_SPECIAL}"); assert_eq!(secrets3.get("KEYCLOAK_PREFIX_CLIENTSECRET_SPECIAL").unwrap(), "secret_value_3");