feat: Support for loading Servarr API tokens from a file
This commit is contained in:
@@ -319,13 +319,13 @@ sonarr:
|
|||||||
uri: http://htpc.local/sonarr # Example of using the 'uri' key instead of 'host' and 'port'
|
uri: http://htpc.local/sonarr # Example of using the 'uri' key instead of 'host' and 'port'
|
||||||
api_token: someApiToken1234567890
|
api_token: someApiToken1234567890
|
||||||
readarr:
|
readarr:
|
||||||
host: 192.168.0.87
|
host: 192.168.0.87
|
||||||
port: 8787
|
port: 8787
|
||||||
api_token: someApiToken1234567890
|
api_token_file: /root/.config/readarr_api_token # Example of loading the API token from a file instead of hardcoding it in the configuration file
|
||||||
lidarr:
|
lidarr:
|
||||||
host: 192.168.0.86
|
host: 192.168.0.86
|
||||||
port: 8686
|
port: 8686
|
||||||
api_token: someApiToken1234567890
|
api_token: ${MY_LIDARR_API_TOKEN} # Example of configuring using environment variables
|
||||||
whisparr:
|
whisparr:
|
||||||
host: 192.168.0.69
|
host: 192.168.0.69
|
||||||
port: 6969
|
port: 6969
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ mod tests {
|
|||||||
assert_eq!(servarr_config.host, Some("localhost".to_string()));
|
assert_eq!(servarr_config.host, Some("localhost".to_string()));
|
||||||
assert_eq!(servarr_config.port, None);
|
assert_eq!(servarr_config.port, None);
|
||||||
assert_eq!(servarr_config.uri, None);
|
assert_eq!(servarr_config.uri, None);
|
||||||
assert!(servarr_config.api_token.is_empty());
|
assert_eq!(servarr_config.api_token, Some(String::new()));
|
||||||
assert_eq!(servarr_config.ssl_cert_path, None);
|
assert_eq!(servarr_config.ssl_cert_path, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,14 +507,16 @@ mod tests {
|
|||||||
let port = 1234;
|
let port = 1234;
|
||||||
let uri = "http://localhost:1234".to_owned();
|
let uri = "http://localhost:1234".to_owned();
|
||||||
let api_token = "thisisatest".to_owned();
|
let api_token = "thisisatest".to_owned();
|
||||||
|
let api_token_file = "/root/.config/api_token".to_owned();
|
||||||
let ssl_cert_path = "/some/path".to_owned();
|
let ssl_cert_path = "/some/path".to_owned();
|
||||||
let expected_str = format!("ServarrConfig {{ host: Some(\"{}\"), port: Some({}), uri: Some(\"{}\"), api_token: \"***********\", ssl_cert_path: Some(\"{}\") }}",
|
let expected_str = format!("ServarrConfig {{ host: Some(\"{}\"), port: Some({}), uri: Some(\"{}\"), api_token: Some(\"***********\"), api_token_file: Some(\"{}\"), ssl_cert_path: Some(\"{}\") }}",
|
||||||
host, port, uri, ssl_cert_path);
|
host, port, uri, api_token_file, ssl_cert_path);
|
||||||
let servarr_config = ServarrConfig {
|
let servarr_config = ServarrConfig {
|
||||||
host: Some(host),
|
host: Some(host),
|
||||||
port: Some(port),
|
port: Some(port),
|
||||||
uri: Some(uri),
|
uri: Some(uri),
|
||||||
api_token,
|
api_token: Some(api_token),
|
||||||
|
api_token_file: Some(api_token_file),
|
||||||
ssl_cert_path: Some(ssl_cert_path),
|
ssl_cert_path: Some(ssl_cert_path),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+38
-6
@@ -1,6 +1,6 @@
|
|||||||
use std::process;
|
use std::{fs, process};
|
||||||
|
use std::path::PathBuf;
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error, Result};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
@@ -258,6 +258,28 @@ impl AppConfig {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn post_process_initialization(&mut self) {
|
||||||
|
let fetch_token = |config: &mut ServarrConfig, name: &'static str| {
|
||||||
|
if let Some(api_token_file) = config.api_token_file.as_ref() {
|
||||||
|
if !PathBuf::from(api_token_file).exists() {
|
||||||
|
log_and_print_error(format!("The specified {} API token file", name));
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let api_token = fs::read_to_string(api_token_file).map_err(|e| anyhow!(e)).unwrap();
|
||||||
|
config.api_token = Some(api_token.trim().to_owned());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(radarr_config) = self.radarr.as_mut() {
|
||||||
|
fetch_token(radarr_config, "Radarr");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(sonarr_config) = self.sonarr.as_mut() {
|
||||||
|
fetch_token(sonarr_config, "Sonarr");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Redact, Deserialize, Serialize, Clone)]
|
#[derive(Redact, Deserialize, Serialize, Clone)]
|
||||||
@@ -268,9 +290,11 @@ pub struct ServarrConfig {
|
|||||||
pub port: Option<u16>,
|
pub port: Option<u16>,
|
||||||
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
pub uri: Option<String>,
|
pub uri: Option<String>,
|
||||||
#[serde(default, deserialize_with = "deserialize_env_var")]
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
#[redact]
|
#[redact]
|
||||||
pub api_token: String,
|
pub api_token: Option<String>,
|
||||||
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
|
pub api_token_file: Option<String>,
|
||||||
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
pub ssl_cert_path: Option<String>,
|
pub ssl_cert_path: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -281,6 +305,13 @@ impl ServarrConfig {
|
|||||||
log_and_print_error("'host' or 'uri' is required for configuration".to_owned());
|
log_and_print_error("'host' or 'uri' is required for configuration".to_owned());
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.api_token_file.is_none() && self.api_token.is_none() {
|
||||||
|
log_and_print_error(
|
||||||
|
"'api_token' or 'api_token_path' is required for configuration".to_owned(),
|
||||||
|
);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +321,8 @@ impl Default for ServarrConfig {
|
|||||||
host: Some("localhost".to_string()),
|
host: Some("localhost".to_string()),
|
||||||
port: None,
|
port: None,
|
||||||
uri: None,
|
uri: None,
|
||||||
api_token: "".to_string(),
|
api_token: Some(String::new()),
|
||||||
|
api_token_file: None,
|
||||||
ssl_cert_path: None,
|
ssl_cert_path: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -87,7 +87,7 @@ async fn main() -> Result<()> {
|
|||||||
let running = Arc::new(AtomicBool::new(true));
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
let r = running.clone();
|
let r = running.clone();
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
let config = if let Some(ref config_file) = args.config {
|
let mut config = if let Some(ref config_file) = args.config {
|
||||||
load_config(config_file.to_str().expect("Invalid config file specified"))?
|
load_config(config_file.to_str().expect("Invalid config file specified"))?
|
||||||
} else {
|
} else {
|
||||||
confy::load("managarr", "config")?
|
confy::load("managarr", "config")?
|
||||||
@@ -95,6 +95,7 @@ async fn main() -> Result<()> {
|
|||||||
let spinner_disabled = args.disable_spinner;
|
let spinner_disabled = args.disable_spinner;
|
||||||
debug!("Managarr loaded using config: {config:?}");
|
debug!("Managarr loaded using config: {config:?}");
|
||||||
config.validate();
|
config.validate();
|
||||||
|
config.post_process_initialization();
|
||||||
let reqwest_client = build_network_client(&config);
|
let reqwest_client = build_network_client(&config);
|
||||||
let (sync_network_tx, sync_network_rx) = mpsc::channel(500);
|
let (sync_network_tx, sync_network_rx) = mpsc::channel(500);
|
||||||
let cancellation_token = CancellationToken::new();
|
let cancellation_token = CancellationToken::new();
|
||||||
|
|||||||
+2
-1
@@ -213,6 +213,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
uri,
|
uri,
|
||||||
api_token,
|
api_token,
|
||||||
ssl_cert_path,
|
ssl_cert_path,
|
||||||
|
..
|
||||||
},
|
},
|
||||||
default_port,
|
default_port,
|
||||||
) = match network_event.into() {
|
) = match network_event.into() {
|
||||||
@@ -252,7 +253,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
uri,
|
uri,
|
||||||
method,
|
method,
|
||||||
body,
|
body,
|
||||||
api_token: api_token.to_owned(),
|
api_token: api_token.as_ref().expect("API token not found").clone(),
|
||||||
ignore_status_code: false,
|
ignore_status_code: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ mod tests {
|
|||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
let radarr_config = ServarrConfig {
|
let radarr_config = ServarrConfig {
|
||||||
host,
|
host,
|
||||||
api_token: String::new(),
|
api_token: Some(String::new()),
|
||||||
port,
|
port,
|
||||||
ssl_cert_path: None,
|
ssl_cert_path: None,
|
||||||
..ServarrConfig::default()
|
..ServarrConfig::default()
|
||||||
@@ -472,7 +472,7 @@ mod tests {
|
|||||||
let servarr_config = ServarrConfig {
|
let servarr_config = ServarrConfig {
|
||||||
host: Some("192.168.0.123".to_owned()),
|
host: Some("192.168.0.123".to_owned()),
|
||||||
port: Some(8080),
|
port: Some(8080),
|
||||||
api_token: api_token.clone(),
|
api_token: Some(api_token.clone()),
|
||||||
ssl_cert_path: Some("/test/cert.crt".to_owned()),
|
ssl_cert_path: Some("/test/cert.crt".to_owned()),
|
||||||
..ServarrConfig::default()
|
..ServarrConfig::default()
|
||||||
};
|
};
|
||||||
@@ -507,7 +507,7 @@ mod tests {
|
|||||||
let resource = network_event.resource();
|
let resource = network_event.resource();
|
||||||
let servarr_config = ServarrConfig {
|
let servarr_config = ServarrConfig {
|
||||||
uri: Some("https://192.168.0.123:8080".to_owned()),
|
uri: Some("https://192.168.0.123:8080".to_owned()),
|
||||||
api_token: api_token.clone(),
|
api_token: Some(api_token.clone()),
|
||||||
..ServarrConfig::default()
|
..ServarrConfig::default()
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
@@ -577,7 +577,7 @@ mod tests {
|
|||||||
let servarr_config = ServarrConfig {
|
let servarr_config = ServarrConfig {
|
||||||
host: Some("192.168.0.123".to_owned()),
|
host: Some("192.168.0.123".to_owned()),
|
||||||
port: Some(8080),
|
port: Some(8080),
|
||||||
api_token: api_token.clone(),
|
api_token: Some(api_token.clone()),
|
||||||
ssl_cert_path: Some("/test/cert.crt".to_owned()),
|
ssl_cert_path: Some("/test/cert.crt".to_owned()),
|
||||||
..ServarrConfig::default()
|
..ServarrConfig::default()
|
||||||
};
|
};
|
||||||
@@ -618,7 +618,7 @@ mod tests {
|
|||||||
let resource = network_event.resource();
|
let resource = network_event.resource();
|
||||||
let servarr_config = ServarrConfig {
|
let servarr_config = ServarrConfig {
|
||||||
uri: Some("https://192.168.0.123:8080".to_owned()),
|
uri: Some("https://192.168.0.123:8080".to_owned()),
|
||||||
api_token: api_token.clone(),
|
api_token: Some(api_token.clone()),
|
||||||
..ServarrConfig::default()
|
..ServarrConfig::default()
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
@@ -738,7 +738,7 @@ pub(in crate::network) mod test_utils {
|
|||||||
let servarr_config = ServarrConfig {
|
let servarr_config = ServarrConfig {
|
||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
api_token: "test1234".to_owned(),
|
api_token: Some("test1234".to_owned()),
|
||||||
..ServarrConfig::default()
|
..ServarrConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user