Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions internal/controller/dnsrecord_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
"errors"
"fmt"
"reflect"
"strings"
"time"

"github.com/fluxcd/pkg/runtime/conditions"
"github.com/fluxcd/pkg/runtime/patch"
"golang.org/x/net/publicsuffix"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -109,7 +109,7 @@
defer func() {
patchOpts := []patch.Option{}

if errors.Is(retErr, reconcile.TerminalError(nil)) || (retErr == nil && (result.IsZero() || !result.Requeue)) {

Check failure on line 112 in internal/controller/dnsrecord_controller.go

View workflow job for this annotation

GitHub Actions / lint

SA1019: result.Requeue is deprecated: Use `RequeueAfter` instead. (staticcheck)
patchOpts = append(patchOpts, patch.WithStatusObservedGeneration{})
}

Expand All @@ -128,21 +128,18 @@
}
}()

zoneName, _ := publicsuffix.EffectiveTLDPlusOne(dnsrecord.Spec.Name)

zones := &cloudflareoperatoriov1.ZoneList{}
if err := r.List(ctx, zones, client.MatchingFields{cloudflareoperatoriov1.ZoneNameIndexKey: zoneName}); err != nil {
if err := r.List(ctx, zones); err != nil {
log.Error(err, "Failed to list zones")
return ctrl.Result{RequeueAfter: r.RetryInterval}, nil
}

if len(zones.Items) == 0 {
intconditions.MarkFalse(dnsrecord, fmt.Errorf("zone %q not found", zoneName))
zone := findZoneForDNSRecord(dnsrecord.Spec.Name, zones.Items)
if zone == nil {
intconditions.MarkFalse(dnsrecord, fmt.Errorf("zone for %q not found", dnsrecord.Spec.Name))
return ctrl.Result{RequeueAfter: r.RetryInterval}, nil
}

zone := &zones.Items[0]

if !dnsrecord.DeletionTimestamp.IsZero() {
if err := r.reconcileDelete(ctx, zone.Status.ID, dnsrecord); err != nil {
log.Error(err, "Failed to delete DNS record in Cloudflare, record may still exist in Cloudflare")
Expand Down Expand Up @@ -307,6 +304,20 @@
return reflect.DeepEqual(a, bb)
}

// findZoneForDNSRecord returns the longest matching zone for a DNS record name.
func findZoneForDNSRecord(dnsRecordName string, zones []cloudflareoperatoriov1.Zone) *cloudflareoperatoriov1.Zone {
var matchedZone *cloudflareoperatoriov1.Zone
for i := range zones {
zone := &zones[i]
if dnsRecordName == zone.Spec.Name || strings.HasSuffix(dnsRecordName, "."+zone.Spec.Name) {
if matchedZone == nil || len(zone.Spec.Name) > len(matchedZone.Spec.Name) {
matchedZone = zone
}
}
}
return matchedZone
}

// requestsForIPChange returns a list of reconcile.Requests for DNSRecords that need to be reconciled if the IP changes
func (r *DNSRecordReconciler) requestsForIPChange(ctx context.Context, o client.Object) []reconcile.Request {
ip, ok := o.(*cloudflareoperatoriov1.IP)
Expand Down
26 changes: 26 additions & 0 deletions internal/controller/dnsrecord_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,30 @@ func TestDNSRecordReconciler_reconcileDNSRecord(t *testing.T) {
isEqual := r.compareDNSRecord(dnsRecordSpec, cloudflareDNSRecord)
g.Expect(isEqual).To(BeTrue())
})

t.Run("find longest matching zone", func(t *testing.T) {
g := NewWithT(t)

zones := []cloudflareoperatoriov1.Zone{
{
ObjectMeta: metav1.ObjectMeta{Name: "root"},
Spec: cloudflareoperatoriov1.ZoneSpec{Name: "example.com"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "sub"},
Spec: cloudflareoperatoriov1.ZoneSpec{Name: "tst.example.com"},
},
}

zone := findZoneForDNSRecord("podinfo.tst.example.com", zones)
g.Expect(zone).ToNot(BeNil())
g.Expect(zone.Spec.Name).To(Equal("tst.example.com"))

zone = findZoneForDNSRecord("foo.example.com", zones)
g.Expect(zone).ToNot(BeNil())
g.Expect(zone.Spec.Name).To(Equal("example.com"))

zone = findZoneForDNSRecord("no.match.test", zones)
g.Expect(zone).To(BeNil())
})
}
Loading