diff --git a/internal/controller/externaldnswatcher_controller.go b/internal/controller/externaldnswatcher_controller.go index 52e7514..413dc4f 100644 --- a/internal/controller/externaldnswatcher_controller.go +++ b/internal/controller/externaldnswatcher_controller.go @@ -21,6 +21,7 @@ import ( "fmt" dnsv1alpha1 "git.mayers.cloud/superflo22/split-horizon-operator/api/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "reflect" "sigs.k8s.io/controller-runtime/pkg/handler" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "strings" @@ -61,16 +62,15 @@ func (r *ExternalDNSWatcherReconciler) Reconcile(ctx context.Context, req ctrl.R // Step 2: Check annotation annotations := gateway.GetAnnotations() - if annotations["dns.mayers.cloud/enabled"] != "true" { - log.Info("ExternalDNS watcher is not enabled") + authority := annotations["dns.mayers.cloud/authority"] + if authority == "" { + log.Info("Missing required authority annotation") return ctrl.Result{}, nil } - network := annotations["dns.mayers.cloud/network"] - authority := annotations["dns.mayers.cloud/authority"] - if network == "" || authority == "" { - log.Info("Missing required annotations") - return ctrl.Result{}, nil + if network == "" { + log.Info("Missing network annotation assuming default network") + network = "default" } // Step 3: Get Gateway IP (if available) @@ -88,42 +88,75 @@ func (r *ExternalDNSWatcherReconciler) Reconcile(ctx context.Context, req ctrl.R } for _, route := range routes.Items { - for _, parent := range route.Spec.ParentRefs { + // Step 5: Collect hostnames + for _, hostname := range route.Spec.Hostnames { - // Check if the parent is a Gateway and matches the current gateway - if string(*parent.Kind) == "Gateway" && string(parent.Name) == gateway.Name { - // Step 5: Collect hostnames - for _, hostname := range route.Spec.Hostnames { - record := &dnsv1alpha1.TechnitiumRecord{ - TypeMeta: metav1.TypeMeta{ - Kind: "TechnitiumRecord", - APIVersion: "dns.mayers.cloud/v1alpha1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s", strings.ReplaceAll(string(hostname), ".", "-")), - Namespace: route.Namespace, - }, - Spec: dnsv1alpha1.TechnitiumRecordSpec{ - AuthorityRef: dnsv1alpha1.AuthorityReference{ - Name: authority, - }, - Name: string(hostname), - TTL: 300, - ClassPath: "SimpleAddress", - RecordData: map[string][]string{ - network: gatewayIPs, - }, - }, - } - // Log the record yaml - log.Info("TechnitiumRecord", "record", record) + // Naming convention for TechnitiumRecord + recordName := fmt.Sprintf("%s", strings.ReplaceAll(string(hostname), ".", "-")) - if err := r.Client.Patch(ctx, record, client.Apply, client.ForceOwnership, client.FieldOwner("external-dns-watcher")); err != nil { - log.Error(err, "Failed to apply TechnitiumRecord") + // Bestehendes TechnitiumRecord abrufen + var existingRecord dnsv1alpha1.TechnitiumRecord + err := r.Client.Get(ctx, client.ObjectKey{ + Namespace: route.Namespace, + Name: recordName, + }, &existingRecord) + if err != nil { + log.Info("Creating new Record", "recordName", recordName) + + record := &dnsv1alpha1.TechnitiumRecord{ + TypeMeta: metav1.TypeMeta{ + Kind: "TechnitiumRecord", + APIVersion: "dns.mayers.cloud/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: recordName, + Namespace: route.Namespace, + }, + Spec: dnsv1alpha1.TechnitiumRecordSpec{ + AuthorityRef: dnsv1alpha1.AuthorityReference{ + Name: authority, + }, + Name: string(hostname), + TTL: 300, + ClassPath: "SimpleAddress", + RecordData: map[string][]string{ + network: gatewayIPs, + }, + }, + } + // Log the record yaml + log.V(1).Info("TechnitiumRecord Manifest", "record", record) + + if err := r.Client.Patch(ctx, record, client.Apply, client.ForceOwnership, client.FieldOwner("external-dns-watcher")); err != nil { + log.Error(err, "Failed to apply TechnitiumRecord") + } else { + log.Info("Created new Record", "name", record.Name) + } + } + + // Step 6: Update existing TechnitiumRecord + if existingRecord.Spec.RecordData[network] != nil { + // Check if the IPs are different + if !reflect.DeepEqual(existingRecord.Spec.RecordData[network], gatewayIPs) { + log.Info("Updating existing Record", "recordName", recordName) + + existingRecord.Spec.RecordData[network] = gatewayIPs + if err := r.Update(ctx, &existingRecord); err != nil { + log.Error(err, "Failed to update TechnitiumRecord") } else { - log.Info("Reconciled TechnitiumRecord", "name", record.Name) + log.Info("Updated IPs in existing Record", "name", recordName) } } + } else { + log.Info("Adding new network to existing Record", "recordName", recordName) + + // Add the new network and IPs + existingRecord.Spec.RecordData[network] = gatewayIPs + if err := r.Update(ctx, &existingRecord); err != nil { + log.Error(err, "Failed to update TechnitiumRecord") + } else { + log.Info("Updated new network in existing Record", "name", recordName) + } } } }