22 Commits

Author SHA1 Message Date
dependabot[bot]
5f2b543b75 Bump reqwest from 0.13.4 to 0.13.5
Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.13.4 to 0.13.5.
- [Release notes](https://github.com/seanmonstar/reqwest/releases)
- [Changelog](https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/reqwest/compare/v0.13.4...v0.13.5)

---
updated-dependencies:
- dependency-name: reqwest
  dependency-version: 0.13.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-14 07:34:37 +00:00
Timothy Miller
7c6d5b43c1 Merge pull request #296 from timothymiller/dependabot/cargo/rustls-0.23.44
Bump rustls from 0.23.43 to 0.23.44
2026-09-12 01:19:44 -04:00
dependabot[bot]
9f4e37f175 Bump rustls from 0.23.43 to 0.23.44
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.43 to 0.23.44.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.43...v/0.23.44)

---
updated-dependencies:
- dependency-name: rustls
  dependency-version: 0.23.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-11 07:34:16 +00:00
Timothy Miller
848da5acd1 Merge pull request #295 from timothymiller/dependabot/github_actions/docker/login-action-4.6.0
Bump docker/login-action from 4.5.2 to 4.6.0
2026-09-04 06:00:07 -04:00
dependabot[bot]
5289d2067e Bump docker/login-action from 4.5.2 to 4.6.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.5.2 to 4.6.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v4.5.2...v4.6.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-03 07:32:54 +00:00
Timothy Miller
6d7e4d644e Merge pull request #291 from timothymiller/dependabot/github_actions/docker/login-action-4.5.2
Bump docker/login-action from 4 to 4.5.2
2026-09-02 19:06:49 -04:00
Timothy Miller
1faef32f1e Merge pull request #290 from timothymiller/dependabot/cargo/rustls-0.23.43
Bump rustls from 0.23.42 to 0.23.43
2026-09-02 19:06:38 -04:00
Timothy Miller
ee46eb9c4c Merge pull request #289 from cliffordwhansen/comment_support_legacy_config
Comment support legacy config
2026-09-02 19:06:28 -04:00
Clifford W. Hansen
da4b20e252 Added .idea to .gitignore 2026-08-18 11:29:35 +02:00
Clifford W. Hansen
3307adaede Add support for record_comment in configuration, deserialization, and API integration. 2026-08-18 11:29:35 +02:00
dependabot[bot]
65f5629157 Bump docker/login-action from 4 to 4.5.2
Bumps [docker/login-action](https://github.com/docker/login-action) from 4 to 4.5.2.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v4...v4.5.2)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.5.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-31 07:32:53 +00:00
dependabot[bot]
da3b90ff93 Bump rustls from 0.23.42 to 0.23.43
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.42 to 0.23.43.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.42...v/0.23.43)

---
updated-dependencies:
- dependency-name: rustls
  dependency-version: 0.23.43
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-30 07:33:24 +00:00
Timothy Miller
4ef6ba1b74 Merge pull request #288 from timothymiller/dependabot/cargo/serde-1.0.229
Bump serde from 1.0.228 to 1.0.229
2026-07-22 14:31:07 -04:00
Timothy Miller
4cf7987f73 Merge pull request #287 from timothymiller/dependabot/cargo/tokio-1.53.1
Bump tokio from 1.52.4 to 1.53.1
2026-07-22 14:30:57 -04:00
Timothy Miller
70a562b734 Merge pull request #286 from timothymiller/dependabot/cargo/serde_json-1.0.151
Bump serde_json from 1.0.150 to 1.0.151
2026-07-22 14:30:48 -04:00
Timothy Miller
4c4a5e544a Merge pull request #285 from timothymiller/dependabot/github_actions/azure/setup-helm-5
Bump azure/setup-helm from 4 to 5
2026-07-22 14:30:39 -04:00
Timothy Miller
9a3c86c9bc Merge pull request #284 from timothymiller/dependabot/github_actions/actions/checkout-7
Bump actions/checkout from 4 to 7
2026-07-22 14:30:29 -04:00
dependabot[bot]
7ea89cd973 Bump serde from 1.0.228 to 1.0.229
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.228 to 1.0.229.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.228...v1.0.229)

---
updated-dependencies:
- dependency-name: serde
  dependency-version: 1.0.229
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 07:33:59 +00:00
dependabot[bot]
a59d787e89 Bump tokio from 1.52.4 to 1.53.1
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.52.4 to 1.53.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.52.4...tokio-1.53.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.53.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 07:33:51 +00:00
dependabot[bot]
f0be440d00 Bump serde_json from 1.0.150 to 1.0.151
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.150 to 1.0.151.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.150...v1.0.151)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-version: 1.0.151
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 07:33:42 +00:00
dependabot[bot]
e3678c6e24 Bump azure/setup-helm from 4 to 5
Bumps [azure/setup-helm](https://github.com/azure/setup-helm) from 4 to 5.
- [Release notes](https://github.com/azure/setup-helm/releases)
- [Changelog](https://github.com/Azure/setup-helm/blob/main/CHANGELOG.md)
- [Commits](https://github.com/azure/setup-helm/compare/v4...v5)

---
updated-dependencies:
- dependency-name: azure/setup-helm
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 07:32:50 +00:00
dependabot[bot]
8e79fc8798 Bump actions/checkout from 4 to 7
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 07:32:48 +00:00
7 changed files with 206 additions and 50 deletions

View File

@@ -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

View File

@@ -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.6.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

3
.gitignore vendored
View File

@@ -8,3 +8,6 @@ debug/
# Git History
**/.history/*
# JetBrains IDE
.idea/

83
Cargo.lock generated
View File

@@ -39,6 +39,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
[[package]]
name = "bitflags"
version = "2.11.0"
@@ -168,7 +174,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
]
[[package]]
@@ -276,7 +282,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
]
[[package]]
@@ -469,7 +475,7 @@ version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
dependencies = [
"base64",
"base64 0.22.1",
"bytes",
"futures-channel",
"futures-util",
@@ -679,7 +685,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
dependencies = [
"quote",
"syn",
"syn 2.0.117",
]
[[package]]
@@ -801,7 +807,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
"syn 2.0.117",
]
[[package]]
@@ -882,11 +888,11 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "reqwest"
version = "0.13.4"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029"
dependencies = [
"base64",
"base64 0.23.1",
"bytes",
"futures-core",
"http",
@@ -946,9 +952,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.42"
version = "0.23.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138"
checksum = "6725596c3f2c3a0aef021139e145d4eafe314a6623e4680ca83852b2c67ab2ba"
dependencies = [
"once_cell",
"ring",
@@ -1008,9 +1014,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
version = "0.103.13"
version = "0.103.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
dependencies = [
"ring",
"rustls-pki-types",
@@ -1078,9 +1084,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 +1094,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 +1198,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 +1226,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
]
[[package]]
@@ -1242,7 +1259,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
]
[[package]]
@@ -1257,9 +1274,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 +1296,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
]
[[package]]
@@ -1500,7 +1517,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
"wasm-bindgen-shared",
]
@@ -1736,7 +1753,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031"
dependencies = [
"assert-json-diff",
"base64",
"base64 0.22.1",
"deadpool",
"futures",
"http",
@@ -1782,7 +1799,7 @@ dependencies = [
"heck",
"indexmap",
"prettyplease",
"syn",
"syn 2.0.117",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
@@ -1798,7 +1815,7 @@ dependencies = [
"prettyplease",
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
"wit-bindgen-core",
"wit-bindgen-rust",
]
@@ -1865,7 +1882,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
"synstructure",
]
@@ -1886,7 +1903,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
"synstructure",
]
@@ -1926,7 +1943,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.117",
]
[[package]]

View File

@@ -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#"{

View File

@@ -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(

View File

@@ -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, &notifier, &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,
&notifier,
&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>,
}