aboutsummaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
authorGus Power <gus@infinitesidequests.com>2025-05-14 13:21:08 +0100
committerGus Power <gus@infinitesidequests.com>2025-05-14 13:21:08 +0100
commitdd1483cb6d9c060a17dc68357975de2b1ec09c08 (patch)
treedae1850e9ab89894fd217cfcd32ce31d91a767f8 /src/config.rs
parent87c3219c0e6c7f374cf117eb1990dd41e196710a (diff)
reduce size of DnsRecordType (introduce enum), add overall config w/ supporting "full" test file.
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..9230f38
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,115 @@
+use crate::dyndns_service::DynDnsProvider;
+use fqdn::FQDN;
+use serde::{Deserialize, Serialize};
+use serde_with::DisplayFromStr;
+use serde_with::serde_as;
+use strum::Display;
+
+#[derive(Debug, Deserialize, Serialize)]
+#[serde(transparent)]
+struct Config {
+ wans: Vec<WanConfig>
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+struct WanConfig {
+ interface: Option<String>,
+ #[serde(flatten)]
+ dns_record: DnsRecord,
+ providers: Vec<DynDnsProvider>,
+}
+
+#[derive(Debug, Display, Deserialize, Serialize)]
+#[derive(PartialEq)]
+pub enum DnsRecordType {
+ A,
+ AAAA
+}
+
+#[serde_as]
+#[derive(Debug, Deserialize, Serialize)]
+struct DnsRecord {
+ #[serde_as(as = "DisplayFromStr")]
+ fqdn: FQDN,
+ #[serde(default = "default_ttl")]
+ ttl: u32,
+ #[serde(default = "default_record_type")]
+ record_type: DnsRecordType,
+}
+
+fn default_record_type() -> DnsRecordType {
+ DnsRecordType::A
+}
+fn default_ttl() -> u32 {
+ 300
+}
+
+#[cfg(test)]
+mod tests {
+ use std::error::Error;
+ use std::fs::{read_dir, File};
+ use std::io::BufReader;
+ use super::*;
+ use serde_json::json;
+ use std::str::FromStr;
+ use crate::dyndns_service::DynDnsProvider::GANDI;
+ use crate::dyndns_service::gandi::Gandi;
+
+ #[test]
+ fn check_minimal_config() {
+ let input = json!({
+ "fqdn": "dyn.domain.com",
+ "providers": [ {
+ "type": "GANDI",
+ "api_key": "SOME-API-KEY",
+ } ]
+ });
+
+ let wan_config = serde_json::from_value::<WanConfig>(input).unwrap();
+
+ assert_eq!(
+ wan_config.dns_record.fqdn,
+ FQDN::from_str("dyn.domain.com").unwrap()
+ );
+ assert_eq!(wan_config.interface, None);
+
+ assert_eq!(wan_config.providers.len(), 1);
+ let expected = Gandi::new("SOME-API-KEY".to_string());
+ let actual = wan_config.providers.get(0).unwrap();
+ assert_eq!(&GANDI(expected), actual);
+ }
+
+ #[test]
+ fn check_defaults_on_dns_record_deserialization() {
+ let input = json!({
+ "fqdn": "dyn.mydomain.com",
+ });
+
+ let dns_record = serde_json::from_value::<DnsRecord>(input).unwrap();
+
+ assert_eq!(dns_record.record_type, default_record_type());
+ assert_eq!(dns_record.ttl, default_ttl());
+
+ assert_eq!(dns_record.fqdn, FQDN::from_str("dyn.mydomain.com").unwrap());
+ }
+
+ #[test]
+ fn check_file_configs() -> Result<(), Box<dyn Error>> {
+ let path = std::path::Path::new("test");
+ for entry in read_dir(path)? {
+ let entry = entry?;
+ let test_file_path = entry.path();
+ if test_file_path.extension().unwrap_or_default() != "json" {
+ continue;
+ }
+
+ let file = File::open(test_file_path)?;
+ let reader = BufReader::new(file);
+
+ let actual: Config = serde_json::from_reader(reader)?;
+ assert_eq!(actual.wans.len(), 2);
+ }
+ Ok(())
+ }
+
+}