diff options
| author | rtkay123 <dev@kanjala.com> | 2026-04-02 14:27:45 +0200 |
|---|---|---|
| committer | rtkay123 <dev@kanjala.com> | 2026-04-02 14:27:45 +0200 |
| commit | 8bc645b006080b860e40c0ff55b485125dc6157d (patch) | |
| tree | 8344e498fa50dc237f0f1fdbde2e38305da2fdfe /lib/warden-core/src/config/cli/database.rs | |
| parent | daeb5311840680599a0ce6e49d181b9289010f68 (diff) | |
| download | warden-master.tar.bz2 warden-master.zip | |
Diffstat (limited to 'lib/warden-core/src/config/cli/database.rs')
| -rw-r--r-- | lib/warden-core/src/config/cli/database.rs | 192 |
1 files changed, 148 insertions, 44 deletions
diff --git a/lib/warden-core/src/config/cli/database.rs b/lib/warden-core/src/config/cli/database.rs index 70bf600..90032a2 100644 --- a/lib/warden-core/src/config/cli/database.rs +++ b/lib/warden-core/src/config/cli/database.rs @@ -22,7 +22,7 @@ pub struct Database { pub database_password: Option<String>, /// Database host - #[arg(long, env = "DB_HOST", default_value = "localhost")] + #[arg(long, env = "DB_HOST")] #[serde(rename = "host")] pub database_host: Option<String>, @@ -37,7 +37,7 @@ pub struct Database { pub database_name: Option<String>, /// Database pool size - #[arg(long, env = "DATABASE_POOL_SIZE", default_value = "10")] + #[arg(long, env = "DATABASE_POOL_SIZE")] #[serde(rename = "pool-size")] pub database_pool_size: Option<u32>, } @@ -58,56 +58,67 @@ impl Default for Database { impl Database { pub fn merge(cli: &Self, file: &Self) -> Result<Self, WardenError> { - let url = cli.database_url.clone().or(file.database_url.clone()); - let pool_size = cli .database_pool_size .or(file.database_pool_size) .unwrap_or(10); - let final_url = match url { - Some(u) => u, - None => { - let host = cli - .database_host - .clone() - .or(file.database_host.clone()) - .unwrap_or_else(|| "localhost".to_string()); - - let mut u = Url::parse(&format!("postgresql://{}", host))?; - - let user = cli - .database_username - .as_ref() - .or(file.database_username.as_ref()); - let pass = cli - .database_password - .as_ref() - .or(file.database_password.as_ref()); - let port = cli.database_port.or(file.database_port); - let name = cli.database_name.as_ref().or(file.database_name.as_ref()); - - if let Some(user) = user { - u.set_username(user).ok(); - } - if let Some(pass) = pass { - u.set_password(Some(pass)).ok(); - } - if let Some(port) = port { - u.set_port(Some(port)).ok(); - } - if let Some(name) = name { - u.set_path(name); - } - - u - } - }; + if let Some(url) = cli + .database_url + .clone() + .or_else(|| file.database_url.clone()) + { + return Ok(Self { + database_url: Some(url), + database_pool_size: Some(pool_size), + ..Default::default() + }); + } + + let host = cli + .database_host + .as_deref() + .or(file.database_host.as_deref()) + .unwrap_or("localhost"); + + let mut u = Url::parse(&format!("postgresql://{}", host))?; + + let user = cli + .database_username + .as_deref() + .or(file.database_username.as_deref()); + let pass = cli + .database_password + .as_deref() + .or(file.database_password.as_deref()); + let port = cli.database_port.or(file.database_port); + let name = cli + .database_name + .as_deref() + .or(file.database_name.as_deref()); + + if let Some(user) = user { + u.set_username(user).ok(); + } + if let Some(pass) = pass { + u.set_password(Some(pass)).ok(); + } + if let Some(port) = port { + u.set_port(Some(port)).ok(); + } + if let Some(name) = name { + u.set_path(name); + } Ok(Self { - database_url: Some(final_url), + database_url: Some(u), database_pool_size: Some(pool_size), - ..cli.clone() + // Carry over the other fields for record-keeping + database_host: Some(host.to_string()), + database_username: user.map(String::from), + database_password: pass.map(String::from), + database_port: port, + database_name: name.map(String::from), }) } @@ -134,3 +145,96 @@ impl Database { Ok(url) } } + +#[cfg(test)] +mod tests { + use super::*; + use url::Url; + + /// Helper to create a "naked" Database struct with all Nones + /// Useful for testing merge logic without Default values interfering + fn empty_db() -> Database { + Database { + database_url: None, + database_username: None, + database_password: None, + database_host: None, + database_port: None, + database_name: None, + database_pool_size: None, + } + } + + #[test] + fn test_get_url_from_components() { + let db = Database { + database_host: Some("127.0.0.1".to_string()), + database_username: Some("admin".to_string()), + database_password: Some("secret".to_string()), + database_port: Some(5432), + database_name: Some("testdb".to_string()), + ..empty_db() + }; + + let url = db.get_url().expect("Should parse URL"); + // Note: get_url uses "postgres://" scheme + assert_eq!( + url.as_str(), + "postgres://admin:secret@127.0.0.1:5432/testdb" + ); + } + + #[test] + fn test_merge_cli_overrides_file() { + let mut file_config = empty_db(); + file_config.database_host = Some("file-host".to_string()); + file_config.database_port = Some(1111); + + let mut cli_config = empty_db(); + cli_config.database_host = Some("cli-host".to_string()); + // database_port is None in CLI + + let merged = Database::merge(&cli_config, &file_config).expect("Merge failed"); + + let url = merged.database_url.unwrap(); + // CLI host should win + assert_eq!(url.host_str(), Some("cli-host")); + // File port should win because CLI was None + assert_eq!(url.port(), Some(1111)); + } + + #[test] + fn test_merge_url_override_wins_all() { + let mut file_config = empty_db(); + file_config.database_host = Some("local-host".to_string()); + + let mut cli_config = empty_db(); + let expected_url = "postgresql://remote-host:9999/prod"; + cli_config.database_url = Some(Url::parse(expected_url).unwrap()); + + let merged = Database::merge(&cli_config, &file_config).expect("Merge failed"); + + assert_eq!(merged.database_url.unwrap().as_str(), expected_url); + } + + #[test] + fn test_merge_pool_size_logic() { + let mut file_config = empty_db(); + file_config.database_pool_size = Some(50); + + let cli_config = empty_db(); // pool_size is None + + let merged = Database::merge(&cli_config, &file_config).expect("Merge failed"); + + // Should take file value if CLI is None + assert_eq!(merged.database_pool_size, Some(50)); + } + + #[test] + fn test_default_trait_implementation() { + let db = Database::default(); + assert_eq!(db.database_port, Some(5432)); + assert_eq!(db.database_username, Some("postgres".to_string())); + assert_eq!(db.database_host, Some("localhost".to_string())); + } +} |
