aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs102
1 files changed, 93 insertions, 9 deletions
diff --git a/src/main.rs b/src/main.rs
index 57f4c7d..66fbdee 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,10 @@
use crate::config::Config;
-use crate::error::AppResult;
+use crate::error::{AppError, AppResult};
+use crate::ip_service::IpService;
use clap::Parser;
+use homedir::my_home;
+use log::info;
+use reqwest::ClientBuilder;
use std::path::PathBuf;
use std::process::exit;
@@ -13,17 +17,54 @@ mod ip_service;
mod test_macros;
#[derive(Parser, Debug)]
-#[command(version, about, long_about = None)]
+#[command(ignore_errors(true), version, about, long_about = None)]
struct Args {
- #[arg(short, long, default_value = "~/.config/multiwan-dyndns/config.json")]
- config_file: PathBuf,
+ #[arg(short, long)]
+ config_file: Option<PathBuf>,
}
-fn main() {
+impl Args {
+ fn get_config_files(&self) -> Vec<PathBuf> {
+ match self.config_file {
+ Some(ref config_file) => vec![config_file.to_path_buf()],
+ None => DefaultConfigFile::default().paths,
+ }
+ }
+}
+
+struct DefaultConfigFile {
+ paths: Vec<PathBuf>,
+}
+
+impl DefaultConfigFile {
+ fn user_home_config() -> AppResult<Option<PathBuf>> {
+ let home = my_home().map_err(AppError::UnableToGetHomeDirectory)?;
+ match home {
+ None => Ok(None),
+ Some(mut path) => {
+ path.push(".config/multiwan-dyndns/config.json");
+ Ok(Some(path))
+ }
+ }
+ }
+}
+impl Default for DefaultConfigFile {
+ fn default() -> Self {
+ let mut paths = Vec::new();
+ paths.push(PathBuf::from("/etc/multiwan-dyndns.json"));
+ if let Some(user_home) = Self::user_home_config().unwrap() {
+ paths.push(user_home);
+ }
+ Self { paths }
+ }
+}
+
+#[tokio::main]
+async fn main() {
env_logger::init();
let args = Args::parse();
- match run(args) {
+ match run(args).await {
Ok(_) => exit(0),
Err(e) => {
log::error!("{}", e);
@@ -32,10 +73,12 @@ fn main() {
}
}
-fn run(args: Args) -> AppResult<()> {
- let config = Config::load(&args.config_file)?;
+async fn run(args: Args) -> AppResult<()> {
+ let config = Config::load(args.get_config_files())?;
+ let client = ClientBuilder::new().build()?;
for network in config.networks {
- // let ip = IpService::resolve(&network.ip_service)?;
+ let ip = network.ip_service.resolve(&client).await?;
+ info!("{:?}: {}", network.interface, ip);
// for dyndns in network.providers {
// DynDnsService::register(&dyndns, &ip)?;
// }
@@ -43,3 +86,44 @@ fn run(args: Args) -> AppResult<()> {
Ok(())
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use homedir::my_home;
+ use std::ffi::OsString;
+ use std::iter;
+ use std::path::Path;
+
+ macro_rules! assert_contains_config {
+ ($config:expr, $expected:expr) => {
+ assert!(
+ $config.contains(&$expected.to_path_buf()),
+ "Expected {} path {:?}\nActual paths: {:?}",
+ stringify!($expected),
+ $expected,
+ $config
+ );
+ };
+ }
+
+ test! {
+ fn verify_default_config_path_is_in_home_directory() {
+ let args = Args::parse_from(iter::empty::<OsString>());
+
+ let global_config = Path::new("/etc/multiwan-dyndns.json");
+ let user_config_path = format!("{}/.config/multiwan-dyndns/config.json", my_home()?.unwrap().to_string_lossy());
+ let user_config = Path::new(&user_config_path);
+
+ let actual = args.get_config_files();
+ assert_contains_config!(actual, user_config);
+ assert_contains_config!(actual, global_config);
+ }
+ }
+
+ #[tokio::test]
+ async fn verify_it_actually_runs() {
+ let args = vec!["multiwan-dyndns", "--config-file", "test/noop.json"];
+ run(Args::parse_from(args)).await.expect("app didn't run!");
+ }
+}