From b00f3e2f1956a2d53742c1b7fa041df9ab0c0c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Augusto=20C=C3=A9sar?= Date: Fri, 3 Jan 2025 09:28:16 +0100 Subject: [PATCH] feat: skip Dnsmasq and Caddy if can't read /etc/resolver (#132) This should fix cases where starting Linkup on a system that does not have `/etc/resolver` setup would break. Now it will skip both `caddy` and `dnsmasq` if the folder is not found. --- linkup-cli/src/commands/local_dns.rs | 15 +++++++++--- linkup-cli/src/services/caddy.rs | 34 ++++++++++++++++++-------- linkup-cli/src/services/dnsmasq.rs | 36 +++++++++++++++++++--------- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/linkup-cli/src/commands/local_dns.rs b/linkup-cli/src/commands/local_dns.rs index 301059e..3817642 100644 --- a/linkup-cli/src/commands/local_dns.rs +++ b/linkup-cli/src/commands/local_dns.rs @@ -146,9 +146,18 @@ fn uninstall_resolvers(resolve_domains: &[String]) -> Result<()> { Ok(()) } -pub fn list_resolvers() -> Result> { - let resolvers = fs::read_dir("/etc/resolver/")? - .map(|f| f.unwrap().file_name().into_string().unwrap()) +pub fn list_resolvers() -> std::result::Result, std::io::Error> { + let resolvers_dir = match fs::read_dir("/etc/resolver/") { + Ok(read_dir) => read_dir, + Err(err) => match err.kind() { + std::io::ErrorKind::NotFound => return Ok(vec![]), + _ => return Err(err), + }, + }; + + let resolvers = resolvers_dir + .filter_map(|entry| entry.ok()) + .filter_map(|entry| entry.file_name().into_string().ok()) .collect(); Ok(resolvers) diff --git a/linkup-cli/src/services/caddy.rs b/linkup-cli/src/services/caddy.rs index 610c9473..6d76ba3 100644 --- a/linkup-cli/src/services/caddy.rs +++ b/linkup-cli/src/services/caddy.rs @@ -159,10 +159,10 @@ impl Caddy { output_str.contains("redis") } - fn should_start(&self, domains: &[String]) -> bool { - let resolvers = local_dns::list_resolvers().unwrap(); + fn should_start(&self, domains: &[String]) -> Result { + let resolvers = local_dns::list_resolvers()?; - domains.iter().any(|domain| resolvers.contains(domain)) + Ok(domains.iter().any(|domain| resolvers.contains(domain))) } pub fn running_pid(&self) -> Option { @@ -180,14 +180,28 @@ impl BackgroundService for Caddy { ) -> Result<(), Error> { let domains = &state.domain_strings(); - if !self.should_start(domains) { - self.notify_update_with_details( - &status_sender, - super::RunStatus::Skipped, - "Local DNS not installed", - ); + match self.should_start(domains) { + Ok(true) => (), + Ok(false) => { + self.notify_update_with_details( + &status_sender, + super::RunStatus::Skipped, + "Local DNS not installed", + ); - return Ok(()); + return Ok(()); + } + Err(err) => { + self.notify_update_with_details( + &status_sender, + super::RunStatus::Skipped, + "Failed to read resolvers folder", + ); + + log::warn!("Failed to read resolvers folder: {}", err); + + return Ok(()); + } } self.notify_update(&status_sender, super::RunStatus::Starting); diff --git a/linkup-cli/src/services/dnsmasq.rs b/linkup-cli/src/services/dnsmasq.rs index dae4dcc..e788206 100644 --- a/linkup-cli/src/services/dnsmasq.rs +++ b/linkup-cli/src/services/dnsmasq.rs @@ -90,10 +90,10 @@ pid-file={}\n", signal::get_running_pid(&self.pid_file_path) } - fn should_start(&self, domains: &[String]) -> bool { - let resolvers = local_dns::list_resolvers().unwrap(); + fn should_start(&self, domains: &[String]) -> Result { + let resolvers = local_dns::list_resolvers()?; - domains.iter().any(|domain| resolvers.contains(domain)) + Ok(domains.iter().any(|domain| resolvers.contains(domain))) } } @@ -107,14 +107,28 @@ impl BackgroundService for Dnsmasq { ) -> Result<(), Error> { let domains = &state.domain_strings(); - if !self.should_start(domains) { - self.notify_update_with_details( - &status_sender, - super::RunStatus::Skipped, - "Local DNS not installed", - ); - - return Ok(()); + match self.should_start(domains) { + Ok(true) => (), + Ok(false) => { + self.notify_update_with_details( + &status_sender, + super::RunStatus::Skipped, + "Local DNS not installed", + ); + + return Ok(()); + } + Err(err) => { + self.notify_update_with_details( + &status_sender, + super::RunStatus::Skipped, + "Failed to read resolvers folder", + ); + + log::warn!("Failed to read resolvers folder: {}", err); + + return Ok(()); + } } self.notify_update(&status_sender, super::RunStatus::Starting);