Commit graph

57 commits

Author SHA1 Message Date
Tom Limoncelli
703084160f
REFACTOR: BIND/GANDI_V5 add "RP" record type, rewrite CLOUDFLAREAPI CF_* and more (#3886)
# Issue

* New record type: "RP" (supported by BIND and GANDI_V5) 
* Cloudflare: CF_REDIRECT/CF_TEMP_REDIRECT now generate
CF_SINGLE_REDIRECT records. All PAGE_RULE-based code is removed.
PAGE_RULEs are deprecated at Cloudflare. (be careful when upgrading!)
* New "v2" RecordConfig: RP and CF_SINGLE_REDIRECT are the only record
types that use this method. It shifts most of the work out of JavaScript
and into the Go code, making new record types easier to make, easier to
test, and easier to use by providers. This opens the door to new things
like a potential code-generator for rtypes. Converting existing rtypes
will happen over the next year.
* When only the TTL changes (MODIFY-TTL), the output lists the TTL
change first, not at the end of the line where it is visually lost.
* CF_REDIRECT/CF_TEMP_REDIRECT generate different rule "names". They
will be updated the first time you "push" with this release. The order
of the rules may also change. If you rules depend on a particular order,
be very careful with this upgrade!

Refactoring:

* New "v2" RecordConfig: Record types using this new method simply
package the parameters from dnsconfig.js statements like
CF_REDIRECT(foo,bar) and send them (raw) to the Go code. The Go code
does all processing, validation, etc. and turns them into RecordConfig
that store all the rdata in `RecordConfig.F`. No more adding fields to
RecordConfig for each new record type!
* RecordConfig.IsModernType() returns true if the record uses the new v2
record mechanism.
* PostProcess is now a method on DnsConfig and DomainConfig.
* DOC: How to create new rtypes using the v2 method (incomplete)

Other things:

* Integration tests for CF "full proxy" are removed. This feature
doesn't exist any more.
* DEV: Debugger tips now includes VSCode advice
* TESTING: The names of testgroup's can now have extra spaces to make
data align better
* CF_TEMP_REDIRECT/CF_REDIRECT is now a "builder" that generates
CLOUDFLAREAPI_SINGLE_REDIRECT records.
* And more!

# Resolution

---------

Co-authored-by: Jakob Ackermann <das7pad@outlook.com>
2025-12-04 16:42:20 -05:00
Tom Limoncelli
7dc81bb4b1
CHORE: FIx lint in diff2 (#3885) 2025-12-04 10:30:19 -05:00
Tom Limoncelli
e87f03a8a3
CHORE: fmt (#3882) 2025-12-03 14:53:02 -05:00
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
Tom Limoncelli
db21e30abb
Update deps (#3790) 2025-10-10 14:16:46 -04:00
James O'Gorman
4ce19352e9
PORKBUN: Improve retry handling, mark as concurrent (#3652) 2025-07-09 12:03:59 -04:00
Max Chernoff
3ea7ea84c9
FEATURE: Support ignoring the ech= parameter in HTTPS/SVCB RR types (#3485) 2025-06-11 11:16:15 -04:00
Tom Limoncelli
5dbe5e84c9
CHORE: Fix lint warnings from golangci-lint (#3311) 2025-01-13 11:33:12 -05:00
Tom Limoncelli
a341022068
BUGFIX: IGNORE() deletes ignored records on ByZone() platforms (#3263) 2024-12-18 20:34:52 -05:00
Tom Limoncelli
06ba3cce77
Bugfix: Providers with batched updates might not report the correct number of changes (#3108) 2024-09-16 12:20:30 -04:00
Tom Limoncelli
2944eded30
TESTING: Fix reversed got/want output in compareconfig_test.go (#3070) 2024-08-05 16:12:20 -04:00
Tom Limoncelli
798c0d6b9e deadcode: Change/ChangeList.String 2024-03-03 15:42:49 -05:00
Tom Limoncelli
80ff814988 deadcode: groupbyRSet 2024-03-03 15:42:49 -05:00
Tom Limoncelli
34d6e079b2 deadcode: groupbyRSet 2024-03-03 15:42:49 -05:00
Tom Limoncelli
ed999b99bd deadcode: justMsgString (move to test) 2024-03-03 15:42:49 -05:00
Tom Limoncelli
0b8bb1d1ba
FEATURE: Add experimental --reportmax flag (#2719) 2023-12-13 12:32:39 -05:00
Tom Limoncelli
790513a170
CHORE: Fix golint and staticcheck errors/warnings (#2717) 2023-12-11 16:24:11 -05:00
Tom Limoncelli
cbccbbeb8d
REFACTOR: Opinion: TXT records are one long string (#2631)
Co-authored-by: Costas Drogos <costas.drogos@gmail.com>
Co-authored-by: imlonghao <git@imlonghao.com>
Co-authored-by: Jeffrey Cafferata <jeffrey@jcid.nl>
Co-authored-by: Vincent Hagen <blackshadev@users.noreply.github.com>
2023-12-04 17:45:25 -05:00
Tom Limoncelli
3dab594757
CHORE: More cleanups (#2632) 2023-11-19 13:44:49 -05:00
Tom Limoncelli
c91fe6c1c8
CHORE: Remove diff1 from codebase (#2575) 2023-10-22 13:56:13 -04:00
Tom Limoncelli
69bf714852
TESTING: handoff() tests should disable NO_PURGE (#2568) 2023-09-26 11:25:57 -04:00
Vincent Hagen
e32bdc053f
NEW FEATURE: Order changes based on the record dependencies (#2419)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-08-29 14:00:09 -04:00
tomf
a7fe17a29c
Display changes, even if upstream has no records. (#2531)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2023-08-24 10:29:27 -04:00
Tom Limoncelli
7fc80ac7cc
CLOUDFLARE: BUGFIX: Proxy=full not handled in diff2 (#2525)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-21 12:19:16 -04:00
Tom Limoncelli
0b7dabacc8
NEW FEATURE: IGNORE() (diff2 only) (#2388)
Co-authored-by: Jeffrey Cafferata <jeffrey@jcid.nl>
2023-05-24 15:14:36 -04:00
nemunaire
5ae231030e
Update version in go.mod (#2382) 2023-05-20 13:21:45 -04:00
Tom Limoncelli
66a76c44c1
Don't count diff2.REPORT (informational warnings) as a "correction" (#2361)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-05-16 10:42:08 -04:00
Tom Limoncelli
0d479b2780
verifyCNAMEAssertions should warn, not panic (#2340)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-05-09 14:29:09 -04:00
Tom Limoncelli
ace2242daf
BUG: diff2 doesn't process IGNORE_TARGET() correctly (#2338)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-05-08 22:29:58 -04:00
Daniil Lemenkov
36e3595612
CHORE: Satisfy Staticcheck and remove unused code (#2331) 2023-05-08 16:49:26 -04:00
Tom Limoncelli
780e17ada9
Linting (#2308)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-05-01 18:40:10 -04:00
Tom Limoncelli
8f4a08a7e6
ROUTE53: Fix "No such DNS type error" on legacy or ignored records (#2294)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-05-01 18:33:29 -04:00
Tom Limoncelli
be8495c5e8
Integration tests should test diff2's IGNORE* (#2292)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-04-23 13:28:18 -05:00
Tom Limoncelli
2a28d81490
MSDNS: be more efficient with ttl changes (#2251)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-03-31 09:08:26 -04:00
Tom Limoncelli
f676c4956e
diff2: Add a "hints" when change is TTL-only (#2249)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-03-29 14:34:10 -04:00
Tom Limoncelli
6ac1961341
TESTING: Disable colorized output during tests (#2248)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-03-29 13:57:49 -04:00
Vincent Hagen
9ffec690f5
TRANSIP: Improve diff2 implementation (#2228)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2023-03-26 12:51:45 -04:00
Tom Limoncelli
edf4c92815
FEATURE: Truncate report of ignored/purged items unless --full (#2203)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-03-20 09:40:28 -04:00
Tom Limoncelli
30646a15f7
CHORE: go generate (#2180) 2023-03-16 09:21:35 -04:00
Tom Limoncelli
81054e72c5
CHORE: linting (#2176) 2023-03-15 18:35:34 -04:00
Tom Limoncelli
2586e2b611
CORE: Clean up diff2 code in prep for production (#2104) 2023-02-28 01:25:09 -05:00
Tom Limoncelli
e129e40313
FEATURE: Colorize diff2 output (#2103) 2023-02-28 01:14:06 -05:00
Tom Limoncelli
05dc26bf2e
BUG: diff2: ttl changes don't always work (#2093) 2023-02-25 22:40:54 -05:00
Jeffrey Cafferata
ab872cc13f
CHORE: Go fmt (#2095)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2023-02-25 22:20:12 -05:00
Tom Limoncelli
fc3a217dc1
Bugfixed: NO_PURGE now works on all diff2 providers (#2084) 2023-02-19 12:33:08 -05:00
Tom Limoncelli
e3dc604247
AZURE_DNS: Convert to use diff2 natively (#2058) 2023-02-07 16:53:49 -05:00
Tom Limoncelli
e1ce6ff34f
CLOUDFLARE: Adopt diff2 (#2040) 2023-02-01 16:18:01 -05:00
Tom Limoncelli
de202531cb
NEW FEATURE: NO_PURGE reports what is not purged (diff2 only) (#2031) 2023-02-01 07:27:00 -05:00
Tom Limoncelli
0051b41720
BUGFIX: CREATE may product empty log messages (ByRecordSet) (#2013) 2023-01-29 13:01:40 -05:00
Tom Limoncelli
8249a4b95b
Linting (#1996) 2023-01-28 11:09:38 -05:00