Compare commits
4 Commits
f5d7e05e9f
...
8bee3e48d3
Author | SHA1 | Date | |
---|---|---|---|
8bee3e48d3 | |||
087eaa04fa | |||
78c0fbf83b | |||
8a9da6e8da |
@ -34,6 +34,14 @@ struct DnsRecord {
|
||||
meta: HashMap<Box<str>, serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct CloudflareResponse {
|
||||
success: bool,
|
||||
errors: Vec<HashMap<String, serde_json::Value>>,
|
||||
messages: Vec<HashMap<String, serde_json::Value>>,
|
||||
result: Option<Vec<DnsRecord>>,
|
||||
}
|
||||
|
||||
impl CloudflareClient {
|
||||
pub async fn new(api_key: Box<str>, zone_id: Box<str>, domains: Vec<Box<str>>) -> Result<Self> {
|
||||
let force_ipv4 = IpAddr::from([0, 0, 0, 0]);
|
||||
@ -57,10 +65,11 @@ impl CloudflareClient {
|
||||
pub async fn check(&mut self) -> Result<()> {
|
||||
let new_ip = get_current_public_ipv4(&self.client).await?;
|
||||
if new_ip == self.current_ip {
|
||||
info!("IP '{}' is already set", new_ip);
|
||||
return Ok(());
|
||||
}
|
||||
info!(
|
||||
"Ip has changed from '{}' -> '{}'",
|
||||
"IP has changed from '{}' -> '{}'",
|
||||
&self.current_ip, &new_ip
|
||||
);
|
||||
self.update_dns_records(new_ip).await?;
|
||||
@ -75,7 +84,7 @@ impl CloudflareClient {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Could not getch dns records for domain '{}': {:?}",
|
||||
"Could not fetch DNS records for domain '{}': {:?}",
|
||||
&domain, &e
|
||||
);
|
||||
continue;
|
||||
@ -85,6 +94,10 @@ impl CloudflareClient {
|
||||
let new_ip_s = new_ip.to_string().into_boxed_str();
|
||||
for mut record in records.into_iter() {
|
||||
if record.content == new_ip_s {
|
||||
info!(
|
||||
"On {}, ip already updated to '{}'",
|
||||
&record.name, &record.content
|
||||
);
|
||||
continue;
|
||||
}
|
||||
info!(
|
||||
@ -109,7 +122,8 @@ impl CloudflareClient {
|
||||
"https://api.cloudflare.com/client/v4/zones/{}/dns_records?type=A&name={}",
|
||||
self.zone_id, domain
|
||||
);
|
||||
let mut response = self
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.get(&url)
|
||||
.header("Authorization", format!("Bearer {}", self.api_key))
|
||||
@ -117,12 +131,23 @@ impl CloudflareClient {
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?
|
||||
.json::<HashMap<String, Vec<DnsRecord>>>()
|
||||
.text()
|
||||
.await?;
|
||||
|
||||
response
|
||||
.remove("result")
|
||||
.context("Key result not in return")
|
||||
let cloudflare_response: CloudflareResponse =
|
||||
serde_json::from_str(&response).context("Failed to deserialize Cloudflare response")?;
|
||||
|
||||
if !cloudflare_response.success {
|
||||
error!(
|
||||
"Cloudflare API returned errors: {:?}",
|
||||
cloudflare_response.errors
|
||||
);
|
||||
return Err(anyhow::anyhow!("Cloudflare API returned errors"));
|
||||
}
|
||||
|
||||
cloudflare_response
|
||||
.result
|
||||
.context("Key 'result' not found in response")
|
||||
}
|
||||
|
||||
async fn update_dns_record(&self, record: &mut DnsRecord, ip_content: Box<str>) -> Result<()> {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::fmt;
|
||||
|
||||
use log::{debug, error, info, log_enabled, Level};
|
||||
use log::{debug, error, info};
|
||||
use netlink_packet_core::{NetlinkMessage, NetlinkPayload};
|
||||
use netlink_packet_route::RouteNetlinkMessage as RtnlMessage;
|
||||
|
||||
@ -38,9 +38,7 @@ impl<'a> MessageHandler<'a> {
|
||||
.await
|
||||
}
|
||||
_ => {
|
||||
if log_enabled!(Level::Debug) {
|
||||
debug!("Unhandled message payload: {:?}", message.payload);
|
||||
}
|
||||
debug!("Unhandled message payload: {:?}", message.payload);
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
@ -51,30 +49,24 @@ impl<'a> MessageHandler<'a> {
|
||||
D: fmt::Display + ?Sized,
|
||||
M: fmt::Debug,
|
||||
{
|
||||
if log_enabled!(Level::Debug) {
|
||||
debug!("{}: {:?}", log_msg, msg);
|
||||
} else {
|
||||
info!("{}", log_msg);
|
||||
if let Err(e) = self.cloudflare.check().await {
|
||||
self.errs_counter += 1;
|
||||
error!(
|
||||
"Failed to check cloudflare ({}/{}): {:?}",
|
||||
self.errs_counter, self.errs_max, &e
|
||||
);
|
||||
if self.errs_counter >= self.errs_max {
|
||||
return None;
|
||||
}
|
||||
info!("{}", log_msg);
|
||||
debug!("{}: {:?}", log_msg, msg);
|
||||
if let Err(e) = self.cloudflare.check().await {
|
||||
self.errs_counter += 1;
|
||||
error!(
|
||||
"Failed to check cloudflare ({}/{}): {:?}",
|
||||
self.errs_counter, self.errs_max, &e
|
||||
);
|
||||
if self.errs_counter >= self.errs_max {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
async fn log_info<M: fmt::Debug>(&self, log_msg: &str, msg: &M) -> Option<()> {
|
||||
if log_enabled!(Level::Debug) {
|
||||
debug!("{:?} message: {:?}", log_msg, msg);
|
||||
} else {
|
||||
info!("{}", log_msg);
|
||||
}
|
||||
info!("{}", log_msg);
|
||||
debug!("{:?} message: {:?}", log_msg, msg);
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user