diff options
Diffstat (limited to 'src/dns_updater.rs')
-rw-r--r-- | src/dns_updater.rs | 88 |
1 files changed, 69 insertions, 19 deletions
diff --git a/src/dns_updater.rs b/src/dns_updater.rs index d781671..e65689d 100644 --- a/src/dns_updater.rs +++ b/src/dns_updater.rs @@ -8,16 +8,28 @@ use tokio::sync::watch; use tracing::*; use crate::dns_config::*; -use crate::provider::DnsProvider; +use crate::DomainProvider; pub async fn dns_updater_task( mut rx_dns_config: watch::Receiver<Arc<DnsConfig>>, - provider: Box<dyn DnsProvider>, + providers: Vec<DomainProvider>, allowed_domains: Vec<String>, mut must_exit: watch::Receiver<bool>, ) { + for dom in allowed_domains.iter() { + info!(domain = dom, "allowing subdomains of domain"); + } + for prov in providers.iter() { + info!( + domain = prov.domain, + provider = prov.provider.provider(), + "got provider for domain" + ); + } + info!("DNS updater will start in 5 seconds"); tokio::time::sleep(Duration::from_secs(5)).await; + info!("DNS updater starting"); let mut config = Arc::new(DnsConfig::new()); @@ -32,21 +44,37 @@ pub async fn dns_updater_task( ); let new_config: Arc<DnsConfig> = rx_dns_config.borrow().clone(); - for (k, v) in new_config.entries.iter() { - if config.entries.get(k) != Some(v) { - let fulldomain = format!("{}.{}", k.subdomain, k.domain); - if !allowed_domains.iter().any(|d| fulldomain.ends_with(d)) { + for (key, value) in new_config.entries.iter() { + // Skip entries that haven't changed + if config.entries.get(key) == Some(value) { + continue; + } + + // Skip entries for unallowed domains + if !allowed_domains.iter().any(|d| key.dns_path.ends_with(d)) { + error!( + domain = key.dns_path, + "domain/subdomain/hostname not in allowed list", + ); + continue; + } + + let provider = providers.iter().find(|p| key.dns_path.ends_with(&p.domain)); + + if let Some(provider) = provider { + if let Err(e) = update_dns_entry(key, value, provider).await { error!( - "Got an entry for domain {} which is not in allowed list", - k.domain + record = key.to_string(), + target = value.to_string(), + error = e.to_string(), + "unable to update record" ); - continue; - } - - info!("Updating {} {}", k, v); - if let Err(e) = update_dns_entry(k, v, provider.as_ref()).await { - error!("Unable to update entry {} {}: {}", k, v, e); } + } else { + error!( + domain = key.dns_path, + "no provider matches this domain/subdomain/hostname" + ); } } @@ -57,8 +85,22 @@ pub async fn dns_updater_task( async fn update_dns_entry( key: &DnsEntryKey, value: &DnsEntryValue, - provider: &dyn DnsProvider, + provider: &DomainProvider, ) -> Result<()> { + let subdomain = key + .dns_path + .strip_suffix(&provider.domain) + .unwrap() + .trim_end_matches('.'); + info!( + record = key.to_string(), + target = value.to_string(), + domain = provider.domain, + subdomain = &subdomain, + provider = provider.provider.provider(), + "updating record" + ); + if value.targets.is_empty() { bail!("zero targets (internal error)"); } @@ -73,7 +115,8 @@ async fn update_dns_entry( ); } provider - .update_a(&key.domain, &key.subdomain, &targets) + .provider + .update_a(&provider.domain, &subdomain, &targets) .await?; } DnsRecordType::AAAA => { @@ -85,17 +128,24 @@ async fn update_dns_entry( ); } provider - .update_aaaa(&key.domain, &key.subdomain, &targets) + .provider + .update_aaaa(&provider.domain, &subdomain, &targets) .await?; } DnsRecordType::CNAME => { let mut targets = value.targets.iter().cloned().collect::<Vec<_>>(); if targets.len() > 1 { targets.sort(); - warn!("Several CNAME targets for {}: {:?}. Taking first one in alphabetical order. Consider switching to a single global target instead.", key, targets); + warn!( + record = key.to_string(), + all_targets = value.to_string(), + selected_target = targets[0], + "Several CNAME targets, taking first one in alphabetical order. Consider switching to a single global target instead." + ); } provider - .update_cname(&key.domain, &key.subdomain, &targets[0]) + .provider + .update_cname(&provider.domain, &subdomain, &targets[0]) .await?; } } |