From 0d56712d17e4302145d32dca955a4f01051093e2 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen <30603252+malpou@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:33:42 +0000 Subject: [PATCH 01/16] feat: add option to use only new format TXT records --- main.go | 2 +- pkg/apis/externaldns/types.go | 2 + registry/txt.go | 25 +++-- registry/txt_test.go | 178 ++++++++++++++++++++++++++++------ 4 files changed, 169 insertions(+), 38 deletions(-) diff --git a/main.go b/main.go index dced351fdb..2931266367 100644 --- a/main.go +++ b/main.go @@ -387,7 +387,7 @@ func main() { case "noop": r, err = registry.NewNoopRegistry(p) case "txt": - r, err = registry.NewTXTRegistry(p, cfg.TXTPrefix, cfg.TXTSuffix, cfg.TXTOwnerID, cfg.TXTCacheInterval, cfg.TXTWildcardReplacement, cfg.ManagedDNSRecordTypes, cfg.ExcludeDNSRecordTypes, cfg.TXTEncryptEnabled, []byte(cfg.TXTEncryptAESKey)) + r, err = registry.NewTXTRegistry(p, cfg.TXTPrefix, cfg.TXTSuffix, cfg.TXTOwnerID, cfg.TXTCacheInterval, cfg.TXTWildcardReplacement, cfg.ManagedDNSRecordTypes, cfg.ExcludeDNSRecordTypes, cfg.TXTEncryptEnabled, []byte(cfg.TXTEncryptAESKey), cfg.TXTNewFormatOnly) case "aws-sd": r, err = registry.NewAWSSDRegistry(p, cfg.TXTOwnerID) default: diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 6cd78ee593..ada0ce1e7d 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -138,6 +138,7 @@ type Config struct { TXTSuffix string TXTEncryptEnabled bool TXTEncryptAESKey string `secure:"yes"` + TXTNewFormatOnly bool Interval time.Duration MinEventSyncInterval time.Duration Once bool @@ -299,6 +300,7 @@ var defaultConfig = &Config{ MinEventSyncInterval: 5 * time.Second, TXTEncryptEnabled: false, TXTEncryptAESKey: "", + TXTNewFormatOnly: false, Interval: time.Minute, Once: false, DryRun: false, diff --git a/registry/txt.go b/registry/txt.go index e594a40f6d..c713c2e840 100644 --- a/registry/txt.go +++ b/registry/txt.go @@ -56,10 +56,19 @@ type TXTRegistry struct { // encrypt text records txtEncryptEnabled bool txtEncryptAESKey []byte + + newFormatOnly bool } -// NewTXTRegistry returns new TXTRegistry object -func NewTXTRegistry(provider provider.Provider, txtPrefix, txtSuffix, ownerID string, cacheInterval time.Duration, txtWildcardReplacement string, managedRecordTypes, excludeRecordTypes []string, txtEncryptEnabled bool, txtEncryptAESKey []byte) (*TXTRegistry, error) { +// NewTXTRegistry returns a new TXTRegistry object. When newFormatOnly is true, it will only +// generate new format TXT records, otherwise it generates both old and new formats for +// backwards compatibility. +func NewTXTRegistry(provider provider.Provider, txtPrefix, txtSuffix, ownerID string, + cacheInterval time.Duration, txtWildcardReplacement string, + managedRecordTypes, excludeRecordTypes []string, + txtEncryptEnabled bool, txtEncryptAESKey []byte, + newFormatOnly bool) (*TXTRegistry, error) { + if ownerID == "" { return nil, errors.New("owner id cannot be empty") } @@ -88,6 +97,7 @@ func NewTXTRegistry(provider provider.Provider, txtPrefix, txtSuffix, ownerID st excludeRecordTypes: excludeRecordTypes, txtEncryptEnabled: txtEncryptEnabled, txtEncryptAESKey: txtEncryptAESKey, + newFormatOnly: newFormatOnly, }, nil } @@ -209,12 +219,14 @@ func (im *TXTRegistry) Records(ctx context.Context) ([]*endpoint.Endpoint, error return endpoints, nil } -// generateTXTRecord generates both "old" and "new" TXT records. -// Once we decide to drop old format we need to drop toTXTName() and rename toNewTXTName +// generateTXTRecord generates TXT records in either both formats (old and new) or new format only, +// depending on the newFormatOnly configuration. The old format is maintained for backwards +// compatibility but can be disabled to reduce the number of DNS records. func (im *TXTRegistry) generateTXTRecord(r *endpoint.Endpoint) []*endpoint.Endpoint { endpoints := make([]*endpoint.Endpoint, 0) - if !im.txtEncryptEnabled && !im.mapper.recordTypeInAffix() && r.RecordType != endpoint.RecordTypeAAAA { + // Create legacy format record by default unless newFormatOnly is true + if !im.newFormatOnly && !im.txtEncryptEnabled && !im.mapper.recordTypeInAffix() && r.RecordType != endpoint.RecordTypeAAAA { // old TXT record format txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true, im.txtEncryptEnabled, im.txtEncryptAESKey)) if txt != nil { @@ -224,7 +236,8 @@ func (im *TXTRegistry) generateTXTRecord(r *endpoint.Endpoint) []*endpoint.Endpo endpoints = append(endpoints, txt) } } - // new TXT record format (containing record type) + + // Always create new format record recordType := r.RecordType // AWS Alias records are encoded as type "cname" if isAlias, found := r.GetProviderSpecificProperty("alias"); found && isAlias == "true" && recordType == endpoint.RecordTypeA { diff --git a/registry/txt_test.go b/registry/txt_test.go index 77ef84262f..cdd190b123 100644 --- a/registry/txt_test.go +++ b/registry/txt_test.go @@ -46,20 +46,20 @@ func TestTXTRegistry(t *testing.T) { func testTXTRegistryNew(t *testing.T) { p := inmemory.NewInMemoryProvider() - _, err := NewTXTRegistry(p, "txt", "", "", time.Hour, "", []string{}, []string{}, false, nil) + _, err := NewTXTRegistry(p, "txt", "", "", time.Hour, "", []string{}, []string{}, false, nil, false) require.Error(t, err) - _, err = NewTXTRegistry(p, "", "txt", "", time.Hour, "", []string{}, []string{}, false, nil) + _, err = NewTXTRegistry(p, "", "txt", "", time.Hour, "", []string{}, []string{}, false, nil, false) require.Error(t, err) - r, err := NewTXTRegistry(p, "txt", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, err := NewTXTRegistry(p, "txt", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) require.NoError(t, err) assert.Equal(t, p, r.provider) - r, err = NewTXTRegistry(p, "", "txt", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, err = NewTXTRegistry(p, "", "txt", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) require.NoError(t, err) - _, err = NewTXTRegistry(p, "txt", "txt", "owner", time.Hour, "", []string{}, []string{}, false, nil) + _, err = NewTXTRegistry(p, "txt", "txt", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) require.Error(t, err) _, ok := r.mapper.(affixNameMapper) @@ -68,16 +68,16 @@ func testTXTRegistryNew(t *testing.T) { assert.Equal(t, p, r.provider) aesKey := []byte(";k&l)nUC/33:{?d{3)54+,AD?]SX%yh^") - _, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + _, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) require.NoError(t, err) - _, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, aesKey) + _, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, aesKey, false) require.NoError(t, err) - _, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, nil) + _, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, nil, false) require.Error(t, err) - r, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, aesKey) + r, err = NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, aesKey, false) require.NoError(t, err) _, ok = r.mapper.(affixNameMapper) @@ -215,13 +215,13 @@ func testTXTRegistryRecordsPrefixed(t *testing.T) { }, } - r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil, false) records, _ := r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) // Ensure prefix is case-insensitive - r, _ = NewTXTRegistry(p, "TxT.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil) + r, _ = NewTXTRegistry(p, "TxT.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil, false) records, _ = r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) @@ -340,13 +340,13 @@ func testTXTRegistryRecordsSuffixed(t *testing.T) { }, } - r, _ := NewTXTRegistry(p, "", "-txt", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "-txt", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) records, _ := r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) // Ensure prefix is case-insensitive - r, _ = NewTXTRegistry(p, "", "-TxT", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ = NewTXTRegistry(p, "", "-TxT", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) records, _ = r.Records(ctx) assert.True(t, testutils.SameEndpointLabels(records, expectedRecords)) @@ -457,7 +457,7 @@ func testTXTRegistryRecordsNoPrefix(t *testing.T) { }, } - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) records, _ := r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) @@ -484,12 +484,12 @@ func testTXTRegistryRecordsPrefixedTemplated(t *testing.T) { }, } - r, _ := NewTXTRegistry(p, "txt-%{record_type}.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "txt-%{record_type}.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil, false) records, _ := r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) - r, _ = NewTXTRegistry(p, "TxT-%{record_type}.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil) + r, _ = NewTXTRegistry(p, "TxT-%{record_type}.", "", "owner", time.Hour, "wc", []string{}, []string{}, false, nil, false) records, _ = r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) @@ -516,12 +516,12 @@ func testTXTRegistryRecordsSuffixedTemplated(t *testing.T) { }, } - r, _ := NewTXTRegistry(p, "", "txt%{record_type}", "owner", time.Hour, "wc", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "txt%{record_type}", "owner", time.Hour, "wc", []string{}, []string{}, false, nil, false) records, _ := r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) - r, _ = NewTXTRegistry(p, "", "TxT%{record_type}", "owner", time.Hour, "wc", []string{}, []string{}, false, nil) + r, _ = NewTXTRegistry(p, "", "TxT%{record_type}", "owner", time.Hour, "wc", []string{}, []string{}, false, nil, false) records, _ = r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) @@ -564,7 +564,7 @@ func testTXTRegistryApplyChangesWithPrefix(t *testing.T) { newEndpointWithOwner("txt.cname-multiple.test-zone.example.org", "\"heritage=external-dns,external-dns/owner=owner\"", endpoint.RecordTypeTXT, "").WithSetIdentifier("test-set-2"), }, }) - r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) changes := &plan.Changes{ Create: []*endpoint.Endpoint{ @@ -653,7 +653,7 @@ func testTXTRegistryApplyChangesWithTemplatedPrefix(t *testing.T) { p.ApplyChanges(ctx, &plan.Changes{ Create: []*endpoint.Endpoint{}, }) - r, _ := NewTXTRegistry(p, "prefix%{record_type}.", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "prefix%{record_type}.", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) changes := &plan.Changes{ Create: []*endpoint.Endpoint{ newEndpointWithOwnerResource("new-record-1.test-zone.example.org", "new-loadbalancer-1.lb.com", endpoint.RecordTypeCNAME, "", "ingress/default/my-ingress"), @@ -696,7 +696,7 @@ func testTXTRegistryApplyChangesWithTemplatedSuffix(t *testing.T) { p.OnApplyChanges = func(ctx context.Context, got *plan.Changes) { assert.Equal(t, ctxEndpoints, ctx.Value(provider.RecordsContextKey)) } - r, _ := NewTXTRegistry(p, "", "-%{record_type}suffix", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "-%{record_type}suffix", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) changes := &plan.Changes{ Create: []*endpoint.Endpoint{ newEndpointWithOwnerResource("new-record-1.test-zone.example.org", "new-loadbalancer-1.lb.com", endpoint.RecordTypeCNAME, "", "ingress/default/my-ingress"), @@ -761,7 +761,7 @@ func testTXTRegistryApplyChangesWithSuffix(t *testing.T) { newEndpointWithOwner("cname-multiple-txt.test-zone.example.org", "\"heritage=external-dns,external-dns/owner=owner\"", endpoint.RecordTypeTXT, "").WithSetIdentifier("test-set-2"), }, }) - r, _ := NewTXTRegistry(p, "", "-txt", "owner", time.Hour, "wildcard", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "-txt", "owner", time.Hour, "wildcard", []string{}, []string{}, false, nil, false) changes := &plan.Changes{ Create: []*endpoint.Endpoint{ @@ -865,7 +865,7 @@ func testTXTRegistryApplyChangesNoPrefix(t *testing.T) { newEndpointWithOwner("cname-foobar.test-zone.example.org", "\"heritage=external-dns,external-dns/owner=owner\"", endpoint.RecordTypeTXT, ""), }, }) - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) changes := &plan.Changes{ Create: []*endpoint.Endpoint{ @@ -1028,7 +1028,7 @@ func testTXTRegistryMissingRecordsNoPrefix(t *testing.T) { }, } - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "wc", []string{endpoint.RecordTypeCNAME, endpoint.RecordTypeA, endpoint.RecordTypeNS}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "wc", []string{endpoint.RecordTypeCNAME, endpoint.RecordTypeA, endpoint.RecordTypeNS}, []string{}, false, nil, false) records, _ := r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) @@ -1138,7 +1138,7 @@ func testTXTRegistryMissingRecordsWithPrefix(t *testing.T) { }, } - r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "wc", []string{endpoint.RecordTypeCNAME, endpoint.RecordTypeA, endpoint.RecordTypeNS, endpoint.RecordTypeTXT}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "wc", []string{endpoint.RecordTypeCNAME, endpoint.RecordTypeA, endpoint.RecordTypeNS, endpoint.RecordTypeTXT}, []string{}, false, nil, false) records, _ := r.Records(ctx) assert.True(t, testutils.SameEndpoints(records, expectedRecords)) @@ -1433,7 +1433,7 @@ func TestNewTXTScheme(t *testing.T) { newEndpointWithOwner("cname-foobar.test-zone.example.org", "\"heritage=external-dns,external-dns/owner=owner\"", endpoint.RecordTypeTXT, ""), }, }) - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) changes := &plan.Changes{ Create: []*endpoint.Endpoint{ @@ -1509,7 +1509,7 @@ func TestGenerateTXT(t *testing.T) { } p := inmemory.NewInMemoryProvider() p.CreateZone(testZone) - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) gotTXT := r.generateTXTRecord(record) assert.Equal(t, expectedTXT, gotTXT) } @@ -1528,7 +1528,7 @@ func TestGenerateTXTForAAAA(t *testing.T) { } p := inmemory.NewInMemoryProvider() p.CreateZone(testZone) - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) gotTXT := r.generateTXTRecord(record) assert.Equal(t, expectedTXT, gotTXT) } @@ -1545,7 +1545,7 @@ func TestFailGenerateTXT(t *testing.T) { expectedTXT := []*endpoint.Endpoint{} p := inmemory.NewInMemoryProvider() p.CreateZone(testZone) - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) gotTXT := r.generateTXTRecord(cnameRecord) assert.Equal(t, expectedTXT, gotTXT) } @@ -1563,7 +1563,7 @@ func TestTXTRegistryApplyChangesEncrypt(t *testing.T) { }, }) - r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "", []string{}, []string{}, true, []byte("12345678901234567890123456789012")) + r, _ := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "", []string{}, []string{}, true, []byte("12345678901234567890123456789012"), false) records, _ := r.Records(ctx) changes := &plan.Changes{ Delete: records, @@ -1609,7 +1609,7 @@ func TestMultiClusterDifferentRecordTypeOwnership(t *testing.T) { }, }) - r, _ := NewTXTRegistry(p, "_owner.", "", "bar", time.Hour, "", []string{}, []string{}, false, nil) + r, _ := NewTXTRegistry(p, "_owner.", "", "bar", time.Hour, "", []string{}, []string{}, false, nil, false) records, _ := r.Records(ctx) // new cluster has same ingress host as other cluster and uses CNAME ingress address @@ -1682,3 +1682,119 @@ func newEndpointWithOwnerResource(dnsName, target, recordType, ownerID, resource e.Labels[endpoint.ResourceLabelKey] = resource return e } + +func TestNewTXTRegistryWithNewFormatOnly(t *testing.T) { + p := inmemory.NewInMemoryProvider() + + r, err := NewTXTRegistry(p, "txt", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false) + require.NoError(t, err) + assert.False(t, r.newFormatOnly) + + r, err = NewTXTRegistry(p, "txt", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, true) + require.NoError(t, err) + assert.True(t, r.newFormatOnly) +} + +func TestGenerateTXTRecordWithNewFormatOnly(t *testing.T) { + p := inmemory.NewInMemoryProvider() + testCases := []struct { + name string + newFormatOnly bool + endpoint *endpoint.Endpoint + expectedRecords int + expectedPrefix string + description string + }{ + { + name: "legacy format enabled - standard record", + newFormatOnly: false, + endpoint: newEndpointWithOwner("foo.test-zone.example.org", "1.2.3.4", endpoint.RecordTypeA, "owner"), + expectedRecords: 2, + expectedPrefix: "a-", + description: "Should generate both old and new format TXT records", + }, + { + name: "new format only - standard record", + newFormatOnly: true, + endpoint: newEndpointWithOwner("foo.test-zone.example.org", "1.2.3.4", endpoint.RecordTypeA, "owner"), + expectedRecords: 1, + expectedPrefix: "a-", + description: "Should only generate new format TXT record", + }, + { + name: "legacy format enabled - AAAA record", + newFormatOnly: false, + endpoint: newEndpointWithOwner("foo.test-zone.example.org", "2001:db8::1", endpoint.RecordTypeAAAA, "owner"), + expectedRecords: 1, + expectedPrefix: "aaaa-", + description: "Should only generate new format for AAAA records regardless of setting", + }, + { + name: "new format only - AAAA record", + newFormatOnly: true, + endpoint: newEndpointWithOwner("foo.test-zone.example.org", "2001:db8::1", endpoint.RecordTypeAAAA, "owner"), + expectedRecords: 1, + expectedPrefix: "aaaa-", + description: "Should only generate new format for AAAA records", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, tc.newFormatOnly) + records := r.generateTXTRecord(tc.endpoint) + + assert.Equal(t, tc.expectedRecords, len(records), tc.description) + + for _, record := range records { + assert.Equal(t, endpoint.RecordTypeTXT, record.RecordType) + } + + if tc.newFormatOnly || tc.endpoint.RecordType == endpoint.RecordTypeAAAA { + hasNewFormat := false + for _, record := range records { + if strings.HasPrefix(record.DNSName, tc.expectedPrefix) { + hasNewFormat = true + break + } + } + assert.True(t, hasNewFormat, + "Should have at least one record with prefix %s when using new format", tc.expectedPrefix) + } + }) + } +} + +func TestApplyChangesWithNewFormatOnly(t *testing.T) { + p := inmemory.NewInMemoryProvider() + p.CreateZone(testZone) + ctx := context.Background() + + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, true) + + changes := &plan.Changes{ + Create: []*endpoint.Endpoint{ + newEndpointWithOwner("new-record.test-zone.example.org", "1.2.3.4", endpoint.RecordTypeA, "owner"), + }, + } + + err := r.ApplyChanges(ctx, changes) + require.NoError(t, err) + + records, err := p.Records(ctx) + require.NoError(t, err) + + var txtRecords []*endpoint.Endpoint + for _, record := range records { + if record.RecordType == endpoint.RecordTypeTXT { + txtRecords = append(txtRecords, record) + } + } + + assert.Equal(t, 1, len(txtRecords), "Should only create one TXT record in new format") + + if len(txtRecords) > 0 { + assert.True(t, strings.HasPrefix(txtRecords[0].DNSName, "a-"), + "TXT record should have 'a-' prefix when using new format only") + } +} From c7154c9a2c60a59ba33efde9a9d0439d868e20ed Mon Sep 17 00:00:00 2001 From: Malthe Poulsen <30603252+malpou@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:02:44 +0000 Subject: [PATCH 02/16] add flag and docs --- docs/registry/txt.md | 18 ++++++++++++++++++ pkg/apis/externaldns/types.go | 1 + 2 files changed, 19 insertions(+) diff --git a/docs/registry/txt.md b/docs/registry/txt.md index c6ea26bfbd..a94d0f6c81 100644 --- a/docs/registry/txt.md +++ b/docs/registry/txt.md @@ -3,6 +3,24 @@ The TXT registry is the default registry. It stores DNS record metadata in TXT records, using the same provider. +## Record Format Options +The TXT registry supports two formats for storing DNS record metadata: +- Legacy format: Creates a TXT record without record type information +- New format: Creates a TXT record with record type information (e.g., 'a-' prefix for A records) + +By default, the TXT registry creates records in both formats for backwards compatibility. You can configure it to use only the new format by using the `--txt-new-format-only` flag. This reduces the number of TXT records created, which can be helpful when working with provider-specific record limits. + +Note: AAAA records always use only the new format regardless of this setting. + +Example: +```sh +# Default behavior - creates both formats +external-dns + +# Only create new format records +external-dns --txt-new-format-only +``` + ## Prefixes and Suffixes In order to avoid having the registry TXT records collide with diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index ada0ce1e7d..6f8625bf02 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -582,6 +582,7 @@ func (cfg *Config) ParseFlags(args []string) error { app.Flag("txt-wildcard-replacement", "When using the TXT registry, a custom string that's used instead of an asterisk for TXT records corresponding to wildcard DNS records (optional)").Default(defaultConfig.TXTWildcardReplacement).StringVar(&cfg.TXTWildcardReplacement) app.Flag("txt-encrypt-enabled", "When using the TXT registry, set if TXT records should be encrypted before stored (default: disabled)").BoolVar(&cfg.TXTEncryptEnabled) app.Flag("txt-encrypt-aes-key", "When using the TXT registry, set TXT record decryption and encryption 32 byte aes key (required when --txt-encrypt=true)").Default(defaultConfig.TXTEncryptAESKey).StringVar(&cfg.TXTEncryptAESKey) + app.Flag("txt-new-format-only", "When using the TXT registry, only use new format records which include record type information (e.g., prefix: 'a-'). Reduces number of TXT records (default: disabled)").Default(defaultConfig.TXTNewFormatOnly).BoolVar(&cfg.TXTNewFormatOnly) app.Flag("dynamodb-region", "When using the DynamoDB registry, the AWS region of the DynamoDB table (optional)").Default(cfg.AWSDynamoDBRegion).StringVar(&cfg.AWSDynamoDBRegion) app.Flag("dynamodb-table", "When using the DynamoDB registry, the name of the DynamoDB table (default: \"external-dns\")").Default(defaultConfig.AWSDynamoDBTable).StringVar(&cfg.AWSDynamoDBTable) From fd9091a723f1f09e4575dd42502defd68472e059 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Sat, 4 Jan 2025 15:39:23 +0100 Subject: [PATCH 03/16] refine documentation on how to use the flag --- docs/flags.md | 1 + docs/registry/txt.md | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/flags.md b/docs/flags.md index bf98d3f517..f5003b0ee5 100644 --- a/docs/flags.md +++ b/docs/flags.md @@ -150,6 +150,7 @@ | `--txt-prefix=""` | When using the TXT registry, a custom string that's prefixed to each ownership DNS record (optional). Could contain record type template like '%{record_type}-prefix-'. Mutual exclusive with txt-suffix! | | `--txt-suffix=""` | When using the TXT registry, a custom string that's suffixed to the host portion of each ownership DNS record (optional). Could contain record type template like '-%{record_type}-suffix'. Mutual exclusive with txt-prefix! | | `--txt-wildcard-replacement=""` | When using the TXT registry, a custom string that's used instead of an asterisk for TXT records corresponding to wildcard DNS records (optional) | +| `--txt-new-format-only` | When using the TXT registry, only create new format records with record type information (default: disabled) | | `--[no-]txt-encrypt-enabled` | When using the TXT registry, set if TXT records should be encrypted before stored (default: disabled) | | `--txt-encrypt-aes-key=""` | When using the TXT registry, set TXT record decryption and encryption 32 byte aes key (required when --txt-encrypt=true) | | `--dynamodb-region=""` | When using the DynamoDB registry, the AWS region of the DynamoDB table (optional) | diff --git a/docs/registry/txt.md b/docs/registry/txt.md index a94d0f6c81..5d63294ed8 100644 --- a/docs/registry/txt.md +++ b/docs/registry/txt.md @@ -10,16 +10,19 @@ The TXT registry supports two formats for storing DNS record metadata: By default, the TXT registry creates records in both formats for backwards compatibility. You can configure it to use only the new format by using the `--txt-new-format-only` flag. This reduces the number of TXT records created, which can be helpful when working with provider-specific record limits. -Note: AAAA records always use only the new format regardless of this setting. +Note: The following record types always use only the new format regardless of this setting: +- AAAA records +- Encrypted TXT records (when using `--txt-encrypt-enabled`) Example: ```sh # Default behavior - creates both formats -external-dns +external-dns --provider=aws --source=ingress --managed-record-types=A,TXT -# Only create new format records -external-dns --txt-new-format-only +# Only create new format records (alongside other required flags) +external-dns --provider=aws --source=ingress --managed-record-types=A,TXT --txt-new-format-only ``` +The `--txt-new-format-only` flag should be used in addition to your existing external-dns configuration flags. It does not implicitly configure TXT record handling - you still need to specify `--managed-record-types=TXT` if you want external-dns to manage TXT records. ## Prefixes and Suffixes From 64a1b4da75a3e7eb4d21e6d8f303730c5dbbaee2 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Sat, 4 Jan 2025 15:44:12 +0100 Subject: [PATCH 04/16] add section regarding manual migration --- docs/registry/txt.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/registry/txt.md b/docs/registry/txt.md index 5d63294ed8..8273cf2a6f 100644 --- a/docs/registry/txt.md +++ b/docs/registry/txt.md @@ -24,6 +24,14 @@ external-dns --provider=aws --source=ingress --managed-record-types=A,TXT --txt- ``` The `--txt-new-format-only` flag should be used in addition to your existing external-dns configuration flags. It does not implicitly configure TXT record handling - you still need to specify `--managed-record-types=TXT` if you want external-dns to manage TXT records. +### Migration to New Format Only +When transitioning from dual-format to new-format-only records: +- Ensure all your `external-dns` instances support the new format +- Enable the `--txt-new-format-only` flag on your external-dns instances +Manually clean up any existing legacy format TXT records from your DNS provider + +Note: `external-dns` will not automatically remove legacy format records when switching to new-format-only mode. You'll need to clean up the old records manually if desired. + ## Prefixes and Suffixes In order to avoid having the registry TXT records collide with From 4c2e124990f8b3a4f5611ddadee67b191a7bce2f Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Sat, 4 Jan 2025 15:53:12 +0100 Subject: [PATCH 05/16] update documentation to be same as in types.go --- docs/flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/flags.md b/docs/flags.md index f5003b0ee5..cbe88921e4 100644 --- a/docs/flags.md +++ b/docs/flags.md @@ -150,7 +150,7 @@ | `--txt-prefix=""` | When using the TXT registry, a custom string that's prefixed to each ownership DNS record (optional). Could contain record type template like '%{record_type}-prefix-'. Mutual exclusive with txt-suffix! | | `--txt-suffix=""` | When using the TXT registry, a custom string that's suffixed to the host portion of each ownership DNS record (optional). Could contain record type template like '-%{record_type}-suffix'. Mutual exclusive with txt-prefix! | | `--txt-wildcard-replacement=""` | When using the TXT registry, a custom string that's used instead of an asterisk for TXT records corresponding to wildcard DNS records (optional) | -| `--txt-new-format-only` | When using the TXT registry, only create new format records with record type information (default: disabled) | +| `--txt-new-format-only` | When using the TXT registry, only use new format records which include record type information (e.g., prefix: 'a-'). Reduces number of TXT records (default: disabled) | | `--[no-]txt-encrypt-enabled` | When using the TXT registry, set if TXT records should be encrypted before stored (default: disabled) | | `--txt-encrypt-aes-key=""` | When using the TXT registry, set TXT record decryption and encryption 32 byte aes key (required when --txt-encrypt=true) | | `--dynamodb-region=""` | When using the DynamoDB registry, the AWS region of the DynamoDB table (optional) | From 438d56574f542aedef32c67d01549faf3174062f Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Sat, 4 Jan 2025 15:53:28 +0100 Subject: [PATCH 06/16] fix compile issue --- pkg/apis/externaldns/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 4c776f56e8..8c162c252e 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -593,7 +593,7 @@ func App(cfg *Config) *kingpin.Application { app.Flag("txt-wildcard-replacement", "When using the TXT registry, a custom string that's used instead of an asterisk for TXT records corresponding to wildcard DNS records (optional)").Default(defaultConfig.TXTWildcardReplacement).StringVar(&cfg.TXTWildcardReplacement) app.Flag("txt-encrypt-enabled", "When using the TXT registry, set if TXT records should be encrypted before stored (default: disabled)").BoolVar(&cfg.TXTEncryptEnabled) app.Flag("txt-encrypt-aes-key", "When using the TXT registry, set TXT record decryption and encryption 32 byte aes key (required when --txt-encrypt=true)").Default(defaultConfig.TXTEncryptAESKey).StringVar(&cfg.TXTEncryptAESKey) - app.Flag("txt-new-format-only", "When using the TXT registry, only use new format records which include record type information (e.g., prefix: 'a-'). Reduces number of TXT records (default: disabled)").Default(defaultConfig.TXTNewFormatOnly).BoolVar(&cfg.TXTNewFormatOnly) + app.Flag("txt-new-format-only", "When using the TXT registry, only use new format records which include record type information (e.g., prefix: 'a-'). Reduces number of TXT records (default: disabled)").BoolVar(&cfg.TXTNewFormatOnly) app.Flag("dynamodb-region", "When using the DynamoDB registry, the AWS region of the DynamoDB table (optional)").Default(cfg.AWSDynamoDBRegion).StringVar(&cfg.AWSDynamoDBRegion) app.Flag("dynamodb-table", "When using the DynamoDB registry, the name of the DynamoDB table (default: \"external-dns\")").Default(defaultConfig.AWSDynamoDBTable).StringVar(&cfg.AWSDynamoDBTable) From 893702695e9e00143f00168914711bc85a840326 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Sat, 4 Jan 2025 15:54:06 +0100 Subject: [PATCH 07/16] add tests for new flag --- pkg/apis/externaldns/types_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/apis/externaldns/types_test.go b/pkg/apis/externaldns/types_test.go index ab77cc9ec8..a372f6a387 100644 --- a/pkg/apis/externaldns/types_test.go +++ b/pkg/apis/externaldns/types_test.go @@ -75,7 +75,7 @@ var ( AzureSubscriptionID: "", CloudflareProxied: false, CloudflareDNSRecordsPerPage: 100, - CloudflareRegionKey: "", + CloudflareRegionKey: "", CoreDNSPrefix: "/skydns/", AkamaiServiceConsumerDomain: "", AkamaiClientToken: "", @@ -97,6 +97,7 @@ var ( TXTOwnerID: "default", TXTPrefix: "", TXTCacheInterval: 0, + TXTNewFormatOnly: false, Interval: time.Minute, MinEventSyncInterval: 5 * time.Second, Once: false, @@ -176,7 +177,7 @@ var ( AzureSubscriptionID: "arg", CloudflareProxied: true, CloudflareDNSRecordsPerPage: 5000, - CloudflareRegionKey: "us", + CloudflareRegionKey: "us", CoreDNSPrefix: "/coredns/", AkamaiServiceConsumerDomain: "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net", AkamaiClientToken: "o184671d5307a388180fbf7f11dbdf46", @@ -202,6 +203,7 @@ var ( TXTOwnerID: "owner-1", TXTPrefix: "associated-txt-record", TXTCacheInterval: 12 * time.Hour, + TXTNewFormatOnly: true, Interval: 10 * time.Minute, MinEventSyncInterval: 50 * time.Second, Once: true, @@ -338,6 +340,7 @@ func TestParseFlags(t *testing.T) { "--txt-owner-id=owner-1", "--txt-prefix=associated-txt-record", "--txt-cache-interval=12h", + "--txt-new-format-only", "--dynamodb-table=custom-table", "--interval=10m", "--min-event-sync-interval=50s", @@ -399,7 +402,7 @@ func TestParseFlags(t *testing.T) { "EXTERNAL_DNS_AZURE_SUBSCRIPTION_ID": "arg", "EXTERNAL_DNS_CLOUDFLARE_PROXIED": "1", "EXTERNAL_DNS_CLOUDFLARE_DNS_RECORDS_PER_PAGE": "5000", - "EXTERNAL_DNS_CLOUDFLARE_REGION_KEY": "us", + "EXTERNAL_DNS_CLOUDFLARE_REGION_KEY": "us", "EXTERNAL_DNS_COREDNS_PREFIX": "/coredns/", "EXTERNAL_DNS_AKAMAI_SERVICECONSUMERDOMAIN": "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net", "EXTERNAL_DNS_AKAMAI_CLIENT_TOKEN": "o184671d5307a388180fbf7f11dbdf46", @@ -451,6 +454,7 @@ func TestParseFlags(t *testing.T) { "EXTERNAL_DNS_TXT_OWNER_ID": "owner-1", "EXTERNAL_DNS_TXT_PREFIX": "associated-txt-record", "EXTERNAL_DNS_TXT_CACHE_INTERVAL": "12h", + "EXTERNAL_DNS_TXT_NEW_FORMAT_ONLY": "1", "EXTERNAL_DNS_INTERVAL": "10m", "EXTERNAL_DNS_MIN_EVENT_SYNC_INTERVAL": "50s", "EXTERNAL_DNS_ONCE": "1", From ab3dfe6f4ee0f2e36fbf0951b63f26b3ed5aeac5 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Sat, 4 Jan 2025 16:06:10 +0100 Subject: [PATCH 08/16] update flags documentation correctly --- docs/flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/flags.md b/docs/flags.md index cbe88921e4..04a205faa5 100644 --- a/docs/flags.md +++ b/docs/flags.md @@ -150,9 +150,9 @@ | `--txt-prefix=""` | When using the TXT registry, a custom string that's prefixed to each ownership DNS record (optional). Could contain record type template like '%{record_type}-prefix-'. Mutual exclusive with txt-suffix! | | `--txt-suffix=""` | When using the TXT registry, a custom string that's suffixed to the host portion of each ownership DNS record (optional). Could contain record type template like '-%{record_type}-suffix'. Mutual exclusive with txt-prefix! | | `--txt-wildcard-replacement=""` | When using the TXT registry, a custom string that's used instead of an asterisk for TXT records corresponding to wildcard DNS records (optional) | -| `--txt-new-format-only` | When using the TXT registry, only use new format records which include record type information (e.g., prefix: 'a-'). Reduces number of TXT records (default: disabled) | | `--[no-]txt-encrypt-enabled` | When using the TXT registry, set if TXT records should be encrypted before stored (default: disabled) | | `--txt-encrypt-aes-key=""` | When using the TXT registry, set TXT record decryption and encryption 32 byte aes key (required when --txt-encrypt=true) | +| `--[no-]txt-new-format-only` | When using the TXT registry, only use new format records which include record type information (e.g., prefix: 'a-'). Reduces number of TXT records (default: disabled) | | `--dynamodb-region=""` | When using the DynamoDB registry, the AWS region of the DynamoDB table (optional) | | `--dynamodb-table="external-dns"` | When using the DynamoDB registry, the name of the DynamoDB table (default: "external-dns") | | `--txt-cache-interval=0s` | The interval between cache synchronizations in duration format (default: disabled) | From 299d087917ead3d306d163bd1c67e710cd35f398 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Fri, 10 Jan 2025 16:44:21 +0100 Subject: [PATCH 09/16] add new option to helm chart --- charts/external-dns/templates/deployment.yaml | 3 +++ charts/external-dns/values.yaml | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/charts/external-dns/templates/deployment.yaml b/charts/external-dns/templates/deployment.yaml index 46a41de4fa..03d298989a 100644 --- a/charts/external-dns/templates/deployment.yaml +++ b/charts/external-dns/templates/deployment.yaml @@ -106,6 +106,9 @@ spec: {{- if and (eq .Values.txtPrefix "") (ne .Values.txtSuffix "") }} - --txt-suffix={{ .Values.txtSuffix }} {{- end }} + {{- if .Values.txtNewFormatOnly}} + - --txt-new-format-only + {{- end }} {{- if .Values.namespaced }} - --namespace={{ .Release.Namespace }} {{- end }} diff --git a/charts/external-dns/values.yaml b/charts/external-dns/values.yaml index dc12cdd65b..201f15747b 100644 --- a/charts/external-dns/values.yaml +++ b/charts/external-dns/values.yaml @@ -222,6 +222,11 @@ txtPrefix: # -- (string) Specify a suffix for the domain names of TXT records created for the `txt` registry. # Mutually exclusive with `txtPrefix`. txtSuffix: +# -- (boolean) When true, creates TXT records only in the new format that includes record type information (e.g. "a-" prefix for A records). +# This reduces the number of DNS records created, helping with provider-specific record limits. +# Note: All ExternalDNS instances must support the new format before enabling this option. +# Default: false (maintains backwards compatibility by creating both old and new format records) +txtNewFormatOnly: false # -- Limit possible target zones by domain suffixes. domainFilters: [] From a1d64bd3e82a170e7d78dd8772fc9004b4173a31 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen <30603252+malpou@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:02:55 +0000 Subject: [PATCH 10/16] run helm-docs --- charts/external-dns/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/external-dns/README.md b/charts/external-dns/README.md index d88545c383..dc3c3c08f3 100644 --- a/charts/external-dns/README.md +++ b/charts/external-dns/README.md @@ -176,6 +176,7 @@ If `namespaced` is set to `true`, please ensure that `sources` my only contains | tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | | topologySpreadConstraints | list | `[]` | Topology spread constraints for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided one will be created from the pod selector labels. | | triggerLoopOnEvent | bool | `false` | If `true`, triggers run loop on create/update/delete events in addition of regular interval. | +| txtNewFormatOnly | boolean | `false` | When true, creates TXT records only in the new format that includes record type information (e.g. "a-" prefix for A records). This reduces the number of DNS records created, helping with provider-specific record limits. Note: All ExternalDNS instances must support the new format before enabling this option. Default: false (maintains backwards compatibility by creating both old and new format records) | | txtOwnerId | string | `nil` | Specify an identifier for this instance of _ExternalDNS_ wWhen using a registry other than `noop`. | | txtPrefix | string | `nil` | Specify a prefix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtSuffix`. | | txtSuffix | string | `nil` | Specify a suffix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtPrefix`. | From 78e1ffc83b37eb4263184b7369c3f187c8b53d89 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen <30603252+malpou@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:07:23 +0000 Subject: [PATCH 11/16] remove unessery newline --- registry/txt.go | 1 - 1 file changed, 1 deletion(-) diff --git a/registry/txt.go b/registry/txt.go index c713c2e840..cf5baa400d 100644 --- a/registry/txt.go +++ b/registry/txt.go @@ -68,7 +68,6 @@ func NewTXTRegistry(provider provider.Provider, txtPrefix, txtSuffix, ownerID st managedRecordTypes, excludeRecordTypes []string, txtEncryptEnabled bool, txtEncryptAESKey []byte, newFormatOnly bool) (*TXTRegistry, error) { - if ownerID == "" { return nil, errors.New("owner id cannot be empty") } From 0bcd0e3612e4e4fd4b0cea8b1f0e0d78c9754cf3 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen <30603252+malpou@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:11:46 +0000 Subject: [PATCH 12/16] add entry to unreleased chart items --- charts/external-dns/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/external-dns/CHANGELOG.md b/charts/external-dns/CHANGELOG.md index 3569fa6869..bfa28b9e45 100644 --- a/charts/external-dns/CHANGELOG.md +++ b/charts/external-dns/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ability to configure `imagePullSecrets` via helm `global` value ([#4667](https://github.com/kubernetes-sigs/external-dns/pull/4667)) _@jkroepke_ - Added options to configure `labelFilter` and `managedRecordTypes` via dedicated helm values ([#4849](https://github.com/kubernetes-sigs/external-dns/pull/4849)) _@abaguas_ +- Added `txtNewFormatOnly` value to configure creation of TXT records in new format only ([#4946](https://github.com/kubernetes-sigs/external-dns/pull/4946)) _@malpou_ ### Fixed From 07e4c3ee1e943cd8505f9e35cc16be638de2c7a7 Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Thu, 16 Jan 2025 17:21:35 +0100 Subject: [PATCH 13/16] Revert "run helm-docs" This reverts commit a1d64bd3e82a170e7d78dd8772fc9004b4173a31. --- charts/external-dns/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/charts/external-dns/README.md b/charts/external-dns/README.md index dc3c3c08f3..d88545c383 100644 --- a/charts/external-dns/README.md +++ b/charts/external-dns/README.md @@ -176,7 +176,6 @@ If `namespaced` is set to `true`, please ensure that `sources` my only contains | tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | | topologySpreadConstraints | list | `[]` | Topology spread constraints for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided one will be created from the pod selector labels. | | triggerLoopOnEvent | bool | `false` | If `true`, triggers run loop on create/update/delete events in addition of regular interval. | -| txtNewFormatOnly | boolean | `false` | When true, creates TXT records only in the new format that includes record type information (e.g. "a-" prefix for A records). This reduces the number of DNS records created, helping with provider-specific record limits. Note: All ExternalDNS instances must support the new format before enabling this option. Default: false (maintains backwards compatibility by creating both old and new format records) | | txtOwnerId | string | `nil` | Specify an identifier for this instance of _ExternalDNS_ wWhen using a registry other than `noop`. | | txtPrefix | string | `nil` | Specify a prefix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtSuffix`. | | txtSuffix | string | `nil` | Specify a suffix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtPrefix`. | From c8d85a74c751e5e40f66efda33dbfa4040a9d93a Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Thu, 16 Jan 2025 17:21:41 +0100 Subject: [PATCH 14/16] Revert "add new option to helm chart" This reverts commit 299d087917ead3d306d163bd1c67e710cd35f398. --- charts/external-dns/templates/deployment.yaml | 3 --- charts/external-dns/values.yaml | 5 ----- 2 files changed, 8 deletions(-) diff --git a/charts/external-dns/templates/deployment.yaml b/charts/external-dns/templates/deployment.yaml index 03d298989a..46a41de4fa 100644 --- a/charts/external-dns/templates/deployment.yaml +++ b/charts/external-dns/templates/deployment.yaml @@ -106,9 +106,6 @@ spec: {{- if and (eq .Values.txtPrefix "") (ne .Values.txtSuffix "") }} - --txt-suffix={{ .Values.txtSuffix }} {{- end }} - {{- if .Values.txtNewFormatOnly}} - - --txt-new-format-only - {{- end }} {{- if .Values.namespaced }} - --namespace={{ .Release.Namespace }} {{- end }} diff --git a/charts/external-dns/values.yaml b/charts/external-dns/values.yaml index 201f15747b..dc12cdd65b 100644 --- a/charts/external-dns/values.yaml +++ b/charts/external-dns/values.yaml @@ -222,11 +222,6 @@ txtPrefix: # -- (string) Specify a suffix for the domain names of TXT records created for the `txt` registry. # Mutually exclusive with `txtPrefix`. txtSuffix: -# -- (boolean) When true, creates TXT records only in the new format that includes record type information (e.g. "a-" prefix for A records). -# This reduces the number of DNS records created, helping with provider-specific record limits. -# Note: All ExternalDNS instances must support the new format before enabling this option. -# Default: false (maintains backwards compatibility by creating both old and new format records) -txtNewFormatOnly: false # -- Limit possible target zones by domain suffixes. domainFilters: [] From 5a849a7b9cc50b64c2dbf4a855d19816513f0e5c Mon Sep 17 00:00:00 2001 From: Malthe Poulsen Date: Thu, 16 Jan 2025 17:24:26 +0100 Subject: [PATCH 15/16] Revert "add entry to unreleased chart items" This reverts commit 0bcd0e3612e4e4fd4b0cea8b1f0e0d78c9754cf3. --- charts/external-dns/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/charts/external-dns/CHANGELOG.md b/charts/external-dns/CHANGELOG.md index bfa28b9e45..3569fa6869 100644 --- a/charts/external-dns/CHANGELOG.md +++ b/charts/external-dns/CHANGELOG.md @@ -22,7 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ability to configure `imagePullSecrets` via helm `global` value ([#4667](https://github.com/kubernetes-sigs/external-dns/pull/4667)) _@jkroepke_ - Added options to configure `labelFilter` and `managedRecordTypes` via dedicated helm values ([#4849](https://github.com/kubernetes-sigs/external-dns/pull/4849)) _@abaguas_ -- Added `txtNewFormatOnly` value to configure creation of TXT records in new format only ([#4946](https://github.com/kubernetes-sigs/external-dns/pull/4946)) _@malpou_ ### Fixed From 1242e4634c5c8731ac512a5c042dcf91276cfd4d Mon Sep 17 00:00:00 2001 From: Malthe Poulsen <30603252+malpou@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:50:08 +0000 Subject: [PATCH 16/16] fix test cases that have changed --- registry/txt_encryption_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/registry/txt_encryption_test.go b/registry/txt_encryption_test.go index baed5890c1..788fb22cb1 100644 --- a/registry/txt_encryption_test.go +++ b/registry/txt_encryption_test.go @@ -60,7 +60,7 @@ func TestNewTXTRegistryEncryptionConfig(t *testing.T) { }, } for _, test := range tests { - actual, err := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "", []string{}, []string{}, test.encEnabled, test.aesKeyRaw) + actual, err := NewTXTRegistry(p, "txt.", "", "owner", time.Hour, "", []string{}, []string{}, test.encEnabled, test.aesKeyRaw, false) if test.errorExpected { require.Error(t, err) } else { @@ -106,7 +106,7 @@ func TestGenerateTXTGenerateTextRecordEncryptionWihDecryption(t *testing.T) { for _, k := range withEncryptionKeys { t.Run(fmt.Sprintf("key '%s' with decrypted result '%s'", k, test.decrypted), func(t *testing.T) { key := []byte(k) - r, err := NewTXTRegistry(p, "", "", "owner", time.Minute, "", []string{}, []string{}, true, key) + r, err := NewTXTRegistry(p, "", "", "owner", time.Minute, "", []string{}, []string{}, true, key, false) assert.NoError(t, err, "Error creating TXT registry") txtRecords := r.generateTXTRecord(test.record) assert.Len(t, txtRecords, len(test.record.Targets)) @@ -143,7 +143,7 @@ func TestApplyRecordsWithEncryption(t *testing.T) { key := []byte("ZPitL0NGVQBZbTD6DwXJzD8RiStSazzYXQsdUowLURY=") - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, key) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, key, false) _ = r.ApplyChanges(ctx, &plan.Changes{ Create: []*endpoint.Endpoint{ @@ -201,7 +201,7 @@ func TestApplyRecordsWithEncryptionKeyChanged(t *testing.T) { } for _, key := range withEncryptionKeys { - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, []byte(key)) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, []byte(key), false) _ = r.ApplyChanges(ctx, &plan.Changes{ Create: []*endpoint.Endpoint{ newEndpointWithOwner("new-record-1.test-zone.example.org", "new-loadbalancer-1.lb.com", endpoint.RecordTypeCNAME, "owner"), @@ -231,7 +231,7 @@ func TestApplyRecordsOnEncryptionKeyChangeWithKeyIdLabel(t *testing.T) { } for i, key := range withEncryptionKeys { - r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, []byte(key)) + r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, true, []byte(key), false) keyId := fmt.Sprintf("key-id-%d", i) changes := []*endpoint.Endpoint{ newEndpointWithOwnerAndOwnedRecordWithKeyIDLabel("new-record-1.test-zone.example.org", "new-loadbalancer-1.lb.com", endpoint.RecordTypeCNAME, "owner", "", keyId),