dnscontrol/pkg/js/parse_tests
tridion f1b30a1a04
feat: Add IGNORE_EXTERNAL_DNS() for Kubernetes external-dns coexistence (#3869)s
## Summary

This PR adds a new domain modifier `IGNORE_EXTERNAL_DNS()` that
automatically detects and ignores DNS records managed by Kubernetes
[external-dns](https://github.com/kubernetes-sigs/external-dns)
controller.

**Related Issue:** This addresses the feature request discussed in
StackExchange/dnscontrol#935 (Idea: Ownership system), where
@tlimoncelli indicated openness to accepting a PR for this
functionality.

## Problem

When running DNSControl alongside Kubernetes external-dns, users face a
challenge:

- **external-dns** dynamically creates DNS records based on Kubernetes
Ingress/Service resources
- Users cannot use `IGNORE()` because they cannot predict which record
names external-dns will create
- Using `NO_PURGE()` is too broad - it prevents DNSControl from cleaning
up any orphaned records

The fundamental issue is that `IGNORE()` requires static patterns known
at config-time, but external-dns creates records dynamically at runtime.

## Solution

`IGNORE_EXTERNAL_DNS()` solves this by detecting external-dns managed
records at runtime:

```javascript
D("example.com", REG_CHANGEME, DnsProvider(DSP_MY_PROVIDER),
    IGNORE_EXTERNAL_DNS(),  // Automatically ignore external-dns managed records
    A("@", "1.2.3.4"),
    CNAME("www", "@")
);
```

### How It Works

external-dns uses a TXT record registry to track ownership. For each
managed record, it creates a TXT record like:

- `a-myapp.example.com` → TXT containing
`heritage=external-dns,external-dns/owner=...`
- `cname-api.example.com` → TXT containing
`heritage=external-dns,external-dns/owner=...`

This PR:
1. Scans existing TXT records for the `heritage=external-dns` marker
2. Parses the TXT record name prefix (e.g., `a-`, `cname-`) to determine
the managed record type
3. Automatically adds those records to the ignore list during diff
operations

## Changes

| File | Purpose |
|------|---------|
| `models/domain.go` | Add `IgnoreExternalDNS` field to DomainConfig |
| `pkg/js/helpers.js` | Add `IGNORE_EXTERNAL_DNS()` JavaScript helper |
| `pkg/diff2/externaldns.go` | Core detection logic for external-dns TXT
records |
| `pkg/diff2/externaldns_test.go` | Unit tests for detection logic |
| `pkg/diff2/handsoff.go` | Integrate external-dns detection into
handsoff() |
| `pkg/diff2/diff2.go` | Pass IgnoreExternalDNS flag to handsoff() |
| `commands/types/dnscontrol.d.ts` | TypeScript definitions for IDE
support |
| `documentation/.../IGNORE_EXTERNAL_DNS.md` | User documentation |

## Design Philosophy

This follows DNSControl's pattern of convenience builders (like
`M365_BUILDER`, `SPF_BUILDER`, `DKIM_BUILDER`) that make complex
operations simple. Just as those builders abstract away implementation
details, `IGNORE_EXTERNAL_DNS()` abstracts away the complexity of
detecting external-dns managed records.

## Testing

All unit tests pass:
```
go test ./pkg/diff2/... -v  # Tests detection logic
go test ./pkg/js/...        # Tests JS helpers
go build ./...              # Builds successfully
```

## Caveats Documented

- Only supports TXT registry (the default for external-dns)
- Requires external-dns to use default naming conventions
- May need updates if external-dns changes its registry format

---------

Co-authored-by: Tom Limoncelli <6293917+tlimoncelli@users.noreply.github.com>
2025-12-03 08:56:55 -05:00
..
001-basic js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
002-ttl js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
003-meta js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
004-ips js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
006-transforms TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
008-import js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
011-cfRedirect js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
012-duration TESTING: pkg/js/parse_tests: fix a broken test (#1498) 2022-05-03 19:46:48 -04:00
013-mx js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
014-caa js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
015-tlsa NEW PROVIDER: AkamaiEdgeDNS (#1174) 2021-06-22 10:24:49 -04:00
017-txt REFACTOR: Opinion: TXT records are one long string (#2631) 2023-12-04 17:45:25 -05:00
018-dkim REFACTOR: Opinion: TXT records are one long string (#2631) 2023-12-04 17:45:25 -05:00
020-complexRequire js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
021-srv js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
022-sshfp js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
023-ignored-glob-records js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
024-json-import js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
027-ds js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
028-dextend js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
029-dextendsub BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
030-dextenddoc js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
031-dextendnames js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
032-reverseip js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
033-revextend js_test.go should generate & test zonefile output too (#986) 2020-12-03 09:33:39 -05:00
035-naptr Improve MSDNS naptr support (#1165) 2021-06-24 18:26:21 -04:00
036-dextendcf CLOUDFLAREAPI: Adds CF_WORKER_ROUTE (#1243) 2021-10-11 16:04:49 -04:00
037-splithor Improve tagged domain handling in support of Split Horizon feature (#3444) 2025-02-25 12:27:24 -05:00
038-soa Direct SOA record management (#1115) 2021-05-04 15:47:26 -04:00
040-cfWorkerRoute CLOUDFLAREAPI: Adds CF_WORKER_ROUTE (#1243) 2021-10-11 16:04:49 -04:00
045-loc LOC: fix float altitude value ingestion, gate size and precision values (#3130) 2024-09-27 12:06:19 -04:00
054-b3487_d_extend_rev bug(rev) D_EXTEND does not work with REV (#3488) 2025-03-21 12:39:23 -04:00
055-b3550-ipv6ptr BUGFIX: REV fails in D_EXTEND for IPv6 addresses (#3552) 2025-05-03 08:20:44 -04:00
complexImports TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
001-basic.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
001-basic.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
002-ttl.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
002-ttl.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
003-meta.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
003-meta.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
004-ips.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
004-ips.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
005-ignored-records.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
005-ignored-records.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
006-transforms.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
006-transforms.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
007-importTransformTTL.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
007-importTransformTTL.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
008-import.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
008-import.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
009-reverse.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
009-reverse.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
010-alias.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
010-alias.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
011-cfRedirect.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
011-cfRedirect.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
012-duration.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
012-duration.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
013-mx.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
013-mx.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
014-caa.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
014-caa.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
015-tlsa.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
015-tlsa.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
017-txt.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
017-txt.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
018-dkim.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
018-dkim.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
019-r53-alias.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
019-r53-alias.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
020-complexRequire.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
020-complexRequire.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
021-srv.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
021-srv.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
022-sshfp.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
022-sshfp.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
023-ignored-glob-records.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
023-ignored-glob-records.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
024-json-import.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
024-json-import.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
025-autodnssec.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
025-autodnssec.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
026-azure-alias.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
026-azure-alias.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
027-ds.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
027-ds.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
028-dextend.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
028-dextend.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
029-dextendsub.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
029-dextendsub.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
030-dextenddoc.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
030-dextenddoc.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
031-dextendnames.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
031-dextendnames.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
032-reverseip.js bug(rev) D_EXTEND does not work with REV (#3488) 2025-03-21 12:39:23 -04:00
032-reverseip.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
033-revextend.js bug(rev) D_EXTEND does not work with REV (#3488) 2025-03-21 12:39:23 -04:00
033-revextend.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
034-nameserver-ttl.js MAINT: Fix parse_test numbering (#985) 2020-12-01 11:22:12 -05:00
034-nameserver-ttl.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
035-naptr.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
035-naptr.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
036-dextendcf.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
036-dextendcf.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
037-splithor.js Improve tagged domain handling in support of Split Horizon feature (#3444) 2025-02-25 12:27:24 -05:00
037-splithor.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
038-soa.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
038-soa.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
039-include.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
039-include.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
040-cfWorkerRoute.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
040-cfWorkerRoute.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
040-r53-zone.js Add R53_ZONE as an domain identifier (#1241) 2021-09-02 16:54:54 -04:00
040-r53-zone.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
041-newstyleproviders.js NEW FEATURE: Moving provider TYPE from dnsconfig.js to creds.json (#1500) 2022-05-08 14:23:45 -04:00
041-newstyleproviders.json CICD: json files should be strictly formatted (#3282) 2025-01-01 12:02:23 -05:00
043-safety.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
043-safety.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
044-ensureabsent.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
044-ensureabsent.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
045-loc.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
045-loc.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
046-DHCID.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
046-DHCID.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
047-DNAME.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
047-DNAME.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
047-SVCB.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
047-SVCB.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
048-DNSKEY.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
048-DNSKEY.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
049-json5-require.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
049-json5-require.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
050-cfSingleRedirect.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
050-cfSingleRedirect.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
051-HASH.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00
051-HASH.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
054-b3487_d_extend_rev.js bug(rev) D_EXTEND does not work with REV (#3488) 2025-03-21 12:39:23 -04:00
054-b3487_d_extend_rev.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
055-b3550-ipv6ptr.js BUGFIX: REV fails in D_EXTEND for IPv6 addresses (#3552) 2025-05-03 08:20:44 -04:00
055-b3550-ipv6ptr.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
056-openpgpkey.js NEW RECORD TYPE: OPENPGPKEY (basic) (#3718) 2025-08-11 10:44:12 -04:00
056-openpgpkey.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
057-smimea.js NEW FEATURE: Add SMIMEA support for BIND and deSEC (#3786) 2025-10-10 11:16:13 -04:00
057-smimea.json BUGFIX: IDN support is broken for domain names (#3845) 2025-11-29 12:17:44 -05:00
058-ignore-external-dns.js feat: Add IGNORE_EXTERNAL_DNS() for Kubernetes external-dns coexistence (#3869)s 2025-12-03 08:56:55 -05:00
058-ignore-external-dns.json feat: Add IGNORE_EXTERNAL_DNS() for Kubernetes external-dns coexistence (#3869)s 2025-12-03 08:56:55 -05:00
domain-ip-map.json CICD: json files should be strictly formatted (#3282) 2025-01-01 12:02:23 -05:00
domain-ip-map.json5 FEATURE: Enable "require()" function to accept json5 files (#3003) 2024-06-11 15:27:11 -04:00
import.js TESTING: parse_tests: reformat/regenerate .js .json files 2025-01-03 13:19:39 -05:00