Added dynamic string formatting to interpolate {ip} tag in the data property from the JSON file.
This commit is contained in:
parent
c39b0e898a
commit
fa814087bd
|
@ -181,6 +181,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"simple_logger",
|
"simple_logger",
|
||||||
|
"strfmt",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -791,6 +792,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strfmt"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b278b244ef7aa5852b277f52dd0c6cac3a109919e1f6d699adde63251227a30f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.82"
|
version = "1.0.82"
|
||||||
|
|
|
@ -11,4 +11,5 @@ tokio = { version = "1", features = ["full"] }
|
||||||
serde = { version = "1.0.132", features = ["derive"]}
|
serde = { version = "1.0.132", features = ["derive"]}
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
log = { version = "0.4", features = ["std", "serde"] }
|
log = { version = "0.4", features = ["std", "serde"] }
|
||||||
simple_logger = "1.16.0"
|
simple_logger = "1.16.0"
|
||||||
|
strfmt = "0.1.6"
|
|
@ -1,53 +1,17 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
|
use strfmt::strfmt;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use crate::go_daddy_ddns::dns_record::{DNSRecord, DNSRecordsHolder};
|
||||||
|
|
||||||
use crate::ip_handler::get_ip_to_publish;
|
use crate::ip_handler::get_ip_to_publish;
|
||||||
|
|
||||||
|
mod dns_record;
|
||||||
|
|
||||||
const RECORDS_FILE_NAME: &'static str = "records.json";
|
const RECORDS_FILE_NAME: &'static str = "records.json";
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
struct DNSRecordsHolder {
|
|
||||||
records: Vec<DNSRecord>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct DNSRecord {
|
|
||||||
name: String,
|
|
||||||
record_type: String,
|
|
||||||
data: Option<String>,
|
|
||||||
ttl: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct DNSRecordCreateTypeName {
|
|
||||||
data: String,
|
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[serde(default)]
|
|
||||||
port: Option<u16>, // SRV Only.
|
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[serde(default)]
|
|
||||||
priority: Option<u32>, // MX and SRV only.
|
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[serde(default)]
|
|
||||||
protocol: Option<String>, // SRV only.
|
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[serde(default)]
|
|
||||||
service: Option<String>, // SRV only.
|
|
||||||
|
|
||||||
ttl: u32,
|
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[serde(default)]
|
|
||||||
weight: Option<u32>, // SRV only.
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the DNS records if the IP has changed and returns the result of the execution.
|
/// Updates the DNS records if the IP has changed and returns the result of the execution.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -62,7 +26,7 @@ pub async fn exec(domain: &str, key: &str, secret: &str) -> Result<(), Box<dyn s
|
||||||
let new_ip = get_ip_to_publish().await;
|
let new_ip = get_ip_to_publish().await;
|
||||||
|
|
||||||
// There's no need to do anything here. So we stop the execution.
|
// There's no need to do anything here. So we stop the execution.
|
||||||
if Option::is_none(&new_ip) {
|
if new_ip.is_none() {
|
||||||
info!("The IP hasn't changed. Let's stop the execution here.");
|
info!("The IP hasn't changed. Let's stop the execution here.");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -70,7 +34,7 @@ pub async fn exec(domain: &str, key: &str, secret: &str) -> Result<(), Box<dyn s
|
||||||
info!("The IP has changed. Let's update the DNS records.");
|
info!("The IP has changed. Let's update the DNS records.");
|
||||||
for record in get_records() {
|
for record in get_records() {
|
||||||
debug!("{:?}", record);
|
debug!("{:?}", record);
|
||||||
update_record(&record, &new_ip.clone().unwrap(), domain, key, secret).await;
|
update_record(record, &new_ip.clone().unwrap(), domain, key, secret).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -91,7 +55,7 @@ fn get_records() -> Vec<DNSRecord> {
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `record` - A &DNSRecord holding the record to update.
|
/// * `record` - A DNSRecord holding the record to update.
|
||||||
///
|
///
|
||||||
/// * `value` - A &str holding the current WAN ip.
|
/// * `value` - A &str holding the current WAN ip.
|
||||||
///
|
///
|
||||||
|
@ -101,7 +65,7 @@ fn get_records() -> Vec<DNSRecord> {
|
||||||
///
|
///
|
||||||
/// * `secret` - A &str holding the GoDaddy developer secret.
|
/// * `secret` - A &str holding the GoDaddy developer secret.
|
||||||
async fn update_record(
|
async fn update_record(
|
||||||
record: &DNSRecord,
|
record: DNSRecord,
|
||||||
value: &str,
|
value: &str,
|
||||||
domain: &str,
|
domain: &str,
|
||||||
key: &str,
|
key: &str,
|
||||||
|
@ -110,23 +74,35 @@ async fn update_record(
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"https://api.godaddy.com/v1/domains/{domain}/records/{record_type}/{name}",
|
"https://api.godaddy.com/v1/domains/{domain}/records/{record_type}/{name}",
|
||||||
domain = domain,
|
domain = domain,
|
||||||
record_type = record.record_type,
|
record_type = record.record_type.unwrap(),
|
||||||
name = record.name
|
name = record.name.unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let data = match &record.data {
|
let data = match &record.data {
|
||||||
Some(x) => String::from(x),
|
Some(x) => {
|
||||||
|
if record.interpolate.is_some() && record.interpolate.unwrap() == true {
|
||||||
|
let mut vars = HashMap::new();
|
||||||
|
vars.insert("ip".to_string(), value);
|
||||||
|
|
||||||
|
strfmt(x, &vars).expect("Error interpolating {ip} from data.")
|
||||||
|
} else {
|
||||||
|
String::from(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
None => String::from(value),
|
None => String::from(value),
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = vec![DNSRecordCreateTypeName {
|
let body = vec![DNSRecord {
|
||||||
data,
|
name: None,
|
||||||
port: None,
|
record_type: None,
|
||||||
priority: None,
|
data: Some(data),
|
||||||
protocol: None,
|
port: record.port,
|
||||||
service: None,
|
priority: record.priority,
|
||||||
|
protocol: record.protocol,
|
||||||
|
service: record.service,
|
||||||
ttl: record.ttl,
|
ttl: record.ttl,
|
||||||
weight: None,
|
interpolate: None,
|
||||||
|
weight: record.weight,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let header = format!("sso-key {}:{}", key, secret);
|
let header = format!("sso-key {}:{}", key, secret);
|
||||||
|
|
Loading…
Reference in New Issue