mirror of
https://github.com/timothymiller/cloudflare-ddns.git
synced 2026-09-20 14:39:04 -03:00
Compare commits
17 Commits
v2.2.0
...
6d7e4d644e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d7e4d644e | ||
|
|
1faef32f1e | ||
|
|
ee46eb9c4c | ||
|
|
da4b20e252 | ||
|
|
3307adaede | ||
|
|
65f5629157 | ||
|
|
da3b90ff93 | ||
|
|
4ef6ba1b74 | ||
|
|
4cf7987f73 | ||
|
|
70a562b734 | ||
|
|
4c4a5e544a | ||
|
|
9a3c86c9bc | ||
|
|
7ea89cd973 | ||
|
|
a59d787e89 | ||
|
|
f0be440d00 | ||
|
|
e3678c6e24 | ||
|
|
8e79fc8798 |
4
.github/workflows/helm.yml
vendored
4
.github/workflows/helm.yml
vendored
@@ -21,10 +21,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install Helm
|
||||
uses: azure/setup-helm@v4
|
||||
uses: azure/setup-helm@v5
|
||||
|
||||
- name: Lint chart
|
||||
run: helm lint charts/cloudflare-ddns
|
||||
|
||||
2
.github/workflows/image.yml
vendored
2
.github/workflows/image.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v4
|
||||
uses: docker/login-action@v4.5.2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,3 +8,6 @@ debug/
|
||||
|
||||
# Git History
|
||||
**/.history/*
|
||||
|
||||
# JetBrains IDE
|
||||
.idea/
|
||||
63
Cargo.lock
generated
63
Cargo.lock
generated
@@ -168,7 +168,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -276,7 +276,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -679,7 +679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -801,7 +801,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -946,9 +946,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.42"
|
||||
version = "0.23.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138"
|
||||
checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
@@ -1078,9 +1078,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
@@ -1088,29 +1088,29 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 3.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.150"
|
||||
version = "1.0.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -1192,6 +1192,17 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "1.0.2"
|
||||
@@ -1209,7 +1220,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1242,7 +1253,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1257,9 +1268,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.52.4"
|
||||
version = "1.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "317fafbbe3f02fc663dad00ea6186197de963cd4190e86a26d8d0fae095539af"
|
||||
checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -1279,7 +1290,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1500,7 +1511,7 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -1782,7 +1793,7 @@ dependencies = [
|
||||
"heck",
|
||||
"indexmap",
|
||||
"prettyplease",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
"wasm-metadata",
|
||||
"wit-bindgen-core",
|
||||
"wit-component",
|
||||
@@ -1798,7 +1809,7 @@ dependencies = [
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
"wit-bindgen-core",
|
||||
"wit-bindgen-rust",
|
||||
]
|
||||
@@ -1865,7 +1876,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -1886,7 +1897,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -1926,7 +1937,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -31,6 +31,8 @@ pub struct LegacyConfig {
|
||||
pub ip4_provider: Option<String>,
|
||||
#[serde(default)]
|
||||
pub ip6_provider: Option<String>,
|
||||
#[serde(rename = "recordComment", alias = "record_comment", default)]
|
||||
pub record_comment: Option<String>,
|
||||
}
|
||||
|
||||
fn default_true() -> bool {
|
||||
@@ -476,7 +478,7 @@ fn legacy_to_app_config(
|
||||
delete_on_failure: false,
|
||||
ttl,
|
||||
proxied_expression: None,
|
||||
record_comment: None,
|
||||
record_comment: legacy.record_comment.clone(),
|
||||
managed_comment_regex: None,
|
||||
waf_list_description: None,
|
||||
waf_list_item_comment: None,
|
||||
@@ -1063,6 +1065,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: None,
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
};
|
||||
let config = legacy_to_app_config(legacy, false, false).unwrap();
|
||||
assert!(config.legacy_mode);
|
||||
@@ -1091,6 +1094,7 @@ mod tests {
|
||||
ttl: 120,
|
||||
ip4_provider: None,
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
};
|
||||
let config = legacy_to_app_config(legacy, true, true).unwrap();
|
||||
assert!(
|
||||
@@ -1121,6 +1125,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: None,
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
};
|
||||
let config = legacy_to_app_config(legacy, false, false).unwrap();
|
||||
assert!(matches!(config.auth, Auth::Key { ref api_key, ref email }
|
||||
@@ -1145,6 +1150,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: Some("ipify".to_string()),
|
||||
ip6_provider: Some("cloudflare.doh".to_string()),
|
||||
record_comment: None,
|
||||
};
|
||||
let config = legacy_to_app_config(legacy, false, false).unwrap();
|
||||
assert!(matches!(config.providers[&IpType::V4], ProviderType::Ipify));
|
||||
@@ -1172,6 +1178,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: Some("none".to_string()),
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
};
|
||||
let config = legacy_to_app_config(legacy, false, false).unwrap();
|
||||
// ip4_provider=none should exclude V4 even though a=true
|
||||
@@ -1197,6 +1204,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: Some("totally_invalid".to_string()),
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
};
|
||||
let result = legacy_to_app_config(legacy, false, false);
|
||||
assert!(result.is_err());
|
||||
@@ -1204,6 +1212,30 @@ mod tests {
|
||||
assert!(err.contains("ip4_provider"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_legacy_to_app_config_with_record_comment() {
|
||||
let legacy = LegacyConfig {
|
||||
cloudflare: vec![LegacyCloudflareEntry {
|
||||
authentication: LegacyAuthentication {
|
||||
api_token: "tok".to_string(),
|
||||
api_key: None,
|
||||
},
|
||||
zone_id: "z".to_string(),
|
||||
subdomains: vec![],
|
||||
proxied: false,
|
||||
}],
|
||||
a: true,
|
||||
aaaa: false,
|
||||
purge_unknown_records: false,
|
||||
ttl: 300,
|
||||
ip4_provider: None,
|
||||
ip6_provider: None,
|
||||
record_comment: Some("managed by cloudflare-ddns".to_string()),
|
||||
};
|
||||
let config = legacy_to_app_config(legacy, false, false).unwrap();
|
||||
assert_eq!(config.record_comment, Some("managed by cloudflare-ddns".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_legacy_config_deserializes_providers() {
|
||||
let json = r#"{
|
||||
@@ -1220,6 +1252,20 @@ mod tests {
|
||||
assert_eq!(config.ip6_provider, Some("none".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_legacy_config_deserializes_record_comment() {
|
||||
let json = r#"{
|
||||
"cloudflare": [{
|
||||
"authentication": { "api_token": "tok" },
|
||||
"zone_id": "z",
|
||||
"subdomains": ["@"]
|
||||
}],
|
||||
"recordComment": "managed by cloudflare-ddns"
|
||||
}"#;
|
||||
let config = parse_legacy_config(json).unwrap();
|
||||
assert_eq!(config.record_comment, Some("managed by cloudflare-ddns".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_legacy_config_deserializes_without_providers() {
|
||||
let json = r#"{
|
||||
|
||||
@@ -421,6 +421,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: None,
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,6 +974,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: None,
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
};
|
||||
ddns.commit_record(
|
||||
"198.51.100.7",
|
||||
@@ -1104,6 +1106,7 @@ mod tests {
|
||||
ttl: 300,
|
||||
ip4_provider: None,
|
||||
ip6_provider: None,
|
||||
record_comment: None,
|
||||
};
|
||||
|
||||
ddns.commit_record(
|
||||
|
||||
113
src/updater.rs
113
src/updater.rs
@@ -409,7 +409,7 @@ async fn update_legacy(
|
||||
.await
|
||||
{
|
||||
ips.retain(|key, ip_info| {
|
||||
if let Ok(addr) = ip_info.ip.parse::<std::net::IpAddr>() {
|
||||
if let Ok(addr) = ip_info.ip.parse::<IpAddr>() {
|
||||
if cf_filter.contains(&addr) {
|
||||
ppfmt.warningf(
|
||||
pp::EMOJI_WARNING,
|
||||
@@ -445,6 +445,7 @@ async fn update_legacy(
|
||||
legacy.ttl,
|
||||
legacy.purge_unknown_records,
|
||||
noop_reported,
|
||||
config.record_comment.as_deref(),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -599,12 +600,20 @@ impl LegacyDdnsClient {
|
||||
ttl: i64,
|
||||
purge_unknown_records: bool,
|
||||
noop_reported: &mut HashSet<String>,
|
||||
comment: Option<&str>,
|
||||
) -> (Vec<Message>, bool) {
|
||||
let mut messages = Vec::new();
|
||||
let mut notify = false;
|
||||
for ip in ips.values() {
|
||||
let (msgs, changed) = self
|
||||
.commit_record(ip, config, ttl, purge_unknown_records, noop_reported)
|
||||
.commit_record(
|
||||
ip,
|
||||
config,
|
||||
ttl,
|
||||
purge_unknown_records,
|
||||
noop_reported,
|
||||
comment,
|
||||
)
|
||||
.await;
|
||||
messages.extend(msgs);
|
||||
if changed {
|
||||
@@ -621,6 +630,7 @@ impl LegacyDdnsClient {
|
||||
ttl: i64,
|
||||
purge_unknown_records: bool,
|
||||
noop_reported: &mut HashSet<String>,
|
||||
comment: Option<&str>,
|
||||
) -> (Vec<Message>, bool) {
|
||||
let mut messages = Vec::new();
|
||||
let mut changed = false;
|
||||
@@ -660,6 +670,7 @@ impl LegacyDdnsClient {
|
||||
content: ip.ip.clone(),
|
||||
proxied,
|
||||
ttl,
|
||||
comment: comment.map(|s| s.to_string()),
|
||||
};
|
||||
|
||||
let dns_endpoint = format!(
|
||||
@@ -687,7 +698,10 @@ impl LegacyDdnsClient {
|
||||
}
|
||||
} else {
|
||||
identifier = Some(r.id.clone());
|
||||
if r.content != record.content || r.proxied != record.proxied {
|
||||
if r.content != record.content
|
||||
|| r.proxied != record.proxied
|
||||
|| r.comment != record.comment
|
||||
{
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
@@ -1249,7 +1263,7 @@ mod tests {
|
||||
assert!(ok, "skip on detection failure should not be an error");
|
||||
}
|
||||
|
||||
/// A definitive "no address of this family" (e.g. provider `none`) with
|
||||
/// A definitive "no address of this family" (e.g., provider `none`) with
|
||||
/// delete_on_failure enabled deletes the managed records (documented behavior).
|
||||
#[tokio::test]
|
||||
async fn test_update_once_no_ip_deletes_records_with_delete_on_failure() {
|
||||
@@ -1595,7 +1609,7 @@ mod tests {
|
||||
assert!(ok);
|
||||
}
|
||||
|
||||
/// update_once with WAF lists: IPs are detected and WAF list is updated.
|
||||
/// update_once with WAF lists: IPs are detected and the WAF list is updated.
|
||||
#[tokio::test]
|
||||
async fn test_update_once_with_waf_list() {
|
||||
let server = MockServer::start().await;
|
||||
@@ -2001,7 +2015,7 @@ mod tests {
|
||||
final_delete(&config, &cf, ¬ifier, &heartbeat, &ppfmt).await;
|
||||
}
|
||||
|
||||
/// final_delete skips DNS deletion when zone is not found.
|
||||
/// final_delete skips DNS deletion when the zone is not found.
|
||||
#[tokio::test]
|
||||
async fn test_final_delete_skips_when_zone_not_found() {
|
||||
let server = MockServer::start().await;
|
||||
@@ -2239,7 +2253,7 @@ mod tests {
|
||||
let server = MockServer::start().await;
|
||||
let zone_id = "zone-abc";
|
||||
let domain_v6 = "v6only.example.com";
|
||||
// Only a V4 literal provider is configured but domain is V6
|
||||
// Only a V4 literal provider is configured, but domain is V6
|
||||
let ip_v4 = "198.51.100.1";
|
||||
|
||||
// Zone lookup for V6 domain
|
||||
@@ -2494,7 +2508,7 @@ mod tests {
|
||||
subdomains: vec![LegacySubdomainEntry::Simple("@".to_string())],
|
||||
proxied: false,
|
||||
}];
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new())
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new(), None)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -2551,7 +2565,7 @@ mod tests {
|
||||
subdomains: vec![LegacySubdomainEntry::Simple("@".to_string())],
|
||||
proxied: false,
|
||||
}];
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new())
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new(), None)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -2595,7 +2609,7 @@ mod tests {
|
||||
proxied: false,
|
||||
}];
|
||||
// Should not POST
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new())
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new(), None)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -2649,7 +2663,7 @@ mod tests {
|
||||
}],
|
||||
proxied: false,
|
||||
}];
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new())
|
||||
ddns.commit_record(&ip, &config, 300, false, &mut HashSet::new(), None)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -2702,7 +2716,7 @@ mod tests {
|
||||
subdomains: vec![LegacySubdomainEntry::Simple("@".to_string())],
|
||||
proxied: false,
|
||||
}];
|
||||
ddns.commit_record(&ip, &config, 300, true, &mut HashSet::new())
|
||||
ddns.commit_record(&ip, &config, 300, true, &mut HashSet::new(), None)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -2756,7 +2770,7 @@ mod tests {
|
||||
subdomains: vec![LegacySubdomainEntry::Simple("@".to_string())],
|
||||
proxied: false,
|
||||
}];
|
||||
ddns.update_ips(&ips, &config, 300, false, &mut HashSet::new())
|
||||
ddns.update_ips(&ips, &config, 300, false, &mut HashSet::new(), None)
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -3098,6 +3112,75 @@ mod tests {
|
||||
.await;
|
||||
assert!(ok, "Should succeed with both detections");
|
||||
}
|
||||
|
||||
/// update_once passes record_comment to the API when creating a new record.
|
||||
#[tokio::test]
|
||||
async fn test_update_once_with_record_comment() {
|
||||
let server = MockServer::start().await;
|
||||
let zone_id = "zone-abc";
|
||||
let domain = "home.example.com";
|
||||
let ip = "198.51.100.42";
|
||||
let comment = "managed by cf-ddns";
|
||||
|
||||
// Zone lookup
|
||||
Mock::given(method("GET"))
|
||||
.and(path("/zones"))
|
||||
.and(query_param("name", domain))
|
||||
.respond_with(
|
||||
ResponseTemplate::new(200).set_body_json(zones_response(zone_id, "example.com")),
|
||||
)
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
// List existing records (empty)
|
||||
Mock::given(method("GET"))
|
||||
.and(path_regex(format!("/zones/{zone_id}/dns_records")))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(dns_records_empty()))
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
// Create record: POST should receive the comment in the body
|
||||
Mock::given(method("POST"))
|
||||
.and(path(format!("/zones/{zone_id}/dns_records")))
|
||||
.respond_with(
|
||||
ResponseTemplate::new(200).set_body_json(dns_record_created("rec-1", domain, ip)),
|
||||
)
|
||||
.expect(1)
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
let mut providers = HashMap::new();
|
||||
providers.insert(
|
||||
IpType::V4,
|
||||
ProviderType::Literal {
|
||||
ips: vec![ip.parse::<IpAddr>().unwrap()],
|
||||
},
|
||||
);
|
||||
let mut domains = HashMap::new();
|
||||
domains.insert(IpType::V4, vec![domain.to_string()]);
|
||||
|
||||
let mut config = make_config(providers, domains, vec![], false);
|
||||
config.record_comment = Some(comment.to_string());
|
||||
|
||||
let cf = handle(&server.uri());
|
||||
let notifier = empty_notifier();
|
||||
let heartbeat = empty_heartbeat();
|
||||
let ppfmt = pp();
|
||||
|
||||
let mut cf_cache = CachedCloudflareFilter::new();
|
||||
let ok = update_once(
|
||||
&config,
|
||||
&cf,
|
||||
¬ifier,
|
||||
&heartbeat,
|
||||
&mut cf_cache,
|
||||
&ppfmt,
|
||||
&mut HashSet::new(),
|
||||
&crate::test_client(),
|
||||
)
|
||||
.await;
|
||||
assert!(ok, "Should succeed with record_comment set");
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy types for backwards compatibility
|
||||
@@ -3117,6 +3200,8 @@ struct LegacyDnsRecord {
|
||||
name: String,
|
||||
content: String,
|
||||
proxied: bool,
|
||||
#[serde(default)]
|
||||
comment: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
@@ -3127,4 +3212,6 @@ struct LegacyDnsRecordPayload {
|
||||
content: String,
|
||||
proxied: bool,
|
||||
ttl: i64,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
comment: Option<String>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user