From 853577f436feb6e5c1e620a049be966134a3c3e0 Mon Sep 17 00:00:00 2001 From: Michael Nairn Date: Thu, 31 Oct 2024 12:04:40 +0000 Subject: [PATCH] chore: Tidy up dnspolicy controller code and files (#967) Follow on from https://github.com/Kuadrant/kuadrant-operator/pull/937 to cleanup controller files to bring them more inline with the current sotw approach. There are no logical changes in this commit, existing code is just being moved. Signed-off-by: Michael Nairn --- controllers/dns_helper.go | 76 ----------- controllers/dnspolicy_controller.go | 42 ------ controllers/dnspolicy_dnsrecords.go | 65 +++++++++- ...r_test.go => dnspolicy_dnsrecords_test.go} | 4 +- controllers/dnspolicy_metrics.go | 63 +++++++++ controllers/dnspolicy_status.go | 120 ------------------ controllers/dnspolicy_status_updater.go | 73 +++++++++++ ...st.go => dnspolicy_status_updater_test.go} | 2 +- .../effective_dnspolicies_reconciler.go | 49 +++---- 9 files changed, 229 insertions(+), 265 deletions(-) delete mode 100644 controllers/dns_helper.go delete mode 100644 controllers/dnspolicy_controller.go rename controllers/{dns_helper_test.go => dnspolicy_dnsrecords_test.go} (97%) create mode 100644 controllers/dnspolicy_metrics.go delete mode 100644 controllers/dnspolicy_status.go rename controllers/{dnspolicy_status_test.go => dnspolicy_status_updater_test.go} (98%) diff --git a/controllers/dns_helper.go b/controllers/dns_helper.go deleted file mode 100644 index 175b78048..000000000 --- a/controllers/dns_helper.go +++ /dev/null @@ -1,76 +0,0 @@ -package controllers - -import ( - "fmt" - "net" - "strings" - - gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - - "github.com/kuadrant/dns-operator/pkg/builder" - - "github.com/kuadrant/kuadrant-operator/api/v1alpha1" -) - -const ( - LabelGatewayReference = "kuadrant.io/gateway" - LabelListenerReference = "kuadrant.io/listener-name" -) - -func dnsRecordName(gatewayName, listenerName string) string { - return fmt.Sprintf("%s-%s", gatewayName, listenerName) -} - -// GatewayWrapper is a wrapper for gateway to implement interface form the builder -type GatewayWrapper struct { - *gatewayapiv1.Gateway - excludedAddresses []string -} - -func NewGatewayWrapper(gateway *gatewayapiv1.Gateway) *GatewayWrapper { - return &GatewayWrapper{Gateway: gateway} -} - -func (g *GatewayWrapper) GetAddresses() []builder.TargetAddress { - addresses := make([]builder.TargetAddress, len(g.Status.Addresses)) - for i, address := range g.Status.Addresses { - addresses[i] = builder.TargetAddress{ - Type: builder.AddressType(*address.Type), - Value: address.Value, - } - } - return addresses -} - -func (g *GatewayWrapper) RemoveExcludedStatusAddresses(p *v1alpha1.DNSPolicy) error { - g.excludedAddresses = p.Spec.ExcludeAddresses - newAddresses := []gatewayapiv1.GatewayStatusAddress{} - for _, address := range g.Gateway.Status.Addresses { - found := false - for _, exclude := range p.Spec.ExcludeAddresses { - //Only a CIDR will have / in the address so attempt to parse fail if not valid - if strings.Contains(exclude, "/") { - _, network, err := net.ParseCIDR(exclude) - if err != nil { - return fmt.Errorf("could not parse the CIDR from the excludeAddresses field %w", err) - } - ip := net.ParseIP(address.Value) - // only check addresses that are actually IPs - if ip != nil && network.Contains(ip) { - found = true - break - } - } - if exclude == address.Value { - found = true - break - } - } - if !found { - newAddresses = append(newAddresses, address) - } - } - // setting this in memory only wont be saved to actual gateway - g.Status.Addresses = newAddresses - return nil -} diff --git a/controllers/dnspolicy_controller.go b/controllers/dnspolicy_controller.go deleted file mode 100644 index fcb0c85c3..000000000 --- a/controllers/dnspolicy_controller.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controllers - -import ( - "github.com/prometheus/client_golang/prometheus" - - "sigs.k8s.io/controller-runtime/pkg/metrics" -) - -const ( - dnsPolicyNameLabel = "dns_policy_name" - dnsPolicyNamespaceLabel = "dns_policy_namespace" - dnsPolicyCondition = "dns_policy_condition" -) - -var ( - dnsPolicyReady = prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Name: "kuadrant_dns_policy_ready", - Help: "DNS Policy ready", - }, - []string{dnsPolicyNameLabel, dnsPolicyNamespaceLabel, dnsPolicyCondition}) -) - -func init() { - metrics.Registry.MustRegister(dnsPolicyReady) -} diff --git a/controllers/dnspolicy_dnsrecords.go b/controllers/dnspolicy_dnsrecords.go index 0daca897f..f8972c2a2 100644 --- a/controllers/dnspolicy_dnsrecords.go +++ b/controllers/dnspolicy_dnsrecords.go @@ -2,6 +2,8 @@ package controllers import ( "fmt" + "net" + "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" externaldns "sigs.k8s.io/external-dns/endpoint" @@ -13,11 +15,14 @@ import ( "github.com/kuadrant/kuadrant-operator/api/v1alpha1" ) -var ( - ErrNoRoutes = fmt.Errorf("no routes attached to any gateway listeners") - ErrNoAddresses = fmt.Errorf("no valid status addresses to use on gateway") +const ( + LabelListenerReference = "kuadrant.io/listener-name" ) +func dnsRecordName(gatewayName, listenerName string) string { + return fmt.Sprintf("%s-%s", gatewayName, listenerName) +} + func desiredDNSRecord(gateway *gatewayapiv1.Gateway, clusterID string, dnsPolicy *v1alpha1.DNSPolicy, targetListener gatewayapiv1.Listener) (*kuadrantdnsv1alpha1.DNSRecord, error) { rootHost := string(*targetListener.Hostname) var healthCheckSpec *kuadrantdnsv1alpha1.HealthCheckSpec @@ -61,6 +66,60 @@ func desiredDNSRecord(gateway *gatewayapiv1.Gateway, clusterID string, dnsPolicy return dnsRecord, nil } +// GatewayWrapper is a wrapper for gateway to implement interface from the builder +type GatewayWrapper struct { + *gatewayapiv1.Gateway + excludedAddresses []string +} + +func NewGatewayWrapper(gateway *gatewayapiv1.Gateway) *GatewayWrapper { + return &GatewayWrapper{Gateway: gateway} +} + +func (g *GatewayWrapper) GetAddresses() []builder.TargetAddress { + addresses := make([]builder.TargetAddress, len(g.Status.Addresses)) + for i, address := range g.Status.Addresses { + addresses[i] = builder.TargetAddress{ + Type: builder.AddressType(*address.Type), + Value: address.Value, + } + } + return addresses +} + +func (g *GatewayWrapper) RemoveExcludedStatusAddresses(p *v1alpha1.DNSPolicy) error { + g.excludedAddresses = p.Spec.ExcludeAddresses + newAddresses := []gatewayapiv1.GatewayStatusAddress{} + for _, address := range g.Gateway.Status.Addresses { + found := false + for _, exclude := range p.Spec.ExcludeAddresses { + //Only a CIDR will have / in the address so attempt to parse fail if not valid + if strings.Contains(exclude, "/") { + _, network, err := net.ParseCIDR(exclude) + if err != nil { + return fmt.Errorf("could not parse the CIDR from the excludeAddresses field %w", err) + } + ip := net.ParseIP(address.Value) + // only check addresses that are actually IPs + if ip != nil && network.Contains(ip) { + found = true + break + } + } + if exclude == address.Value { + found = true + break + } + } + if !found { + newAddresses = append(newAddresses, address) + } + } + // setting this in memory only won't be saved to actual gateway + g.Status.Addresses = newAddresses + return nil +} + func buildEndpoints(clusterID, hostname string, gateway *gatewayapiv1.Gateway, policy *v1alpha1.DNSPolicy) ([]*externaldns.Endpoint, error) { gw := gateway.DeepCopy() gatewayWrapper := NewGatewayWrapper(gw) diff --git a/controllers/dns_helper_test.go b/controllers/dnspolicy_dnsrecords_test.go similarity index 97% rename from controllers/dns_helper_test.go rename to controllers/dnspolicy_dnsrecords_test.go index 39e26bb70..b1a4f13f4 100644 --- a/controllers/dns_helper_test.go +++ b/controllers/dnspolicy_dnsrecords_test.go @@ -1,3 +1,5 @@ +//go:build unit + package controllers_test import ( @@ -9,7 +11,7 @@ import ( "github.com/kuadrant/kuadrant-operator/controllers" ) -func TestRemoveExcludedStatusAddresses(t *testing.T) { +func TestGatewayWrapper_RemoveExcludedStatusAddresses(t *testing.T) { ipaddress := gatewayapiv1.IPAddressType hostaddress := gatewayapiv1.HostnameAddressType testCases := []struct { diff --git a/controllers/dnspolicy_metrics.go b/controllers/dnspolicy_metrics.go new file mode 100644 index 000000000..26dbef766 --- /dev/null +++ b/controllers/dnspolicy_metrics.go @@ -0,0 +1,63 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "github.com/prometheus/client_golang/prometheus" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/metrics" + + kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" +) + +const ( + dnsPolicyNameLabel = "dns_policy_name" + dnsPolicyNamespaceLabel = "dns_policy_namespace" + dnsPolicyCondition = "dns_policy_condition" +) + +var ( + dnsPolicyReady = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "kuadrant_dns_policy_ready", + Help: "DNS Policy ready", + }, + []string{dnsPolicyNameLabel, dnsPolicyNamespaceLabel, dnsPolicyCondition}) +) + +func emitConditionMetrics(dnsPolicy *kuadrantv1alpha1.DNSPolicy) { + readyStatus := meta.FindStatusCondition(dnsPolicy.Status.Conditions, ReadyConditionType) + if readyStatus == nil { + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "true").Set(0) + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "false").Set(0) + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "unknown").Set(1) + } else if readyStatus.Status != metav1.ConditionTrue { + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "true").Set(0) + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "false").Set(1) + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "unknown").Set(0) + } else { + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "true").Set(1) + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "false").Set(0) + dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "unknown").Set(0) + } +} + +func init() { + metrics.Registry.MustRegister(dnsPolicyReady) +} diff --git a/controllers/dnspolicy_status.go b/controllers/dnspolicy_status.go deleted file mode 100644 index ac42f8605..000000000 --- a/controllers/dnspolicy_status.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controllers - -import ( - "errors" - "fmt" - "slices" - "strings" - - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" - - "github.com/kuadrant/kuadrant-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" - "github.com/kuadrant/kuadrant-operator/pkg/library/utils" -) - -var NegativePolarityConditions []string - -func emitConditionMetrics(dnsPolicy *v1alpha1.DNSPolicy) { - readyStatus := meta.FindStatusCondition(dnsPolicy.Status.Conditions, ReadyConditionType) - if readyStatus == nil { - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "true").Set(0) - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "false").Set(0) - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "unknown").Set(1) - } else if readyStatus.Status != metav1.ConditionTrue { - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "true").Set(0) - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "false").Set(1) - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "unknown").Set(0) - } else { - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "true").Set(1) - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "false").Set(0) - dnsPolicyReady.WithLabelValues(dnsPolicy.Name, dnsPolicy.Namespace, "unknown").Set(0) - } -} - -func enforcedCondition(records []*kuadrantdnsv1alpha1.DNSRecord, dnsPolicy *v1alpha1.DNSPolicy) *metav1.Condition { - // there are no controlled DNS records present - if len(records) == 0 { - cond := kuadrant.EnforcedCondition(dnsPolicy, nil, true) - cond.Message = "DNSPolicy has been successfully enforced : no DNSRecords created based on policy and gateway configuration" - return cond - } - - // filter not ready records - notReadyRecords := utils.Filter(records, func(record *kuadrantdnsv1alpha1.DNSRecord) bool { - return meta.IsStatusConditionFalse(record.Status.Conditions, string(kuadrantdnsv1alpha1.ConditionTypeReady)) - }) - - // if there are records and none of the records are ready - if len(records) > 0 && len(notReadyRecords) == len(records) { - return kuadrant.EnforcedCondition(dnsPolicy, kuadrant.NewErrUnknown(dnsPolicy.Kind(), errors.New("policy is not enforced on any DNSRecord: not a single DNSRecord is ready")), false) - } - - // some of the records are not ready - if len(notReadyRecords) > 0 { - additionalMessage := ". Not ready DNSRecords are: " - for _, record := range notReadyRecords { - additionalMessage += fmt.Sprintf("%s ", record.Name) - } - cond := kuadrant.EnforcedCondition(dnsPolicy, nil, false) - cond.Message += additionalMessage - return cond - } - // all records are ready - return kuadrant.EnforcedCondition(dnsPolicy, nil, true) -} - -func propagateRecordConditions(records []*kuadrantdnsv1alpha1.DNSRecord, policyStatus *v1alpha1.DNSPolicyStatus) { - //reset conditions - policyStatus.RecordConditions = map[string][]metav1.Condition{} - - for _, record := range records { - var allConditions []metav1.Condition - allConditions = append(allConditions, record.Status.Conditions...) - if record.Status.HealthCheck != nil { - allConditions = append(allConditions, record.Status.HealthCheck.Conditions...) - - if record.Status.HealthCheck.Probes != nil { - for _, probeStatus := range record.Status.HealthCheck.Probes { - allConditions = append(allConditions, probeStatus.Conditions...) - } - } - } - - for _, condition := range allConditions { - //skip healthy negative polarity conditions - if slices.Contains(NegativePolarityConditions, condition.Type) && - strings.ToLower(string(condition.Status)) == "false" { - continue - } - //skip healthy positive polarity conditions - if !slices.Contains(NegativePolarityConditions, condition.Type) && - strings.ToLower(string(condition.Status)) == "true" { - continue - } - - policyStatus.RecordConditions[record.Spec.RootHost] = append( - policyStatus.RecordConditions[record.Spec.RootHost], - condition) - } - } -} diff --git a/controllers/dnspolicy_status_updater.go b/controllers/dnspolicy_status_updater.go index e792e4915..5501174e9 100644 --- a/controllers/dnspolicy_status_updater.go +++ b/controllers/dnspolicy_status_updater.go @@ -2,8 +2,10 @@ package controllers import ( "context" + "errors" "fmt" "slices" + "strings" "sync" "github.com/samber/lo" @@ -19,6 +21,7 @@ import ( kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" + "github.com/kuadrant/kuadrant-operator/pkg/library/utils" ) func NewDNSPolicyStatusUpdater(client *dynamic.DynamicClient) *DNSPolicyStatusUpdater { @@ -119,3 +122,73 @@ func (r *DNSPolicyStatusUpdater) updateStatus(ctx context.Context, _ []controlle return nil } + +func enforcedCondition(records []*kuadrantdnsv1alpha1.DNSRecord, dnsPolicy *kuadrantv1alpha1.DNSPolicy) *metav1.Condition { + // there are no controlled DNS records present + if len(records) == 0 { + cond := kuadrant.EnforcedCondition(dnsPolicy, nil, true) + cond.Message = "DNSPolicy has been successfully enforced : no DNSRecords created based on policy and gateway configuration" + return cond + } + + // filter not ready records + notReadyRecords := utils.Filter(records, func(record *kuadrantdnsv1alpha1.DNSRecord) bool { + return meta.IsStatusConditionFalse(record.Status.Conditions, string(kuadrantdnsv1alpha1.ConditionTypeReady)) + }) + + // if there are records and none of the records are ready + if len(records) > 0 && len(notReadyRecords) == len(records) { + return kuadrant.EnforcedCondition(dnsPolicy, kuadrant.NewErrUnknown(dnsPolicy.Kind(), errors.New("policy is not enforced on any DNSRecord: not a single DNSRecord is ready")), false) + } + + // some of the records are not ready + if len(notReadyRecords) > 0 { + additionalMessage := ". Not ready DNSRecords are: " + for _, record := range notReadyRecords { + additionalMessage += fmt.Sprintf("%s ", record.Name) + } + cond := kuadrant.EnforcedCondition(dnsPolicy, nil, false) + cond.Message += additionalMessage + return cond + } + // all records are ready + return kuadrant.EnforcedCondition(dnsPolicy, nil, true) +} + +var NegativePolarityConditions []string + +func propagateRecordConditions(records []*kuadrantdnsv1alpha1.DNSRecord, policyStatus *kuadrantv1alpha1.DNSPolicyStatus) { + //reset conditions + policyStatus.RecordConditions = map[string][]metav1.Condition{} + + for _, record := range records { + var allConditions []metav1.Condition + allConditions = append(allConditions, record.Status.Conditions...) + if record.Status.HealthCheck != nil { + allConditions = append(allConditions, record.Status.HealthCheck.Conditions...) + + if record.Status.HealthCheck.Probes != nil { + for _, probeStatus := range record.Status.HealthCheck.Probes { + allConditions = append(allConditions, probeStatus.Conditions...) + } + } + } + + for _, condition := range allConditions { + //skip healthy negative polarity conditions + if slices.Contains(NegativePolarityConditions, condition.Type) && + strings.ToLower(string(condition.Status)) == "false" { + continue + } + //skip healthy positive polarity conditions + if !slices.Contains(NegativePolarityConditions, condition.Type) && + strings.ToLower(string(condition.Status)) == "true" { + continue + } + + policyStatus.RecordConditions[record.Spec.RootHost] = append( + policyStatus.RecordConditions[record.Spec.RootHost], + condition) + } + } +} diff --git a/controllers/dnspolicy_status_test.go b/controllers/dnspolicy_status_updater_test.go similarity index 98% rename from controllers/dnspolicy_status_test.go rename to controllers/dnspolicy_status_updater_test.go index b8de6bcdf..ffbfef668 100644 --- a/controllers/dnspolicy_status_test.go +++ b/controllers/dnspolicy_status_updater_test.go @@ -13,7 +13,7 @@ import ( "github.com/kuadrant/kuadrant-operator/api/v1alpha1" ) -func TestPropagateRecordConditions(t *testing.T) { +func Test_propagateRecordConditions(t *testing.T) { healthyProviderCondition := metav1.Condition{ Type: "Ready", Status: "True", diff --git a/controllers/effective_dnspolicies_reconciler.go b/controllers/effective_dnspolicies_reconciler.go index 07b106d10..0b1801f54 100644 --- a/controllers/effective_dnspolicies_reconciler.go +++ b/controllers/effective_dnspolicies_reconciler.go @@ -22,6 +22,11 @@ import ( "github.com/kuadrant/kuadrant-operator/pkg/library/utils" ) +var ( + ErrNoRoutes = fmt.Errorf("no routes attached to any gateway listeners") + ErrNoAddresses = fmt.Errorf("no valid status addresses to use on gateway") +) + func NewEffectiveDNSPoliciesReconciler(client *dynamic.DynamicClient, scheme *runtime.Scheme) *EffectiveDNSPoliciesReconciler { return &EffectiveDNSPoliciesReconciler{ client: client, @@ -75,7 +80,7 @@ func (r *EffectiveDNSPoliciesReconciler) reconcile(ctx context.Context, _ []cont continue } - listeners := r.listenersForPolicy(ctx, topology, policy, policyTypeFilterFunc) + listeners := listenersForPolicy(ctx, topology, policy, policyTypeFilterFunc) if logger.V(1).Enabled() { listenerLocators := lo.Map(listeners, func(item *machinery.Listener, _ int) string { @@ -211,27 +216,6 @@ func (r *EffectiveDNSPoliciesReconciler) reconcile(ctx context.Context, _ []cont return r.deleteOrphanDNSRecords(controller.LoggerIntoContext(ctx, logger), topology) } -// listenersForPolicy returns an array of listeners that are targeted by the given policy. -// If the target is a Listener a single element array containing that listener is returned. -// If the target is a Gateway all listeners that do not have a DNS policy explicitly attached are returned. -func (r *EffectiveDNSPoliciesReconciler) listenersForPolicy(_ context.Context, topology *machinery.Topology, policy machinery.Policy, policyTypeFilterFunc dnsPolicyTypeFilter) []*machinery.Listener { - return lo.Flatten(lo.FilterMap(topology.Targetables().Children(policy), func(t machinery.Targetable, _ int) ([]*machinery.Listener, bool) { - if l, ok := t.(*machinery.Listener); ok { - return []*machinery.Listener{l}, true - } - if g, ok := t.(*machinery.Gateway); ok { - listeners := lo.FilterMap(topology.Targetables().Children(g), func(t machinery.Targetable, _ int) (*machinery.Listener, bool) { - l, lok := t.(*machinery.Listener) - lPolicies := lo.FilterMap(l.Policies(), policyTypeFilterFunc) - return l, lok && len(lPolicies) == 0 - }) - return listeners, true - } - - return nil, false - })) -} - // deleteOrphanDNSRecords deletes any DNSRecord resources that exist in the topology but have no parent targettable, policy or path back to the policy. func (r *EffectiveDNSPoliciesReconciler) deleteOrphanDNSRecords(ctx context.Context, topology *machinery.Topology) error { logger := controller.LoggerFromContext(ctx).WithName("deleteOrphanDNSRecords") @@ -298,6 +282,27 @@ func (r *EffectiveDNSPoliciesReconciler) deleteRecord(ctx context.Context, obj m } } +// listenersForPolicy returns an array of listeners that are targeted by the given policy. +// If the target is a Listener a single element array containing that listener is returned. +// If the target is a Gateway all listeners that do not have a DNS policy explicitly attached are returned. +func listenersForPolicy(_ context.Context, topology *machinery.Topology, policy machinery.Policy, policyTypeFilterFunc dnsPolicyTypeFilter) []*machinery.Listener { + return lo.Flatten(lo.FilterMap(topology.Targetables().Children(policy), func(t machinery.Targetable, _ int) ([]*machinery.Listener, bool) { + if l, ok := t.(*machinery.Listener); ok { + return []*machinery.Listener{l}, true + } + if g, ok := t.(*machinery.Gateway); ok { + listeners := lo.FilterMap(topology.Targetables().Children(g), func(t machinery.Targetable, _ int) (*machinery.Listener, bool) { + l, lok := t.(*machinery.Listener) + lPolicies := lo.FilterMap(l.Policies(), policyTypeFilterFunc) + return l, lok && len(lPolicies) == 0 + }) + return listeners, true + } + + return nil, false + })) +} + // canUpdateDNSRecord returns true if the current record can be updated to the desired. func canUpdateDNSRecord(ctx context.Context, current, desired *kuadrantdnsv1alpha1.DNSRecord) bool { logger := controller.LoggerFromContext(ctx)