diff --git a/src/app/app_tests.rs b/src/app/app_tests.rs index 6b98a5e..8975ea0 100644 --- a/src/app/app_tests.rs +++ b/src/app/app_tests.rs @@ -5,7 +5,7 @@ mod tests { use tokio::sync::mpsc; use crate::app::context_clues::{build_context_clue_string, SERVARR_CONTEXT_CLUES}; - use crate::app::{App, Data, ServarrConfig, DEFAULT_ROUTE}; + use crate::app::{App, AppConfig, Data, ServarrConfig, DEFAULT_ROUTE}; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData}; use crate::models::{HorizontallyScrollableText, TabRoute}; @@ -255,13 +255,21 @@ mod tests { } #[test] - fn test_servarr_config_default() { - let radarr_config = ServarrConfig::default(); + fn test_app_config_default() { + let app_config = AppConfig::default(); - assert_eq!(radarr_config.host, Some("localhost".to_string())); - assert_eq!(radarr_config.port, None); - assert_eq!(radarr_config.uri, None); - assert!(radarr_config.api_token.is_empty()); - assert_eq!(radarr_config.ssl_cert_path, None); + assert!(app_config.radarr.is_none()); + assert!(app_config.sonarr.is_none()); + } + + #[test] + fn test_servarr_config_default() { + let servarr_config = ServarrConfig::default(); + + assert_eq!(servarr_config.host, Some("localhost".to_string())); + assert_eq!(servarr_config.port, None); + assert_eq!(servarr_config.uri, None); + assert!(servarr_config.api_token.is_empty()); + assert_eq!(servarr_config.ssl_cert_path, None); } } diff --git a/src/app/mod.rs b/src/app/mod.rs index ba95fcc..f401e1d 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -8,6 +8,7 @@ use tokio::sync::mpsc::Sender; use tokio_util::sync::CancellationToken; use crate::app::context_clues::{build_context_clue_string, SERVARR_CONTEXT_CLUES}; +use crate::cli::Command; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData}; use crate::models::{HorizontallyScrollableText, Route, TabRoute, TabState}; @@ -178,20 +179,45 @@ pub struct Data<'a> { pub sonarr_data: SonarrData, } -#[derive(Debug, Deserialize, Serialize, Default)] +#[derive(Debug, Deserialize, Serialize, Default, Clone)] pub struct AppConfig { - pub radarr: ServarrConfig, - pub sonarr: ServarrConfig, + pub radarr: Option, + pub sonarr: Option, } impl AppConfig { pub fn validate(&self) { - self.radarr.validate(); + if let Some(radarr_config) = &self.radarr { + radarr_config.validate(); + } + + if let Some(sonarr_config) = &self.sonarr { + sonarr_config.validate(); + } + } + + pub fn verify_config_present_for_cli(&self, command: &Command) { + let msg = |servarr: &str| { + log_and_print_error(format!( + "{} configuration missing; Unable to run any {} commands.", + servarr, servarr + )) + }; + match command { + Command::Radarr(_) if self.radarr.is_none() => { + msg("Radarr"); + process::exit(1); + } + Command::Sonarr(_) if self.sonarr.is_none() => { + msg("Sonarr"); + process::exit(1); + } + _ => (), + } } } -#[derive(Debug, Deserialize, Serialize)] -#[cfg_attr(test, derive(Clone))] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct ServarrConfig { pub host: Option, pub port: Option, diff --git a/src/main.rs b/src/main.rs index b45d3e8..b6ece85 100644 --- a/src/main.rs +++ b/src/main.rs @@ -106,13 +106,14 @@ async fn main() -> Result<()> { let app = Arc::new(Mutex::new(App::new( sync_network_tx, - config, + config.clone(), cancellation_token.clone(), ))); match args.command { Some(command) => match command { Command::Radarr(_) | Command::Sonarr(_) => { + config.verify_config_present_for_cli(&command); app.lock().await.cli_mode = true; let app_nw = Arc::clone(&app); let mut network = Network::new(&app_nw, cancellation_token, reqwest_client); @@ -249,9 +250,18 @@ fn build_network_client(config: &AppConfig) -> Client { .http2_keep_alive_interval(Duration::from_secs(5)) .tcp_keepalive(Duration::from_secs(5)); - if let Some(ref cert_path) = config.radarr.ssl_cert_path { - let cert = create_cert(cert_path, "Radarr"); - client_builder = client_builder.add_root_certificate(cert); + if let Some(radarr_config) = &config.radarr { + if let Some(ref cert_path) = &radarr_config.ssl_cert_path { + let cert = create_cert(cert_path, "Radarr"); + client_builder = client_builder.add_root_certificate(cert); + } + } + + if let Some(sonarr_config) = &config.sonarr { + if let Some(ref cert_path) = &sonarr_config.ssl_cert_path { + let cert = create_cert(cert_path, "Sonarr"); + client_builder = client_builder.add_root_certificate(cert); + } } match client_builder.build() { diff --git a/src/network/mod.rs b/src/network/mod.rs index 0967a46..92b4f98 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -216,8 +216,14 @@ impl<'a, 'b> Network<'a, 'b> { }, default_port, ) = match network_event.into() { - NetworkEvent::Radarr(_) => (&app.config.radarr, 7878), - NetworkEvent::Sonarr(_) => (&app.config.sonarr, 8989), + NetworkEvent::Radarr(_) => ( + &app.config.radarr.as_ref().expect("Radarr config undefined"), + 7878, + ), + NetworkEvent::Sonarr(_) => ( + &app.config.sonarr.as_ref().expect("Sonarr config undefined"), + 8989, + ), }; let mut uri = if let Some(servarr_uri) = uri { format!("{servarr_uri}/api/v3{resource}") diff --git a/src/network/network_tests.rs b/src/network/network_tests.rs index 109ac71..1613ca0 100644 --- a/src/network/network_tests.rs +++ b/src/network/network_tests.rs @@ -43,7 +43,7 @@ mod tests { ssl_cert_path: None, ..ServarrConfig::default() }; - app.config.radarr = radarr_config; + app.config.radarr = Some(radarr_config); let app_arc = Arc::new(Mutex::new(app)); let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); @@ -397,6 +397,40 @@ mod tests { async_server.assert_async().await; } + #[tokio::test] + #[should_panic(expected = "Radarr config undefined")] + async fn test_request_props_from_requires_radarr_config_to_be_present_for_radarr_events() { + let app_arc = Arc::new(Mutex::new(App::default())); + let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + network + .request_props_from( + RadarrEvent::GetMovies, + RequestMethod::Get, + None::<()>, + None, + None, + ) + .await; + } + + #[tokio::test] + #[should_panic(expected = "Sonarr config undefined")] + async fn test_request_props_from_requires_sonarr_config_to_be_present_for_sonarr_events() { + let app_arc = Arc::new(Mutex::new(App::default())); + let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + network + .request_props_from( + SonarrEvent::ListSeries, + RequestMethod::Get, + None::<()>, + None, + None, + ) + .await; + } + #[rstest] #[case(RadarrEvent::GetMovies, 7878)] #[case(SonarrEvent::ListSeries, 8989)] @@ -408,6 +442,10 @@ mod tests { let app_arc = Arc::new(Mutex::new(App::default())); let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); let resource = network_event.resource(); + app_arc.lock().await.config = AppConfig { + radarr: Some(ServarrConfig::default()), + sonarr: Some(ServarrConfig::default()), + }; let request_props = network .request_props_from(network_event, RequestMethod::Get, None::<()>, None, None) @@ -440,8 +478,8 @@ mod tests { }; { let mut app = app_arc.lock().await; - app.config.radarr = servarr_config.clone(); - app.config.sonarr = servarr_config; + app.config.radarr = Some(servarr_config.clone()); + app.config.sonarr = Some(servarr_config); } let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); @@ -474,8 +512,8 @@ mod tests { }; { let mut app = app_arc.lock().await; - app.config.radarr = servarr_config.clone(); - app.config.sonarr = servarr_config; + app.config.radarr = Some(servarr_config.clone()); + app.config.sonarr = Some(servarr_config); } let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); @@ -503,6 +541,10 @@ mod tests { let app_arc = Arc::new(Mutex::new(App::default())); let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); let resource = network_event.resource(); + app_arc.lock().await.config = AppConfig { + radarr: Some(ServarrConfig::default()), + sonarr: Some(ServarrConfig::default()), + }; let request_props = network .request_props_from( @@ -541,8 +583,8 @@ mod tests { }; { let mut app = app_arc.lock().await; - app.config.radarr = servarr_config.clone(); - app.config.sonarr = servarr_config; + app.config.radarr = Some(servarr_config.clone()); + app.config.sonarr = Some(servarr_config); } let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); @@ -581,8 +623,8 @@ mod tests { }; { let mut app = app_arc.lock().await; - app.config.radarr = servarr_config.clone(); - app.config.sonarr = servarr_config; + app.config.radarr = Some(servarr_config.clone()); + app.config.sonarr = Some(servarr_config); } let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); @@ -701,8 +743,8 @@ pub(in crate::network) mod test_utils { }; match network_event.into() { - NetworkEvent::Radarr(_) => app.config.radarr = servarr_config, - NetworkEvent::Sonarr(_) => app.config.sonarr = servarr_config, + NetworkEvent::Radarr(_) => app.config.radarr = Some(servarr_config), + NetworkEvent::Sonarr(_) => app.config.sonarr = Some(servarr_config), } let app_arc = Arc::new(Mutex::new(app)); diff --git a/src/network/radarr_network_tests.rs b/src/network/radarr_network_tests.rs index 45b7e8d..6dc5809 100644 --- a/src/network/radarr_network_tests.rs +++ b/src/network/radarr_network_tests.rs @@ -827,7 +827,7 @@ mod test { api_token: "test1234".to_owned(), ..ServarrConfig::default() }; - app.config.radarr = radarr_config; + app.config.radarr = Some(radarr_config); let app_arc = Arc::new(Mutex::new(app)); let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());