Skip to content

fix: resolve DNS record churning caused by Records/AdjustEndpoints - #30

Merged
cardoe merged 2 commits into
mainfrom
fix/dns-churning-trailing-dot-srv
Apr 24, 2026
Merged

cardoe merged 2 commits into
mainfrom
fix/dns-churning-trailing-dot-srv

Conversation

@dusto

@dusto dusto commented Apr 22, 2026 •

Copy link
Copy Markdown
Contributor

AdjustEndpoints was adding trailing dots to DNS names, normalizing TTL
from 0 to 300, and stripping quotes from TXT targets. These
transformations created mismatches between what Records() returned and
what external-dns expected, causing every record to be updated on every
sync cycle. Per the external-dns webhook contract, AdjustEndpoints
should be a pass-through unless provider-specific canonicalization is
needed.

Additionally, Records() returned one endpoint per Rackspace record, but
external-dns expects one endpoint per name+type with all targets merged.

Changes:

  • Make AdjustEndpoints a pass-through (matches BaseProvider default)
  • Merge records with same name+type into single multi-target endpoints
  • Reassemble SRV priority into the target string (Rackspace stores it
    as a separate API field)
  • Skip JSON unmarshal on non-JSON TXT record comments
  • Add request logging to all webhook handlers

…smatch

Records() returned DNS names without trailing dots and SRV targets without
the priority field, while AdjustEndpoints() canonicalized names with trailing
dots and external-dns expected 4-part SRV targets. This mismatch caused
external-dns to detect "changes" on every sync cycle, resulting in constant
create/update/delete API churn.

Changes:
- Add trailing dot to DNSName in convertRecordToEndpoint to match
  AdjustEndpoints canonicalization
- Reassemble SRV priority (stored as separate API field by Rackspace)
  into the "priority weight port target" format external-dns expects
- Add table-driven tests for trailing dot, SRV format, NS/SOA filtering,
  TXT label parsing, domain filtering, dry run, and Records/AdjustEndpoints
  idempotency

@skrobul skrobul left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

AdjustEndpoints was adding trailing dots to DNS names, normalizing TTL
from 0 to 300, and stripping quotes from TXT targets. These
transformations created mismatches between what Records() returned and
what external-dns expected, causing every record to be updated on every
sync cycle. Per the external-dns webhook contract, AdjustEndpoints
should be a pass-through unless provider-specific canonicalization is
needed.

Additionally, Records() returned one endpoint per Rackspace record, but
external-dns expects one endpoint per name+type with all targets merged.

Changes:
- Make AdjustEndpoints a pass-through (matches BaseProvider default)
- Merge records with same name+type into single multi-target endpoints
- Reassemble SRV priority into the target string (Rackspace stores it
  as a separate API field)
- Skip JSON unmarshal on non-JSON TXT record comments
- Add request logging to all webhook handlers
@cardoe
cardoe merged commit 8dbf384 into main Apr 24, 2026
5 checks passed
@cardoe
cardoe deleted the fix/dns-churning-trailing-dot-srv branch April 24, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants