From 40a5fe8453e458a5daac1648b9f8132bb3da639e Mon Sep 17 00:00:00 2001 From: Phil Brookes Date: Thu, 14 Mar 2024 10:36:19 +0100 Subject: [PATCH] remove dns healthcheck probes update manifests and bundle upgrade controller-gen to 0.14.0 (#460) dns: Bump DNS Operator version propagate health check to DNS Records move dns operator back to latest --- .github/workflows/build-images-base.yaml | 2 +- Makefile | 2 +- api/v1alpha1/dnspolicy_types.go | 22 +- api/v1alpha1/zz_generated.deepcopy.go | 5 +- ...adrant-operator.clusterserviceversion.yaml | 26 +- bundle/manifests/kuadrant.io_dnspolicies.yaml | 9 +- bundle/metadata/dependencies.yaml | 2 +- config/crd/bases/kuadrant.io_dnspolicies.yaml | 9 +- config/dependencies/dns/kustomization.yaml | 2 +- config/rbac/role.yaml | 26 +- controllers/dns_helper.go | 71 +- .../dnshealthcheckprobe_eventmapper.go | 54 -- controllers/dnspolicy_controller.go | 20 +- ...dnspolicy_controller_health_checks_test.go | 564 ---------------- ...dnspolicy_controller_multi_cluster_test.go | 625 ++++++++++-------- ...nspolicy_controller_single_cluster_test.go | 189 +++--- controllers/dnspolicy_controller_test.go | 24 - controllers/dnspolicy_dnsrecords.go | 40 +- controllers/dnspolicy_healthchecks.go | 185 ------ examples/dnspolicy/application.yaml | 50 ++ examples/dnspolicy/dnspolicy.yaml | 16 + examples/dnspolicy/gateway.yaml | 20 + examples/dnspolicy/managedzone.yaml | 22 + examples/dnspolicy/script.sh | 5 + go.mod | 5 +- go.sum | 19 +- pkg/common/common.go | 12 + pkg/library/utils/k8s_utils.go | 21 + pkg/library/utils/k8s_utils_test.go | 47 ++ pkg/multicluster/gateway_wrapper.go | 7 +- pkg/multicluster/target.go | 75 +-- 31 files changed, 746 insertions(+), 1430 deletions(-) delete mode 100644 controllers/dnshealthcheckprobe_eventmapper.go delete mode 100644 controllers/dnspolicy_controller_health_checks_test.go delete mode 100644 controllers/dnspolicy_healthchecks.go create mode 100644 examples/dnspolicy/application.yaml create mode 100644 examples/dnspolicy/dnspolicy.yaml create mode 100644 examples/dnspolicy/gateway.yaml create mode 100644 examples/dnspolicy/managedzone.yaml create mode 100755 examples/dnspolicy/script.sh diff --git a/.github/workflows/build-images-base.yaml b/.github/workflows/build-images-base.yaml index 587713325..d9292ab1c 100644 --- a/.github/workflows/build-images-base.yaml +++ b/.github/workflows/build-images-base.yaml @@ -21,7 +21,7 @@ on: type: string dnsOperatorVersion: description: DNS Operator bundle version - default: 0.1.0 + default: lastest type: string wasmShimVersion: description: WASM Shim version diff --git a/Makefile b/Makefile index bad0e1b64..97ee65c55 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ endif LIMITADOR_OPERATOR_BUNDLE_IMG ?= quay.io/kuadrant/limitador-operator-bundle:$(LIMITADOR_OPERATOR_BUNDLE_IMG_TAG) ## dns -DNS_OPERATOR_VERSION ?= 0.1.0 +DNS_OPERATOR_VERSION ?= main kuadrantdns_bundle_is_semantic := $(call is_semantic_version,$(DNS_OPERATOR_VERSION)) ifeq (latest,$(DNS_OPERATOR_VERSION)) diff --git a/api/v1alpha1/dnspolicy_types.go b/api/v1alpha1/dnspolicy_types.go index 6b5a04440..db7ab2030 100644 --- a/api/v1alpha1/dnspolicy_types.go +++ b/api/v1alpha1/dnspolicy_types.go @@ -24,8 +24,6 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" ) @@ -215,14 +213,14 @@ type DNSPolicyList struct { // By default, this health check will be applied to each unique DNS A Record for // the listeners assigned to the target gateway type HealthCheckSpec struct { - Endpoint string `json:"endpoint,omitempty"` - Port *int `json:"port,omitempty"` - Protocol *kuadrantdnsv1alpha1.HealthProtocol `json:"protocol,omitempty"` - FailureThreshold *int `json:"failureThreshold,omitempty"` - AdditionalHeadersRef *kuadrantdnsv1alpha1.AdditionalHeadersRef `json:"additionalHeadersRef,omitempty"` - ExpectedResponses []int `json:"expectedResponses,omitempty"` - AllowInsecureCertificates bool `json:"allowInsecureCertificates,omitempty"` - Interval *metav1.Duration `json:"interval,omitempty"` + Endpoint string `json:"endpoint,omitempty"` + Port *int `json:"port,omitempty"` + Protocol *string `json:"protocol,omitempty"` + FailureThreshold *int `json:"failureThreshold,omitempty"` + AdditionalHeadersRef *string `json:"additionalHeadersRef,omitempty"` + ExpectedResponses []int `json:"expectedResponses,omitempty"` + AllowInsecureCertificates bool `json:"allowInsecureCertificates,omitempty"` + Interval *metav1.Duration `json:"interval,omitempty"` } func (s *HealthCheckSpec) Validate() error { @@ -243,7 +241,7 @@ func (s *HealthCheckSpec) Default() { } if s.Protocol == nil { - protocol := kuadrantdnsv1alpha1.HttpsProtocol + protocol := "HTTPS" s.Protocol = &protocol } } @@ -311,7 +309,7 @@ func (p *DNSPolicy) WithTargetGateway(gwName string) *DNSPolicy { //HealthCheck -func (p *DNSPolicy) WithHealthCheckFor(endpoint string, port *int, protocol kuadrantdnsv1alpha1.HealthProtocol, failureThreshold *int) *DNSPolicy { +func (p *DNSPolicy) WithHealthCheckFor(endpoint string, port *int, protocol string, failureThreshold *int) *DNSPolicy { return p.WithHealthCheck(HealthCheckSpec{ Endpoint: endpoint, Port: port, diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 2a94da87e..2d30cdf06 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,6 @@ package v1alpha1 import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - apiv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -225,7 +224,7 @@ func (in *HealthCheckSpec) DeepCopyInto(out *HealthCheckSpec) { } if in.Protocol != nil { in, out := &in.Protocol, &out.Protocol - *out = new(apiv1alpha1.HealthProtocol) + *out = new(string) **out = **in } if in.FailureThreshold != nil { @@ -235,7 +234,7 @@ func (in *HealthCheckSpec) DeepCopyInto(out *HealthCheckSpec) { } if in.AdditionalHeadersRef != nil { in, out := &in.AdditionalHeadersRef, &out.AdditionalHeadersRef - *out = new(apiv1alpha1.AdditionalHeadersRef) + *out = new(string) **out = **in } if in.ExpectedResponses != nil { diff --git a/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml b/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml index 9a99d1b3a..8a7d80d70 100644 --- a/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml +++ b/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml @@ -262,6 +262,14 @@ spec: - patch - update - watch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch - apiGroups: - extensions.istio.io resources: @@ -347,24 +355,6 @@ spec: - get - patch - update - - apiGroups: - - kuadrant.io - resources: - - dnshealthcheckprobes - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - kuadrant.io - resources: - - dnshealthcheckprobes/status - verbs: - - get - apiGroups: - kuadrant.io resources: diff --git a/bundle/manifests/kuadrant.io_dnspolicies.yaml b/bundle/manifests/kuadrant.io_dnspolicies.yaml index 33ee4a98f..441734e9c 100644 --- a/bundle/manifests/kuadrant.io_dnspolicies.yaml +++ b/bundle/manifests/kuadrant.io_dnspolicies.yaml @@ -68,12 +68,7 @@ spec: the listeners assigned to the target gateway properties: additionalHeadersRef: - properties: - name: - type: string - required: - - name - type: object + type: string allowInsecureCertificates: type: boolean endpoint: @@ -89,8 +84,6 @@ spec: port: type: integer protocol: - description: HealthProtocol represents the protocol to use when - making a health check request type: string type: object loadBalancing: diff --git a/bundle/metadata/dependencies.yaml b/bundle/metadata/dependencies.yaml index 01e31484a..d8ccdcad1 100644 --- a/bundle/metadata/dependencies.yaml +++ b/bundle/metadata/dependencies.yaml @@ -10,7 +10,7 @@ dependencies: - type: olm.package value: packageName: dns-operator - version: "0.1.0" + version: "0.0.0" - type: olm.package value: packageName: cert-manager diff --git a/config/crd/bases/kuadrant.io_dnspolicies.yaml b/config/crd/bases/kuadrant.io_dnspolicies.yaml index d04a6e54e..686adf404 100644 --- a/config/crd/bases/kuadrant.io_dnspolicies.yaml +++ b/config/crd/bases/kuadrant.io_dnspolicies.yaml @@ -67,12 +67,7 @@ spec: the listeners assigned to the target gateway properties: additionalHeadersRef: - properties: - name: - type: string - required: - - name - type: object + type: string allowInsecureCertificates: type: boolean endpoint: @@ -88,8 +83,6 @@ spec: port: type: integer protocol: - description: HealthProtocol represents the protocol to use when - making a health check request type: string type: object loadBalancing: diff --git a/config/dependencies/dns/kustomization.yaml b/config/dependencies/dns/kustomization.yaml index 3087948f0..f7abc9be3 100644 --- a/config/dependencies/dns/kustomization.yaml +++ b/config/dependencies/dns/kustomization.yaml @@ -1,5 +1,5 @@ resources: -- github.com/kuadrant/dns-operator/config/default?ref=v0.1.0 +- github.com/kuadrant/dns-operator/config/default?ref=main patches: - path: deployment_patch.yaml diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index e423a29c6..b390602b2 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -110,6 +110,14 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch - apiGroups: - extensions.istio.io resources: @@ -195,24 +203,6 @@ rules: - get - patch - update -- apiGroups: - - kuadrant.io - resources: - - dnshealthcheckprobes - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - kuadrant.io - resources: - - dnshealthcheckprobes/status - verbs: - - get - apiGroups: - kuadrant.io resources: diff --git a/controllers/dns_helper.go b/controllers/dns_helper.go index ca9124d49..92e270d5e 100644 --- a/controllers/dns_helper.go +++ b/controllers/dns_helper.go @@ -8,17 +8,15 @@ import ( "strings" "golang.org/x/net/publicsuffix" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + externaldns "sigs.k8s.io/external-dns/endpoint" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/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" "github.com/kuadrant/kuadrant-operator/pkg/multicluster" ) @@ -103,25 +101,14 @@ func gatewayDNSRecordLabels(gwKey client.ObjectKey) map[string]string { } } -func withGatewayListener[T metav1.Object](gateway kuadrant.GatewayWrapper, listener gatewayapiv1.Listener, obj T) T { - if obj.GetAnnotations() == nil { - obj.SetAnnotations(map[string]string{}) - } - - obj.GetAnnotations()["dnsrecord-name"] = fmt.Sprintf("%s-%s", gateway.Name, listener.Name) - obj.GetAnnotations()["dnsrecord-namespace"] = gateway.Namespace - - return obj -} - func (dh *dnsHelper) setEndpoints(mcgTarget *multicluster.GatewayTarget, dnsRecord *kuadrantdnsv1alpha1.DNSRecord, listener gatewayapiv1.Listener, strategy v1alpha1.RoutingStrategy) error { gwListenerHost := string(*listener.Hostname) - var endpoints []*kuadrantdnsv1alpha1.Endpoint + var endpoints []*externaldns.Endpoint - //Health Checks currently modify endpoints so we have to keep existing ones in order to not lose health check ids - currentEndpoints := make(map[string]*kuadrantdnsv1alpha1.Endpoint, len(dnsRecord.Spec.Endpoints)) + //Health Checks currently modify endpoints, so we have to keep existing ones in order to not lose health check ids + currentEndpoints := make(map[string]*externaldns.Endpoint, len(dnsRecord.Spec.Endpoints)) for _, endpoint := range dnsRecord.Spec.Endpoints { - currentEndpoints[endpoint.SetID()] = endpoint + currentEndpoints[getSetID(endpoint)] = endpoint } switch strategy { @@ -134,7 +121,7 @@ func (dh *dnsHelper) setEndpoints(mcgTarget *multicluster.GatewayTarget, dnsReco } sort.Slice(endpoints, func(i, j int) bool { - return endpoints[i].SetID() < endpoints[j].SetID() + return getSetID(endpoints[i]) < getSetID(endpoints[j]) }) dnsRecord.Spec.Endpoints = endpoints @@ -144,9 +131,9 @@ func (dh *dnsHelper) setEndpoints(mcgTarget *multicluster.GatewayTarget, dnsReco // getSimpleEndpoints returns the endpoints for the given GatewayTarget using the simple routing strategy -func (dh *dnsHelper) getSimpleEndpoints(mcgTarget *multicluster.GatewayTarget, hostname string, currentEndpoints map[string]*kuadrantdnsv1alpha1.Endpoint) []*kuadrantdnsv1alpha1.Endpoint { +func (dh *dnsHelper) getSimpleEndpoints(mcgTarget *multicluster.GatewayTarget, hostname string, currentEndpoints map[string]*externaldns.Endpoint) []*externaldns.Endpoint { var ( - endpoints []*kuadrantdnsv1alpha1.Endpoint + endpoints []*externaldns.Endpoint ipValues []string hostValues []string ) @@ -177,7 +164,7 @@ func (dh *dnsHelper) getSimpleEndpoints(mcgTarget *multicluster.GatewayTarget, h // getLoadBalancedEndpoints returns the endpoints for the given GatewayTarget using the loadbalanced routing strategy // -// Builds an array of kuadrantdnsv1alpha1.Endpoint resources and sets them on the given DNSRecord. The endpoints expected are calculated +// Builds an array of externaldns.Endpoint resources and sets them on the given DNSRecord. The endpoints expected are calculated // from the GatewayTarget using the target Gateway (GatewayTarget.Gateway), the LoadBalancing Spec // from the DNSPolicy attached to the target gateway (GatewayTarget.LoadBalancing) and the list of clusters the // target gateway is currently placed on (GatewayTarget.ClusterGatewayTargets). @@ -214,20 +201,20 @@ func (dh *dnsHelper) getSimpleEndpoints(mcgTarget *multicluster.GatewayTarget, h // ab2.lb-a1b2.shop.example.com A 192.22.2.3 // ab3.lb-a1b2.shop.example.com A 192.22.2.4 -func (dh *dnsHelper) getLoadBalancedEndpoints(mcgTarget *multicluster.GatewayTarget, hostname string, currentEndpoints map[string]*kuadrantdnsv1alpha1.Endpoint) []*kuadrantdnsv1alpha1.Endpoint { +func (dh *dnsHelper) getLoadBalancedEndpoints(mcgTarget *multicluster.GatewayTarget, hostname string, currentEndpoints map[string]*externaldns.Endpoint) []*externaldns.Endpoint { cnameHost := hostname if isWildCardHost(hostname) { cnameHost = strings.Replace(hostname, "*.", "", -1) } - var endpoint *kuadrantdnsv1alpha1.Endpoint - var defaultEndpoint *kuadrantdnsv1alpha1.Endpoint - endpoints := make([]*kuadrantdnsv1alpha1.Endpoint, 0) - lbName := strings.ToLower(fmt.Sprintf("lb-%s.%s", mcgTarget.GetShortCode(), cnameHost)) + var endpoint *externaldns.Endpoint + var defaultEndpoint *externaldns.Endpoint + endpoints := make([]*externaldns.Endpoint, 0) + lbName := strings.ToLower(fmt.Sprintf("klb.%s", cnameHost)) for geoCode, cgwTargets := range mcgTarget.GroupTargetsByGeo() { geoLbName := strings.ToLower(fmt.Sprintf("%s.%s", geoCode, lbName)) - var clusterEndpoints []*kuadrantdnsv1alpha1.Endpoint + var clusterEndpoints []*externaldns.Endpoint for _, cgwTarget := range cgwTargets { var ipValues []string var hostValues []string @@ -240,7 +227,7 @@ func (dh *dnsHelper) getLoadBalancedEndpoints(mcgTarget *multicluster.GatewayTar } if len(ipValues) > 0 { - clusterLbName := strings.ToLower(fmt.Sprintf("%s.%s", cgwTarget.GetShortCode(), lbName)) + clusterLbName := strings.ToLower(fmt.Sprintf("%s-%s.%s", cgwTarget.GetShortCode(), mcgTarget.GetShortCode(), lbName)) endpoint = createOrUpdateEndpoint(clusterLbName, ipValues, kuadrantdnsv1alpha1.ARecordType, "", DefaultTTL, currentEndpoints) clusterEndpoints = append(clusterEndpoints, endpoint) hostValues = append(hostValues, clusterLbName) @@ -248,7 +235,7 @@ func (dh *dnsHelper) getLoadBalancedEndpoints(mcgTarget *multicluster.GatewayTar for _, hostValue := range hostValues { endpoint = createOrUpdateEndpoint(geoLbName, []string{hostValue}, kuadrantdnsv1alpha1.CNAMERecordType, hostValue, DefaultTTL, currentEndpoints) - endpoint.SetProviderSpecific(kuadrantdnsv1alpha1.ProviderSpecificWeight, strconv.Itoa(cgwTarget.GetWeight())) + endpoint.SetProviderSpecificProperty(kuadrantdnsv1alpha1.ProviderSpecificWeight, strconv.Itoa(cgwTarget.GetWeight())) clusterEndpoints = append(clusterEndpoints, endpoint) } } @@ -270,14 +257,14 @@ func (dh *dnsHelper) getLoadBalancedEndpoints(mcgTarget *multicluster.GatewayTar defaultEndpoint = createOrUpdateEndpoint(lbName, []string{geoLbName}, kuadrantdnsv1alpha1.CNAMERecordType, "default", DefaultCnameTTL, currentEndpoints) } - endpoint.SetProviderSpecific(kuadrantdnsv1alpha1.ProviderSpecificGeoCode, string(geoCode)) + endpoint.SetProviderSpecificProperty(kuadrantdnsv1alpha1.ProviderSpecificGeoCode, string(geoCode)) endpoints = append(endpoints, endpoint) } if len(endpoints) > 0 { // Add the `defaultEndpoint`, this should always be set by this point if `endpoints` isn't empty - defaultEndpoint.SetProviderSpecific(kuadrantdnsv1alpha1.ProviderSpecificGeoCode, string(v1alpha1.WildcardGeo)) + defaultEndpoint.SetProviderSpecificProperty(kuadrantdnsv1alpha1.ProviderSpecificGeoCode, string(v1alpha1.WildcardGeo)) endpoints = append(endpoints, defaultEndpoint) //Create gwListenerHost CNAME (shop.example.com -> lb-a1b2.shop.example.com) endpoint = createOrUpdateEndpoint(hostname, []string{lbName}, kuadrantdnsv1alpha1.CNAMERecordType, "", DefaultCnameTTL, currentEndpoints) @@ -287,12 +274,12 @@ func (dh *dnsHelper) getLoadBalancedEndpoints(mcgTarget *multicluster.GatewayTar return endpoints } -func createOrUpdateEndpoint(dnsName string, targets kuadrantdnsv1alpha1.Targets, recordType kuadrantdnsv1alpha1.DNSRecordType, setIdentifier string, - recordTTL kuadrantdnsv1alpha1.TTL, currentEndpoints map[string]*kuadrantdnsv1alpha1.Endpoint) (endpoint *kuadrantdnsv1alpha1.Endpoint) { +func createOrUpdateEndpoint(dnsName string, targets externaldns.Targets, recordType kuadrantdnsv1alpha1.DNSRecordType, setIdentifier string, + recordTTL externaldns.TTL, currentEndpoints map[string]*externaldns.Endpoint) (endpoint *externaldns.Endpoint) { ok := false endpointID := dnsName + setIdentifier if endpoint, ok = currentEndpoints[endpointID]; !ok { - endpoint = &kuadrantdnsv1alpha1.Endpoint{} + endpoint = &externaldns.Endpoint{} if setIdentifier != "" { endpoint.SetIdentifier = setIdentifier } @@ -362,16 +349,6 @@ func isWildCardHost(host string) bool { return strings.HasPrefix(host, "*") } -func (dh *dnsHelper) getDNSHealthCheckProbes(ctx context.Context, gateway *gatewayapiv1.Gateway, dnsPolicy *v1alpha1.DNSPolicy) ([]*kuadrantdnsv1alpha1.DNSHealthCheckProbe, error) { - list := &kuadrantdnsv1alpha1.DNSHealthCheckProbeList{} - if err := dh.List(ctx, list, &client.ListOptions{ - LabelSelector: labels.SelectorFromSet(commonDNSRecordLabels(client.ObjectKeyFromObject(gateway), dnsPolicy)), - Namespace: dnsPolicy.Namespace, - }); err != nil { - return nil, err - } - - return utils.Map(list.Items, func(obj kuadrantdnsv1alpha1.DNSHealthCheckProbe) *kuadrantdnsv1alpha1.DNSHealthCheckProbe { - return &obj - }), nil +func getSetID(endpoint *externaldns.Endpoint) string { + return endpoint.DNSName + endpoint.SetIdentifier } diff --git a/controllers/dnshealthcheckprobe_eventmapper.go b/controllers/dnshealthcheckprobe_eventmapper.go deleted file mode 100644 index 03c3c4202..000000000 --- a/controllers/dnshealthcheckprobe_eventmapper.go +++ /dev/null @@ -1,54 +0,0 @@ -package controllers - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" - - "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" - "github.com/kuadrant/kuadrant-operator/pkg/library/mappers" - "github.com/kuadrant/kuadrant-operator/pkg/library/utils" -) - -var _ mappers.EventMapper = &DNSHealthCheckProbeEventMapper{} - -func NewDNSHealthCheckProbeEventMapper(o ...mappers.MapperOption) mappers.EventMapper { - return &DNSHealthCheckProbeEventMapper{opts: mappers.Apply(o...)} -} - -// DNSHealthCheckProbeEventMapper is an EventHandler that maps DNSHealthCheckProbe object events to policy events. -type DNSHealthCheckProbeEventMapper struct { - opts mappers.MapperOptions -} - -func (m *DNSHealthCheckProbeEventMapper) MapToPolicy(obj client.Object, policyKind kuadrant.Referrer) []reconcile.Request { - logger := m.opts.Logger.V(1).WithValues("object", client.ObjectKeyFromObject(obj)) - probe, ok := obj.(*kuadrantdnsv1alpha1.DNSHealthCheckProbe) - if !ok { - logger.Info("mapToPolicyRequest:", "error", fmt.Sprintf("%T is not a *v1alpha1.DNSHealthCheckProbe", obj)) - return []reconcile.Request{} - } - - requests := make([]reconcile.Request, 0) - - policyName := utils.GetLabel(probe, policyKind.DirectReferenceAnnotationName()) - if policyName == "" { - return requests - } - policyNamespace := utils.GetLabel(probe, fmt.Sprintf("%s-namespace", policyKind.DirectReferenceAnnotationName())) - if policyNamespace == "" { - return requests - } - logger.Info("mapToPolicyRequest", policyKind.Kind(), policyName) - requests = append(requests, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: policyName, - Namespace: policyNamespace, - }}) - - return requests -} diff --git a/controllers/dnspolicy_controller.go b/controllers/dnspolicy_controller.go index 710015572..3a6806431 100644 --- a/controllers/dnspolicy_controller.go +++ b/controllers/dnspolicy_controller.go @@ -56,6 +56,7 @@ type DNSPolicyReconciler struct { dnsHelper dnsHelper } +//+kubebuilder:rbac:groups=core,resources=namespaces,verbs=get;list;watch //+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies,verbs=get;list;watch;update;patch;delete //+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies/status,verbs=get;update;patch //+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies/finalizers,verbs=update @@ -63,8 +64,6 @@ type DNSPolicyReconciler struct { //+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/status,verbs=get;update;patch //+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/finalizers,verbs=update -//+kubebuilder:rbac:groups=kuadrant.io,resources=dnshealthcheckprobes,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=kuadrant.io,resources=dnshealthcheckprobes/status,verbs=get //+kubebuilder:rbac:groups=kuadrant.io,resources=dnsrecords,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=kuadrant.io,resources=dnsrecords/status,verbs=get @@ -159,12 +158,6 @@ func (r *DNSPolicyReconciler) reconcileResources(ctx context.Context, dnsPolicy return errors.Join(fmt.Errorf("reconcile DNSRecords error %w", err), updateErr) } - if err = r.reconcileHealthCheckProbes(ctx, dnsPolicy, gatewayDiffObj); err != nil { - gatewayCondition = BuildPolicyAffectedCondition(DNSPolicyAffected, dnsPolicy, targetNetworkObject, gatewayapiv1alpha2.PolicyReasonInvalid, err) - updateErr := r.updateGatewayCondition(ctx, gatewayCondition, gatewayDiffObj) - return errors.Join(fmt.Errorf("reconcile HealthChecks error %w", err), updateErr) - } - // set direct back ref - i.e. claim the target network object as taken asap if err = r.TargetRefReconciler.ReconcileTargetBackReference(ctx, dnsPolicy, targetNetworkObject, dnsPolicy.DirectReferenceAnnotationName()); err != nil { gatewayCondition = BuildPolicyAffectedCondition(DNSPolicyAffected, dnsPolicy, targetNetworkObject, gatewayapiv1alpha2.PolicyReasonConflicted, err) @@ -194,10 +187,6 @@ func (r *DNSPolicyReconciler) deleteResources(ctx context.Context, dnsPolicy *v1 return err } - if err := r.deleteHealthCheckProbes(ctx, dnsPolicy); err != nil { - return err - } - // remove direct back ref if targetNetworkObject != nil { if err := r.TargetRefReconciler.DeleteTargetBackReference(ctx, targetNetworkObject, dnsPolicy.DirectReferenceAnnotationName()); err != nil { @@ -249,7 +238,6 @@ func (r *DNSPolicyReconciler) updateGatewayCondition(ctx context.Context, condit func (r *DNSPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { gatewayEventMapper := mappers.NewGatewayEventMapper(mappers.WithLogger(r.Logger().WithName("gatewayEventMapper"))) - dnsHealthCheckProbeEventMapper := NewDNSHealthCheckProbeEventMapper(mappers.WithLogger(r.Logger().WithName("dnsHealthCheckProbeEventMapper"))) r.dnsHelper = dnsHelper{Client: r.Client()} ctrlr := ctrl.NewControllerManagedBy(mgr). @@ -260,12 +248,6 @@ func (r *DNSPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, object client.Object) []reconcile.Request { return gatewayEventMapper.MapToPolicy(object, &v1alpha1.DNSPolicy{}) }), - ). - Watches( - &kuadrantdnsv1alpha1.DNSHealthCheckProbe{}, - handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, object client.Object) []reconcile.Request { - return dnsHealthCheckProbeEventMapper.MapToPolicy(object, &v1alpha1.DNSPolicy{}) - }), ) return ctrlr.Complete(r) } diff --git a/controllers/dnspolicy_controller_health_checks_test.go b/controllers/dnspolicy_controller_health_checks_test.go deleted file mode 100644 index b4581ac8d..000000000 --- a/controllers/dnspolicy_controller_health_checks_test.go +++ /dev/null @@ -1,564 +0,0 @@ -//go:build integration - -package controllers - -import ( - "context" - "fmt" - "time" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - . "github.com/onsi/gomega/gstruct" - - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" - "sigs.k8s.io/controller-runtime/pkg/client" - gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - - kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/pkg/multicluster" -) - -var _ = Describe("DNSPolicy Health Checks", func() { - - var gatewayClass *gatewayapiv1.GatewayClass - var managedZone *kuadrantdnsv1alpha1.ManagedZone - var testNamespace string - var gateway *gatewayapiv1.Gateway - var dnsPolicy *v1alpha1.DNSPolicy - var lbHash, recordName, wildcardRecordName string - var ctx context.Context - - BeforeEach(func() { - ctx = context.Background() - CreateNamespace(&testNamespace) - - gatewayClass = testBuildGatewayClass("foo", "default", "kuadrant.io/bar") - Expect(k8sClient.Create(ctx, gatewayClass)).To(Succeed()) - - managedZone = testBuildManagedZone("mz-example-com", testNamespace, "example.com") - Expect(k8sClient.Create(ctx, managedZone)).To(Succeed()) - - gateway = NewGatewayBuilder(TestGatewayName, gatewayClass.Name, testNamespace). - WithHTTPListener(TestListenerNameOne, TestHostOne). - WithHTTPListener(TestListenerNameWildcard, TestHostWildcard). - Gateway - Expect(k8sClient.Create(ctx, gateway)).To(Succeed()) - - //Set multi cluster gateway status - Eventually(func() error { - gateway.Status.Addresses = []gatewayapiv1.GatewayStatusAddress{ - { - Type: ptr.To(multicluster.MultiClusterIPAddressType), - Value: TestClusterNameOne + "/" + TestIPAddressOne, - }, - { - Type: ptr.To(multicluster.MultiClusterIPAddressType), - Value: TestClusterNameTwo + "/" + TestIPAddressTwo, - }, - } - gateway.Status.Listeners = []gatewayapiv1.ListenerStatus{ - { - Name: TestClusterNameOne + "." + TestListenerNameOne, - SupportedKinds: []gatewayapiv1.RouteGroupKind{}, - AttachedRoutes: 1, - Conditions: []metav1.Condition{}, - }, - { - Name: TestClusterNameTwo + "." + TestListenerNameOne, - SupportedKinds: []gatewayapiv1.RouteGroupKind{}, - AttachedRoutes: 1, - Conditions: []metav1.Condition{}, - }, - { - Name: TestClusterNameOne + "." + TestListenerNameWildcard, - SupportedKinds: []gatewayapiv1.RouteGroupKind{}, - AttachedRoutes: 1, - Conditions: []metav1.Condition{}, - }, - { - Name: TestClusterNameTwo + "." + TestListenerNameWildcard, - SupportedKinds: []gatewayapiv1.RouteGroupKind{}, - AttachedRoutes: 1, - Conditions: []metav1.Condition{}, - }, - } - return k8sClient.Status().Update(ctx, gateway) - }, TestTimeoutMedium, TestRetryIntervalMedium).ShouldNot(HaveOccurred()) - - lbHash = multicluster.ToBase36hash(fmt.Sprintf("%s-%s", gateway.Name, gateway.Namespace)) - recordName = fmt.Sprintf("%s-%s", TestGatewayName, TestListenerNameOne) - wildcardRecordName = fmt.Sprintf("%s-%s", TestGatewayName, TestListenerNameWildcard) - }) - - AfterEach(func() { - if gateway != nil { - err := k8sClient.Delete(ctx, gateway) - Expect(client.IgnoreNotFound(err)).ToNot(HaveOccurred()) - } - if dnsPolicy != nil { - err := k8sClient.Delete(ctx, dnsPolicy) - Expect(client.IgnoreNotFound(err)).ToNot(HaveOccurred()) - - } - if managedZone != nil { - err := k8sClient.Delete(ctx, managedZone) - Expect(client.IgnoreNotFound(err)).ToNot(HaveOccurred()) - } - if gatewayClass != nil { - err := k8sClient.Delete(ctx, gatewayClass) - Expect(client.IgnoreNotFound(err)).ToNot(HaveOccurred()) - } - DeleteNamespaceCallback(&testNamespace)() - }) - - Context("multi cluster gateway status", func() { - - Context("loadbalanced routing strategy", func() { - - Context("with health checks", func() { - var unhealthy bool - - BeforeEach(func() { - dnsPolicy = v1alpha1.NewDNSPolicy("test-dns-policy", testNamespace). - WithTargetGateway(TestGatewayName). - WithRoutingStrategy(v1alpha1.LoadBalancedRoutingStrategy). - WithLoadBalancingWeightedFor(120, nil). - WithHealthCheckFor("/", nil, kuadrantdnsv1alpha1.HttpProtocol, ptr.To(4)) - Expect(k8sClient.Create(ctx, dnsPolicy)).To(BeNil()) - Eventually(func() error { //dns policy exists - return k8sClient.Get(ctx, client.ObjectKey{Name: dnsPolicy.Name, Namespace: dnsPolicy.Namespace}, dnsPolicy) - }, TestTimeoutMedium, TestRetryIntervalMedium).ShouldNot(HaveOccurred()) - }) - - It("should create dns records", func() { - Eventually(func(g Gomega, ctx context.Context) { - recordList := &kuadrantdnsv1alpha1.DNSRecordList{} - err := k8sClient.List(ctx, recordList, &client.ListOptions{Namespace: testNamespace}) - g.Expect(err).NotTo(HaveOccurred()) - g.Expect(recordList.Items).To(HaveLen(2)) - g.Expect(recordList.Items).To( - ContainElements( - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", recordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": HaveLen(6), - }), - }), - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", wildcardRecordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": HaveLen(6), - }), - }), - )) - }, TestTimeoutMedium, TestRetryIntervalMedium, ctx).Should(Succeed()) - }) - - It("should have probes that are healthy", func() { - probeList := &kuadrantdnsv1alpha1.DNSHealthCheckProbeList{} - Eventually(func() error { - Expect(k8sClient.List(ctx, probeList, &client.ListOptions{Namespace: testNamespace})).To(BeNil()) - if len(probeList.Items) != 2 { - return fmt.Errorf("expected %v probes, got %v", 2, len(probeList.Items)) - } - return nil - }, TestTimeoutMedium, TestRetryIntervalMedium).Should(BeNil()) - Expect(len(probeList.Items)).To(Equal(2)) - }) - - Context("all unhealthy probes", func() { - It("should publish all dns records endpoints", func() { - - expectedEndpoints := []*kuadrantdnsv1alpha1.Endpoint{ - { - DNSName: "2w705o.lb-" + lbHash + ".test.example.com", - Targets: []string{ - TestIPAddressTwo, - }, - RecordType: "A", - SetIdentifier: "", - RecordTTL: 60, - }, - { - DNSName: "s07c46.lb-" + lbHash + ".test.example.com", - Targets: []string{ - TestIPAddressOne, - }, - RecordType: "A", - SetIdentifier: "", - RecordTTL: 60, - }, - { - DNSName: "default.lb-" + lbHash + ".test.example.com", - Targets: []string{ - "2w705o.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "2w705o.lb-" + lbHash + ".test.example.com", - RecordTTL: 60, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "weight", - Value: "120", - }, - }, - }, - { - DNSName: "default.lb-" + lbHash + ".test.example.com", - Targets: []string{ - "s07c46.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "s07c46.lb-" + lbHash + ".test.example.com", - RecordTTL: 60, - Labels: nil, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "weight", - Value: "120", - }, - }, - }, - { - DNSName: "lb-" + lbHash + ".test.example.com", - Targets: []string{ - "default.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "default", - RecordTTL: 300, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "geo-code", - Value: "*", - }, - }, - }, - { - DNSName: "test.example.com", - Targets: []string{ - "lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "", - RecordTTL: 300, - }, - } - - probeList := &kuadrantdnsv1alpha1.DNSHealthCheckProbeList{} - Eventually(func() error { - Expect(k8sClient.List(ctx, probeList, &client.ListOptions{Namespace: testNamespace})).To(BeNil()) - if len(probeList.Items) != 2 { - return fmt.Errorf("expected %v probes, got %v", 2, len(probeList.Items)) - } - return nil - }, TestTimeoutLong, TestRetryIntervalMedium).Should(BeNil()) - - for _, probe := range probeList.Items { - Eventually(func() error { - if probe.Name == fmt.Sprintf("%s-%s-%s", TestIPAddressTwo, TestGatewayName, TestHostOne) || - probe.Name == fmt.Sprintf("%s-%s-%s", TestIPAddressOne, TestGatewayName, TestHostOne) { - getProbe := &kuadrantdnsv1alpha1.DNSHealthCheckProbe{} - if err := k8sClient.Get(ctx, client.ObjectKey{Name: probe.Name, Namespace: probe.Namespace}, getProbe); err != nil { - return err - } - patch := client.MergeFrom(getProbe.DeepCopy()) - unhealthy = false - getProbe.Status = kuadrantdnsv1alpha1.DNSHealthCheckProbeStatus{ - LastCheckedAt: metav1.NewTime(time.Now()), - ConsecutiveFailures: *getProbe.Spec.FailureThreshold + 1, - Healthy: &unhealthy, - } - if err := k8sClient.Status().Patch(ctx, getProbe, patch); err != nil { - return err - } - } - return nil - }, TestTimeoutMedium, TestRetryIntervalMedium).Should(BeNil()) - } - createdDNSRecord := &kuadrantdnsv1alpha1.DNSRecord{} - Eventually(func() error { - - err := k8sClient.Get(ctx, client.ObjectKey{Name: recordName, Namespace: testNamespace}, createdDNSRecord) - if err != nil && k8serrors.IsNotFound(err) { - return err - } - if len(createdDNSRecord.Spec.Endpoints) != len(expectedEndpoints) { - return fmt.Errorf("expected %v endpoints in DNSRecord, got %v", len(expectedEndpoints), len(createdDNSRecord.Spec.Endpoints)) - } - return nil - }, TestTimeoutLong, TestRetryIntervalMedium).Should(BeNil()) - Expect(createdDNSRecord.Spec.Endpoints).To(HaveLen(len(expectedEndpoints))) - Expect(createdDNSRecord.Spec.Endpoints).Should(ContainElements(expectedEndpoints)) - }) - }) - Context("some unhealthy probes", func() { - It("should publish expected endpoints", func() { - - expectedEndpoints := []*kuadrantdnsv1alpha1.Endpoint{ - { - DNSName: "2w705o.lb-" + lbHash + ".test.example.com", - Targets: []string{ - TestIPAddressTwo, - }, - RecordType: "A", - SetIdentifier: "", - RecordTTL: 60, - }, - { - DNSName: "s07c46.lb-" + lbHash + ".test.example.com", - Targets: []string{ - TestIPAddressOne, - }, - RecordType: "A", - SetIdentifier: "", - RecordTTL: 60, - }, - { - DNSName: "default.lb-" + lbHash + ".test.example.com", - Targets: []string{ - "2w705o.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "2w705o.lb-" + lbHash + ".test.example.com", - RecordTTL: 60, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "weight", - Value: "120", - }, - }, - }, - { - DNSName: "default.lb-" + lbHash + ".test.example.com", - Targets: []string{ - "s07c46.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "s07c46.lb-" + lbHash + ".test.example.com", - RecordTTL: 60, - Labels: nil, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "weight", - Value: "120", - }, - }, - }, - { - DNSName: "lb-" + lbHash + ".test.example.com", - Targets: []string{ - "default.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "default", - RecordTTL: 300, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "geo-code", - Value: "*", - }, - }, - }, - { - DNSName: "test.example.com", - Targets: []string{ - "lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "", - RecordTTL: 300, - }, - } - - probeList := &kuadrantdnsv1alpha1.DNSHealthCheckProbeList{} - Eventually(func() error { - Expect(k8sClient.List(ctx, probeList, &client.ListOptions{Namespace: testNamespace})).To(BeNil()) - if len(probeList.Items) != 2 { - return fmt.Errorf("expected %v probes, got %v", 2, len(probeList.Items)) - } - return nil - }, TestTimeoutLong, TestRetryIntervalMedium).Should(BeNil()) - Expect(probeList.Items).To(HaveLen(2)) - - Eventually(func() error { - getProbe := &kuadrantdnsv1alpha1.DNSHealthCheckProbe{} - if err := k8sClient.Get(ctx, client.ObjectKey{Name: fmt.Sprintf("%s-%s-%s", TestIPAddressOne, TestGatewayName, TestListenerNameOne), Namespace: testNamespace}, getProbe); err != nil { - return err - } - patch := client.MergeFrom(getProbe.DeepCopy()) - unhealthy = false - getProbe.Status = kuadrantdnsv1alpha1.DNSHealthCheckProbeStatus{ - LastCheckedAt: metav1.NewTime(time.Now()), - ConsecutiveFailures: *getProbe.Spec.FailureThreshold + 1, - Healthy: &unhealthy, - } - if err := k8sClient.Status().Patch(ctx, getProbe, patch); err != nil { - return err - } - return nil - }, TestTimeoutLong, TestRetryIntervalMedium).Should(BeNil()) - - // after that verify that in time the endpoints are 5 in the dnsrecord - createdDNSRecord := &kuadrantdnsv1alpha1.DNSRecord{} - Eventually(func() error { - err := k8sClient.Get(ctx, client.ObjectKey{Name: recordName, Namespace: testNamespace}, createdDNSRecord) - if err != nil && k8serrors.IsNotFound(err) { - return err - } - return nil - }, TestTimeoutMedium, TestRetryIntervalMedium).Should(BeNil()) - Expect(createdDNSRecord.Spec.Endpoints).To(HaveLen(len(expectedEndpoints))) - Expect(createdDNSRecord.Spec.Endpoints).Should(ContainElements(expectedEndpoints)) - }) - }) - Context("some unhealthy endpoints for other listener", func() { - It("should publish expected endpoints", func() { - - expectedEndpoints := []*kuadrantdnsv1alpha1.Endpoint{ - { - DNSName: "2w705o.lb-" + lbHash + ".test.example.com", - Targets: []string{ - TestIPAddressTwo, - }, - RecordType: "A", - SetIdentifier: "", - RecordTTL: 60, - }, - { - DNSName: "s07c46.lb-" + lbHash + ".test.example.com", - Targets: []string{ - TestIPAddressOne, - }, - RecordType: "A", - SetIdentifier: "", - RecordTTL: 60, - }, - { - DNSName: "default.lb-" + lbHash + ".test.example.com", - Targets: []string{ - "2w705o.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "2w705o.lb-" + lbHash + ".test.example.com", - RecordTTL: 60, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "weight", - Value: "120", - }, - }, - }, - { - DNSName: "default.lb-" + lbHash + ".test.example.com", - Targets: []string{ - "s07c46.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "s07c46.lb-" + lbHash + ".test.example.com", - RecordTTL: 60, - Labels: nil, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "weight", - Value: "120", - }, - }, - }, - { - DNSName: "lb-" + lbHash + ".test.example.com", - Targets: []string{ - "default.lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "default", - RecordTTL: 300, - ProviderSpecific: kuadrantdnsv1alpha1.ProviderSpecific{ - { - Name: "geo-code", - Value: "*", - }, - }, - }, - { - DNSName: "test.example.com", - Targets: []string{ - "lb-" + lbHash + ".test.example.com", - }, - RecordType: "CNAME", - SetIdentifier: "", - RecordTTL: 300, - }, - } - - err := k8sClient.Get(ctx, client.ObjectKey{Name: gateway.Name, Namespace: gateway.Namespace}, gateway) - Expect(err).NotTo(HaveOccurred()) - Expect(gateway.Spec.Listeners).NotTo(BeNil()) - // add another listener, should result in 4 probes - typedHostname := gatewayapiv1.Hostname(TestHostTwo) - otherListener := gatewayapiv1.Listener{ - Name: gatewayapiv1.SectionName(TestListenerNameTwo), - Hostname: &typedHostname, - Port: gatewayapiv1.PortNumber(80), - Protocol: gatewayapiv1.HTTPProtocolType, - } - - patch := client.MergeFrom(gateway.DeepCopy()) - gateway.Spec.Listeners = append(gateway.Spec.Listeners, otherListener) - Expect(k8sClient.Patch(ctx, gateway, patch)).To(BeNil()) - - probeList := &kuadrantdnsv1alpha1.DNSHealthCheckProbeList{} - Eventually(func() error { - Expect(k8sClient.List(ctx, probeList, &client.ListOptions{Namespace: testNamespace})).To(BeNil()) - if len(probeList.Items) != 4 { - return fmt.Errorf("expected %v probes, got %v", 4, len(probeList.Items)) - } - return nil - }, TestTimeoutLong, TestRetryIntervalMedium).Should(BeNil()) - Expect(len(probeList.Items)).To(Equal(4)) - - // - Eventually(func() error { - getProbe := &kuadrantdnsv1alpha1.DNSHealthCheckProbe{} - if err = k8sClient.Get(ctx, client.ObjectKey{Name: fmt.Sprintf("%s-%s-%s", TestIPAddressOne, TestGatewayName, TestListenerNameTwo), Namespace: testNamespace}, getProbe); err != nil { - return err - } - patch := client.MergeFrom(getProbe.DeepCopy()) - unhealthy = false - getProbe.Status = kuadrantdnsv1alpha1.DNSHealthCheckProbeStatus{ - LastCheckedAt: metav1.NewTime(time.Now()), - ConsecutiveFailures: *getProbe.Spec.FailureThreshold + 1, - Healthy: &unhealthy, - } - if err = k8sClient.Status().Patch(ctx, getProbe, patch); err != nil { - return err - } - return nil - }, TestTimeoutLong, TestRetryIntervalMedium).Should(BeNil()) - - // after that verify that in time the endpoints are 5 in the dnsrecord - createdDNSRecord := &kuadrantdnsv1alpha1.DNSRecord{} - Eventually(func() error { - err := k8sClient.Get(ctx, client.ObjectKey{Name: recordName, Namespace: testNamespace}, createdDNSRecord) - if err != nil && k8serrors.IsNotFound(err) { - return err - } - return nil - }, TestTimeoutMedium, TestRetryIntervalMedium).Should(BeNil()) - Expect(createdDNSRecord.Spec.Endpoints).To(HaveLen(len(expectedEndpoints))) - Expect(createdDNSRecord.Spec.Endpoints).Should(ContainElements(expectedEndpoints)) - }) - }) - }) - - }) - - }) - -}) diff --git a/controllers/dnspolicy_controller_multi_cluster_test.go b/controllers/dnspolicy_controller_multi_cluster_test.go index a6e7b1d0d..768f3f3bc 100644 --- a/controllers/dnspolicy_controller_multi_cluster_test.go +++ b/controllers/dnspolicy_controller_multi_cluster_test.go @@ -9,6 +9,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" + externaldns "sigs.k8s.io/external-dns/endpoint" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -16,7 +17,10 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" + "github.com/kuadrant/kuadrant-operator/api/v1alpha1" + "github.com/kuadrant/kuadrant-operator/pkg/common" + "github.com/kuadrant/kuadrant-operator/pkg/library/utils" "github.com/kuadrant/kuadrant-operator/pkg/multicluster" ) @@ -27,13 +31,17 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { var testNamespace string var gateway *gatewayapiv1.Gateway var dnsPolicy *v1alpha1.DNSPolicy - var lbHash, recordName, wildcardRecordName string + var ownerID, recordName, wildcardRecordName, clusterTwoIDHash, clusterOneIDHash, gwHash string var ctx context.Context BeforeEach(func() { ctx = context.Background() CreateNamespace(&testNamespace) + var err error + ownerID, err = utils.GetClusterUID(ctx, k8sClient) + Expect(err).To(BeNil()) + gatewayClass = testBuildGatewayClass("foo", "default", "kuadrant.io/bar") Expect(k8sClient.Create(ctx, gatewayClass)).To(Succeed()) @@ -46,6 +54,13 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { Gateway Expect(k8sClient.Create(ctx, gateway)).To(Succeed()) + ownerID = common.ToBase36HashLen(fmt.Sprintf("%s-%s-%s", ownerID, gateway.Name, gateway.Namespace), utils.ClusterIDLength) + + clusterOneIDHash = common.ToBase36HashLen(TestClusterNameOne, utils.ClusterIDLength) + clusterTwoIDHash = common.ToBase36HashLen(TestClusterNameTwo, utils.ClusterIDLength) + + gwHash = common.ToBase36HashLen(gateway.Name+"-"+gateway.Namespace, 6) + //Set multi cluster gateway status Eventually(func() error { gateway.Status.Addresses = []gatewayapiv1.GatewayStatusAddress{ @@ -87,7 +102,6 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { return k8sClient.Status().Update(ctx, gateway) }, TestTimeoutMedium, TestRetryIntervalMedium).ShouldNot(HaveOccurred()) - lbHash = multicluster.ToBase36hash(fmt.Sprintf("%s-%s", gateway.Name, gateway.Namespace)) recordName = fmt.Sprintf("%s-%s", TestGatewayName, TestListenerNameOne) wildcardRecordName = fmt.Sprintf("%s-%s", TestGatewayName, TestListenerNameWildcard) }) @@ -100,7 +114,6 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { if dnsPolicy != nil { err := k8sClient.Delete(ctx, dnsPolicy) Expect(client.IgnoreNotFound(err)).ToNot(HaveOccurred()) - } if managedZone != nil { err := k8sClient.Delete(ctx, managedZone) @@ -133,6 +146,7 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { MatchFields(IgnoreExtras, Fields{ "ObjectMeta": HaveField("Name", recordName), "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), "ManagedZoneRef": HaveField("Name", "mz-example-com"), "Endpoints": ConsistOf( PointTo(MatchFields(IgnoreExtras, Fields{ @@ -140,7 +154,7 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { "Targets": ContainElements(TestIPAddressOne, TestIPAddressTwo), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), ), }), @@ -148,6 +162,7 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { MatchFields(IgnoreExtras, Fields{ "ObjectMeta": HaveField("Name", wildcardRecordName), "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), "ManagedZoneRef": HaveField("Name", "mz-example-com"), "Endpoints": ConsistOf( PointTo(MatchFields(IgnoreExtras, Fields{ @@ -155,7 +170,7 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { "Targets": ContainElements(TestIPAddressOne, TestIPAddressTwo), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), ), }), @@ -184,115 +199,127 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { err := k8sClient.List(ctx, recordList, &client.ListOptions{Namespace: testNamespace}) g.Expect(err).NotTo(HaveOccurred()) g.Expect(recordList.Items).To(HaveLen(2)) - g.Expect(recordList.Items).To( - ContainElements( - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", recordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("2w705o.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf(TestIPAddressTwo), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("default.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("2w705o.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("2w705o.lb-" + lbHash + ".test.example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("default.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("s07c46.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("s07c46.lb-" + lbHash + ".test.example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("s07c46.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf(TestIPAddressOne), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("default.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal(TestHostOne), - "Targets": ConsistOf("lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - })), - ), - }), + + dnsRecord := &kuadrantdnsv1alpha1.DNSRecord{} + err = k8sClient.Get(ctx, client.ObjectKey{Name: recordName, Namespace: testNamespace}, dnsRecord) + g.Expect(err).NotTo(HaveOccurred()) + + wildcardDnsRecord := &kuadrantdnsv1alpha1.DNSRecord{} + err = k8sClient.Get(ctx, client.ObjectKey{Name: wildcardRecordName, Namespace: testNamespace}, wildcardDnsRecord) + g.Expect(err).NotTo(HaveOccurred()) + + g.Expect(*dnsRecord).To( + MatchFields(IgnoreExtras, Fields{ + "ObjectMeta": HaveField("Name", recordName), + "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), + "ManagedZoneRef": HaveField("Name", "mz-example-com"), + "Endpoints": ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), + "Targets": ConsistOf(TestIPAddressTwo), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("default.klb.test.example.com"), + "Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("default.klb.test.example.com"), + "Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), + "Targets": ConsistOf(TestIPAddressOne), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.test.example.com"), + "Targets": ConsistOf("default.klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("default"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(TestHostOne), + "Targets": ConsistOf("klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(300)), + })), + ), }), - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", wildcardRecordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("2w705o.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf(TestIPAddressTwo), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("default.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("2w705o.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("2w705o.lb-" + lbHash + ".example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("default.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("s07c46.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("s07c46.lb-" + lbHash + ".example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("s07c46.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf(TestIPAddressOne), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("default.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal(TestHostWildcard), - "Targets": ConsistOf("lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - })), - ), - }), + }), + ) + g.Expect(*wildcardDnsRecord).To( + MatchFields(IgnoreExtras, Fields{ + "ObjectMeta": HaveField("Name", wildcardRecordName), + "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), + "ManagedZoneRef": HaveField("Name", "mz-example-com"), + "Endpoints": ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), + "Targets": ConsistOf(TestIPAddressTwo), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("default.klb.example.com"), + "Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("default.klb.example.com"), + "Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), + "Targets": ConsistOf(TestIPAddressOne), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.example.com"), + "Targets": ConsistOf("default.klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("default"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(TestHostWildcard), + "Targets": ConsistOf("klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(300)), + })), + ), }), - )) + }), + ) }, TestTimeoutMedium, TestRetryIntervalMedium, ctx).Should(Succeed()) }) @@ -315,134 +342,146 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { err := k8sClient.List(ctx, recordList, &client.ListOptions{Namespace: testNamespace}) g.Expect(err).NotTo(HaveOccurred()) g.Expect(recordList.Items).To(HaveLen(2)) - g.Expect(recordList.Items).To( - ContainElements( - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", recordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("2w705o.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf(TestIPAddressTwo), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("ie.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("2w705o.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("2w705o.lb-" + lbHash + ".test.example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("ie.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("s07c46.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("s07c46.lb-" + lbHash + ".test.example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("s07c46.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf(TestIPAddressOne), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("IE"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal(TestHostOne), - "Targets": ConsistOf("lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - })), - ), - }), + + dnsRecord := &kuadrantdnsv1alpha1.DNSRecord{} + err = k8sClient.Get(ctx, client.ObjectKey{Name: recordName, Namespace: testNamespace}, dnsRecord) + g.Expect(err).NotTo(HaveOccurred()) + + wildcardDnsRecord := &kuadrantdnsv1alpha1.DNSRecord{} + err = k8sClient.Get(ctx, client.ObjectKey{Name: wildcardRecordName, Namespace: testNamespace}, wildcardDnsRecord) + g.Expect(err).NotTo(HaveOccurred()) + + g.Expect(*dnsRecord).To( + MatchFields(IgnoreExtras, Fields{ + "ObjectMeta": HaveField("Name", recordName), + "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), + "ManagedZoneRef": HaveField("Name", "mz-example-com"), + "Endpoints": ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), + "Targets": ConsistOf(TestIPAddressOne), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("ie.klb.test.example.com"), + "Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("ie.klb.test.example.com"), + "Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), + "Targets": ConsistOf(TestIPAddressTwo), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.test.example.com"), + "Targets": ConsistOf("ie.klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("IE"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.test.example.com"), + "Targets": ConsistOf("ie.klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("default"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(TestHostOne), + "Targets": ConsistOf("klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(300)), + })), + ), }), - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", wildcardRecordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("2w705o.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf(TestIPAddressTwo), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("ie.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("2w705o.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("2w705o.lb-" + lbHash + ".example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("ie.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("s07c46.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("s07c46.lb-" + lbHash + ".example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("s07c46.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf(TestIPAddressOne), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("IE"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal(TestHostWildcard), - "Targets": ConsistOf("lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - })), - ), - }), + }), + ) + + g.Expect(*wildcardDnsRecord).To( + MatchFields(IgnoreExtras, Fields{ + "ObjectMeta": HaveField("Name", wildcardRecordName), + "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), + "ManagedZoneRef": HaveField("Name", "mz-example-com"), + "Endpoints": ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), + "Targets": ConsistOf(TestIPAddressOne), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("ie.klb.example.com"), + "Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("ie.klb.example.com"), + "Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), + "Targets": ConsistOf(TestIPAddressTwo), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.example.com"), + "Targets": ConsistOf("ie.klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("IE"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.example.com"), + "Targets": ConsistOf("ie.klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("default"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(TestHostWildcard), + "Targets": ConsistOf("klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(300)), + })), + ), }), - )) + }), + ) }, TestTimeoutMedium, TestRetryIntervalMedium, ctx).Should(Succeed()) }) - }) Context("geo+weighted with custom weights", func() { @@ -499,68 +538,69 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { MatchFields(IgnoreExtras, Fields{ "ObjectMeta": HaveField("Name", recordName), "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), "ManagedZoneRef": HaveField("Name", "mz-example-com"), "Endpoints": ConsistOf( PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("2w705o.lb-" + lbHash + ".test.example.com"), + "DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), "Targets": ConsistOf(TestIPAddressTwo), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("es.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("2w705o.lb-" + lbHash + ".test.example.com"), + "DNSName": Equal("es.klb.test.example.com"), + "Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("2w705o.lb-" + lbHash + ".test.example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "160"}}), + "SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "160"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("ie.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("s07c46.lb-" + lbHash + ".test.example.com"), + "DNSName": Equal("ie.klb.test.example.com"), + "Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("s07c46.lb-" + lbHash + ".test.example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "100"}}), + "SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "100"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("s07c46.lb-" + lbHash + ".test.example.com"), + "DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.test.example.com"), "Targets": ConsistOf(TestIPAddressOne), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("es.lb-" + lbHash + ".test.example.com"), + "DNSName": Equal("klb.test.example.com"), + "Targets": ConsistOf("es.klb.test.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal("ES"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "ES"}}), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "ES"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".test.example.com"), + "DNSName": Equal("klb.test.example.com"), + "Targets": ConsistOf("ie.klb.test.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal("IE"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".test.example.com"), + "DNSName": Equal("klb.test.example.com"), + "Targets": ConsistOf("ie.klb.test.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ "DNSName": Equal(TestHostOne), - "Targets": ConsistOf("lb-" + lbHash + ".test.example.com"), + "Targets": ConsistOf("klb.test.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), + "RecordTTL": Equal(externaldns.TTL(300)), })), ), }), @@ -568,68 +608,69 @@ var _ = Describe("DNSPolicy Multi Cluster", func() { MatchFields(IgnoreExtras, Fields{ "ObjectMeta": HaveField("Name", wildcardRecordName), "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), "ManagedZoneRef": HaveField("Name", "mz-example-com"), "Endpoints": ConsistOf( PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("2w705o.lb-" + lbHash + ".example.com"), + "DNSName": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), "Targets": ConsistOf(TestIPAddressTwo), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("es.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("2w705o.lb-" + lbHash + ".example.com"), + "DNSName": Equal("es.klb.example.com"), + "Targets": ConsistOf(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("2w705o.lb-" + lbHash + ".example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "160"}}), + "SetIdentifier": Equal(clusterTwoIDHash + "-" + gwHash + ".klb.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "160"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("ie.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("s07c46.lb-" + lbHash + ".example.com"), + "DNSName": Equal("ie.klb.example.com"), + "Targets": ConsistOf(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("s07c46.lb-" + lbHash + ".example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "100"}}), + "SetIdentifier": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "100"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("s07c46.lb-" + lbHash + ".example.com"), + "DNSName": Equal(clusterOneIDHash + "-" + gwHash + ".klb.example.com"), "Targets": ConsistOf(TestIPAddressOne), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".example.com"), + "DNSName": Equal("klb.example.com"), + "Targets": ConsistOf("ie.klb.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal("IE"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "IE"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("es.lb-" + lbHash + ".example.com"), + "DNSName": Equal("klb.example.com"), + "Targets": ConsistOf("es.klb.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal("ES"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "ES"}}), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "ES"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("ie.lb-" + lbHash + ".example.com"), + "DNSName": Equal("klb.example.com"), + "Targets": ConsistOf("ie.klb.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), })), PointTo(MatchFields(IgnoreExtras, Fields{ "DNSName": Equal(TestHostWildcard), - "Targets": ConsistOf("lb-" + lbHash + ".example.com"), + "Targets": ConsistOf("klb.example.com"), "RecordType": Equal("CNAME"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), + "RecordTTL": Equal(externaldns.TTL(300)), })), ), }), diff --git a/controllers/dnspolicy_controller_single_cluster_test.go b/controllers/dnspolicy_controller_single_cluster_test.go index 95cbf5533..e1fd0b642 100644 --- a/controllers/dnspolicy_controller_single_cluster_test.go +++ b/controllers/dnspolicy_controller_single_cluster_test.go @@ -9,6 +9,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" + externaldns "sigs.k8s.io/external-dns/endpoint" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -16,8 +17,10 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" + "github.com/kuadrant/kuadrant-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/pkg/multicluster" + "github.com/kuadrant/kuadrant-operator/pkg/common" + "github.com/kuadrant/kuadrant-operator/pkg/library/utils" ) var _ = Describe("DNSPolicy Single Cluster", func() { @@ -27,13 +30,17 @@ var _ = Describe("DNSPolicy Single Cluster", func() { var testNamespace string var gateway *gatewayapiv1.Gateway var dnsPolicy *v1alpha1.DNSPolicy - var lbHash, recordName, wildcardRecordName string + var ownerID, clusterHash, gwHash, recordName, wildcardRecordName string var ctx context.Context BeforeEach(func() { ctx = context.Background() CreateNamespace(&testNamespace) + var err error + clusterUID, err := utils.GetClusterUID(ctx, k8sClient) + Expect(err).To(BeNil()) + gatewayClass = testBuildGatewayClass("foo", "default", "kuadrant.io/bar") Expect(k8sClient.Create(ctx, gatewayClass)).To(Succeed()) @@ -46,6 +53,11 @@ var _ = Describe("DNSPolicy Single Cluster", func() { Gateway Expect(k8sClient.Create(ctx, gateway)).To(Succeed()) + clusterHash = common.ToBase36HashLen(clusterUID, utils.ClusterIDLength) + ownerID = common.ToBase36HashLen(fmt.Sprintf("%s-%s-%s", clusterUID, gateway.Name, gateway.Namespace), utils.ClusterIDLength) + + gwHash = common.ToBase36HashLen(gateway.Name+"-"+gateway.Namespace, 6) + //Set single cluster gateway status Eventually(func() error { gateway.Status.Addresses = []gatewayapiv1.GatewayStatusAddress{ @@ -75,7 +87,6 @@ var _ = Describe("DNSPolicy Single Cluster", func() { return k8sClient.Status().Update(ctx, gateway) }, TestTimeoutMedium, TestRetryIntervalMedium).Should(Succeed()) - lbHash = multicluster.ToBase36hash(fmt.Sprintf("%s-%s", gateway.Name, gateway.Namespace)) recordName = fmt.Sprintf("%s-%s", TestGatewayName, TestListenerNameOne) wildcardRecordName = fmt.Sprintf("%s-%s", TestGatewayName, TestListenerNameWildcard) }) @@ -121,6 +132,7 @@ var _ = Describe("DNSPolicy Single Cluster", func() { MatchFields(IgnoreExtras, Fields{ "ObjectMeta": HaveField("Name", recordName), "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), "ManagedZoneRef": HaveField("Name", "mz-example-com"), "Endpoints": ConsistOf( PointTo(MatchFields(IgnoreExtras, Fields{ @@ -128,7 +140,7 @@ var _ = Describe("DNSPolicy Single Cluster", func() { "Targets": ContainElements(TestIPAddressOne, TestIPAddressTwo), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), ), }), @@ -136,6 +148,7 @@ var _ = Describe("DNSPolicy Single Cluster", func() { MatchFields(IgnoreExtras, Fields{ "ObjectMeta": HaveField("Name", wildcardRecordName), "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), "ManagedZoneRef": HaveField("Name", "mz-example-com"), "Endpoints": ConsistOf( PointTo(MatchFields(IgnoreExtras, Fields{ @@ -143,7 +156,7 @@ var _ = Describe("DNSPolicy Single Cluster", func() { "Targets": ContainElements(TestIPAddressOne, TestIPAddressTwo), "RecordType": Equal("A"), "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), + "RecordTTL": Equal(externaldns.TTL(60)), })), ), }), @@ -169,85 +182,97 @@ var _ = Describe("DNSPolicy Single Cluster", func() { err := k8sClient.List(ctx, recordList, &client.ListOptions{Namespace: testNamespace}) g.Expect(err).NotTo(HaveOccurred()) g.Expect(recordList.Items).To(HaveLen(2)) - g.Expect(recordList.Items).To( - ContainElements( - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", recordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("19sc9b.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf(TestIPAddressOne, TestIPAddressTwo), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("default.lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("19sc9b.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("19sc9b.lb-" + lbHash + ".test.example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".test.example.com"), - "Targets": ConsistOf("default.lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal(TestHostOne), - "Targets": ConsistOf("lb-" + lbHash + ".test.example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - })), - ), - }), + + dnsRecord := &kuadrantdnsv1alpha1.DNSRecord{} + err = k8sClient.Get(ctx, client.ObjectKey{Name: recordName, Namespace: testNamespace}, dnsRecord) + g.Expect(err).NotTo(HaveOccurred()) + + wildcardDnsRecord := &kuadrantdnsv1alpha1.DNSRecord{} + err = k8sClient.Get(ctx, client.ObjectKey{Name: wildcardRecordName, Namespace: testNamespace}, wildcardDnsRecord) + g.Expect(err).NotTo(HaveOccurred()) + + g.Expect(*dnsRecord).To( + MatchFields(IgnoreExtras, Fields{ + "ObjectMeta": HaveField("Name", recordName), + "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), + "ManagedZoneRef": HaveField("Name", "mz-example-com"), + "Endpoints": ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterHash + "-" + gwHash + "." + "klb.test.example.com"), + "Targets": ConsistOf(TestIPAddressOne, TestIPAddressTwo), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("default." + "klb.test.example.com"), + "Targets": ConsistOf(clusterHash + "-" + gwHash + "." + "klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterHash + "-" + gwHash + "." + "klb.test.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.test.example.com"), + "Targets": ConsistOf("default." + "klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("default"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(TestHostOne), + "Targets": ConsistOf("klb.test.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(300)), + })), + ), }), - MatchFields(IgnoreExtras, Fields{ - "ObjectMeta": HaveField("Name", wildcardRecordName), - "Spec": MatchFields(IgnoreExtras, Fields{ - "ManagedZoneRef": HaveField("Name", "mz-example-com"), - "Endpoints": ContainElements( - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("19sc9b.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf(TestIPAddressOne, TestIPAddressTwo), - "RecordType": Equal("A"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("default.lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("19sc9b.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("19sc9b.lb-" + lbHash + ".example.com"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(60)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "weight", Value: "120"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal("lb-" + lbHash + ".example.com"), - "Targets": ConsistOf("default.lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal("default"), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - "ProviderSpecific": Equal(kuadrantdnsv1alpha1.ProviderSpecific{{Name: "geo-code", Value: "*"}}), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "DNSName": Equal(TestHostWildcard), - "Targets": ConsistOf("lb-" + lbHash + ".example.com"), - "RecordType": Equal("CNAME"), - "SetIdentifier": Equal(""), - "RecordTTL": Equal(kuadrantdnsv1alpha1.TTL(300)), - })), - ), - }), + }), + ) + g.Expect(*wildcardDnsRecord).To( + MatchFields(IgnoreExtras, Fields{ + "ObjectMeta": HaveField("Name", wildcardRecordName), + "Spec": MatchFields(IgnoreExtras, Fields{ + "OwnerID": Equal(&ownerID), + "ManagedZoneRef": HaveField("Name", "mz-example-com"), + "Endpoints": ContainElements( + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(clusterHash + "-" + gwHash + "." + "klb.example.com"), + "Targets": ConsistOf(TestIPAddressOne, TestIPAddressTwo), + "RecordType": Equal("A"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(60)), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("default." + "klb.example.com"), + "Targets": ConsistOf(clusterHash + "-" + gwHash + "." + "klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(clusterHash + "-" + gwHash + "." + "klb.example.com"), + "RecordTTL": Equal(externaldns.TTL(60)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "weight", Value: "120"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal("klb.example.com"), + "Targets": ConsistOf("default." + "klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal("default"), + "RecordTTL": Equal(externaldns.TTL(300)), + "ProviderSpecific": Equal(externaldns.ProviderSpecific{{Name: "geo-code", Value: "*"}}), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "DNSName": Equal(TestHostWildcard), + "Targets": ConsistOf("klb.example.com"), + "RecordType": Equal("CNAME"), + "SetIdentifier": Equal(""), + "RecordTTL": Equal(externaldns.TTL(300)), + })), + ), }), - )) + }), + ) }, TestTimeoutMedium, TestRetryIntervalMedium, ctx).Should(Succeed()) }) diff --git a/controllers/dnspolicy_controller_test.go b/controllers/dnspolicy_controller_test.go index b31862ce3..8c31c21ef 100644 --- a/controllers/dnspolicy_controller_test.go +++ b/controllers/dnspolicy_controller_test.go @@ -122,30 +122,6 @@ var _ = Describe("DNSPolicy controller", func() { }, TestTimeoutMedium, time.Second).Should(Succeed()) }) - It("should not have any health check records created", func() { - // create a health check with the labels for the dnspolicy and the gateway name and namespace that would be expected in a valid target scenario - // this one should get deleted if the gateway is invalid policy ref - probe := &kuadrantdnsv1alpha1.DNSHealthCheckProbe{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-%s", TestIPAddressTwo, TestGatewayName, TestHostTwo), - Namespace: testNamespace, - Labels: map[string]string{ - v1alpha1.DNSPolicyDirectReferenceAnnotationName: "test-dns-policy", - fmt.Sprintf("%s-namespace", v1alpha1.DNSPolicyDirectReferenceAnnotationName): testNamespace, - LabelGatewayNSRef: testNamespace, - LabelGatewayReference: "test-gateway", - }, - }, - } - Expect(k8sClient.Create(ctx, probe)).To(Succeed()) - - Eventually(func(g Gomega) { // probe should be removed - err := k8sClient.Get(ctx, client.ObjectKey{Name: probe.Name, Namespace: probe.Namespace}, &kuadrantdnsv1alpha1.DNSHealthCheckProbe{}) - g.Expect(err).To(HaveOccurred()) - g.Expect(err).To(MatchError(ContainSubstring("not found"))) - }, TestTimeoutMedium, time.Second).Should(Succeed()) - }) - It("should not process gateway with inconsistent addresses", func() { // build invalid gateway gateway = NewGatewayBuilder("test-gateway", gatewayClass.Name, testNamespace). diff --git a/controllers/dnspolicy_dnsrecords.go b/controllers/dnspolicy_dnsrecords.go index e11ac83d9..7a994d7ad 100644 --- a/controllers/dnspolicy_dnsrecords.go +++ b/controllers/dnspolicy_dnsrecords.go @@ -14,10 +14,10 @@ import ( kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" + "github.com/kuadrant/kuadrant-operator/api/v1alpha1" + "github.com/kuadrant/kuadrant-operator/pkg/common" reconcilerutils "github.com/kuadrant/kuadrant-operator/pkg/library/reconcilers" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" - - "github.com/kuadrant/kuadrant-operator/api/v1alpha1" "github.com/kuadrant/kuadrant-operator/pkg/multicluster" ) @@ -44,8 +44,11 @@ func (r *DNSPolicyReconciler) reconcileDNSRecords(ctx context.Context, dnsPolicy func (r *DNSPolicyReconciler) reconcileGatewayDNSRecords(ctx context.Context, gw *gatewayapiv1.Gateway, dnsPolicy *v1alpha1.DNSPolicy) error { log := crlog.FromContext(ctx) - - gatewayWrapper := multicluster.NewGatewayWrapper(gw) + clusterID, err := utils.GetClusterUID(ctx, r.Client()) + if err != nil { + return fmt.Errorf("failed to generate cluster ID: %w", err) + } + gatewayWrapper := multicluster.NewGatewayWrapper(gw, clusterID) if err := gatewayWrapper.Validate(); err != nil { return err } @@ -90,7 +93,7 @@ func (r *DNSPolicyReconciler) reconcileGatewayDNSRecords(ctx context.Context, gw return nil } - dnsRecord, err := r.desiredDNSRecord(ctx, gatewayWrapper.Gateway, dnsPolicy, listener, listenerGateways, mz) + dnsRecord, err := r.desiredDNSRecord(gatewayWrapper, dnsPolicy, listener, listenerGateways, mz) if err != nil { return err } @@ -109,7 +112,21 @@ func (r *DNSPolicyReconciler) reconcileGatewayDNSRecords(ctx context.Context, gw return nil } -func (r *DNSPolicyReconciler) desiredDNSRecord(ctx context.Context, gateway *gatewayapiv1.Gateway, dnsPolicy *v1alpha1.DNSPolicy, targetListener gatewayapiv1.Listener, clusterGateways []multicluster.ClusterGateway, managedZone *kuadrantdnsv1alpha1.ManagedZone) (*kuadrantdnsv1alpha1.DNSRecord, error) { +func (r *DNSPolicyReconciler) desiredDNSRecord(gateway *multicluster.GatewayWrapper, dnsPolicy *v1alpha1.DNSPolicy, targetListener gatewayapiv1.Listener, clusterGateways []multicluster.ClusterGateway, managedZone *kuadrantdnsv1alpha1.ManagedZone) (*kuadrantdnsv1alpha1.DNSRecord, error) { + ownerID := common.ToBase36HashLen(fmt.Sprintf("%s-%s-%s", gateway.ClusterID, gateway.Name, gateway.Namespace), utils.ClusterIDLength) + rootHost := string(*targetListener.Hostname) + var healthProtocol *string + var healthCheckSpec *kuadrantdnsv1alpha1.HealthCheckSpec + + if dnsPolicy.Spec.HealthCheck != nil { + healthProtocol = dnsPolicy.Spec.HealthCheck.Protocol + healthCheckSpec = &kuadrantdnsv1alpha1.HealthCheckSpec{ + Endpoint: dnsPolicy.Spec.HealthCheck.Endpoint, + Port: dnsPolicy.Spec.HealthCheck.Port, + Protocol: (*kuadrantdnsv1alpha1.HealthProtocol)(healthProtocol), + FailureThreshold: dnsPolicy.Spec.HealthCheck.FailureThreshold, + } + } dnsRecord := &kuadrantdnsv1alpha1.DNSRecord{ ObjectMeta: metav1.ObjectMeta{ Name: dnsRecordName(gateway.Name, string(targetListener.Name)), @@ -117,24 +134,21 @@ func (r *DNSPolicyReconciler) desiredDNSRecord(ctx context.Context, gateway *gat Labels: commonDNSRecordLabels(client.ObjectKeyFromObject(gateway), dnsPolicy), }, Spec: kuadrantdnsv1alpha1.DNSRecordSpec{ + OwnerID: &ownerID, + RootHost: &rootHost, ManagedZoneRef: &kuadrantdnsv1alpha1.ManagedZoneReference{ Name: managedZone.Name, }, + HealthCheck: healthCheckSpec, }, } dnsRecord.Labels[LabelListenerReference] = string(targetListener.Name) - mcgTarget, err := multicluster.NewGatewayTarget(gateway, clusterGateways, dnsPolicy.Spec.LoadBalancing) + mcgTarget, err := multicluster.NewGatewayTarget(gateway.Gateway, clusterGateways, dnsPolicy.Spec.LoadBalancing) if err != nil { return nil, fmt.Errorf("failed to create multi cluster gateway target for listener %s : %w", targetListener.Name, err) } - probes, err := r.dnsHelper.getDNSHealthCheckProbes(ctx, mcgTarget.Gateway, dnsPolicy) - if err != nil { - return nil, err - } - mcgTarget.RemoveUnhealthyGatewayAddresses(probes, targetListener) - if err = r.dnsHelper.setEndpoints(mcgTarget, dnsRecord, targetListener, dnsPolicy.Spec.RoutingStrategy); err != nil { return nil, fmt.Errorf("failed to add dns record dnsTargets %w %v", err, mcgTarget) } diff --git a/controllers/dnspolicy_healthchecks.go b/controllers/dnspolicy_healthchecks.go deleted file mode 100644 index 8eab4bef4..000000000 --- a/controllers/dnspolicy_healthchecks.go +++ /dev/null @@ -1,185 +0,0 @@ -package controllers - -import ( - "context" - "fmt" - "slices" - "strings" - "time" - - k8serror "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "sigs.k8s.io/controller-runtime/pkg/client" - crlog "sigs.k8s.io/controller-runtime/pkg/log" - gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - - kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" - - "github.com/kuadrant/kuadrant-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" - reconcilerutils "github.com/kuadrant/kuadrant-operator/pkg/library/reconcilers" - "github.com/kuadrant/kuadrant-operator/pkg/multicluster" -) - -func (r *DNSPolicyReconciler) reconcileHealthCheckProbes(ctx context.Context, dnsPolicy *v1alpha1.DNSPolicy, gwDiffObj *reconcilerutils.GatewayDiffs) error { - log := crlog.FromContext(ctx) - - log.V(3).Info("reconciling health checks") - for _, gw := range gwDiffObj.GatewaysWithInvalidPolicyRef { - log.V(1).Info("reconcileHealthCheckProbes: gateway with invalid policy ref", "key", gw.Key()) - if err := r.deleteGatewayHealthCheckProbes(ctx, gw.Gateway, dnsPolicy); err != nil { - return fmt.Errorf("error deleting probes for gw %v: %w", gw.Gateway.Name, err) - } - } - - // Reconcile DNSHealthCheckProbes for each gateway directly referred by the policy (existing and new) - for _, gw := range append(gwDiffObj.GatewaysWithValidPolicyRef, gwDiffObj.GatewaysMissingPolicyRef...) { - log.V(3).Info("reconciling probes", "gateway", gw.Name) - expectedProbes := r.expectedHealthCheckProbesForGateway(ctx, gw, dnsPolicy) - if err := r.createOrUpdateHealthCheckProbes(ctx, expectedProbes); err != nil { - return fmt.Errorf("error creating or updating expected probes for gateway %v: %w", gw.Gateway.Name, err) - } - if err := r.deleteUnexpectedGatewayHealthCheckProbes(ctx, expectedProbes, gw.Gateway, dnsPolicy); err != nil { - return fmt.Errorf("error removing unexpected probes for gateway %v: %w", gw.Gateway.Name, err) - } - } - return nil -} - -func (r *DNSPolicyReconciler) createOrUpdateHealthCheckProbes(ctx context.Context, expectedProbes []*kuadrantdnsv1alpha1.DNSHealthCheckProbe) error { - //create or update all expected probes - for _, hcProbe := range expectedProbes { - p := &kuadrantdnsv1alpha1.DNSHealthCheckProbe{} - if err := r.Client().Get(ctx, client.ObjectKeyFromObject(hcProbe), p); k8serror.IsNotFound(err) { - if err := r.Client().Create(ctx, hcProbe); err != nil { - return err - } - } else if client.IgnoreNotFound(err) == nil { - p.Spec = hcProbe.Spec - if err := r.Client().Update(ctx, p); err != nil { - return err - } - } else { - return err - } - } - - return nil -} - -func (r *DNSPolicyReconciler) deleteGatewayHealthCheckProbes(ctx context.Context, gateway *gatewayapiv1.Gateway, dnsPolicy *v1alpha1.DNSPolicy) error { - return r.deleteHealthCheckProbesWithLabels(ctx, commonDNSRecordLabels(client.ObjectKeyFromObject(gateway), dnsPolicy), dnsPolicy.Namespace) -} - -func (r *DNSPolicyReconciler) deleteHealthCheckProbes(ctx context.Context, dnsPolicy *v1alpha1.DNSPolicy) error { - return r.deleteHealthCheckProbesWithLabels(ctx, policyDNSRecordLabels(dnsPolicy), dnsPolicy.Namespace) -} - -func (r *DNSPolicyReconciler) deleteHealthCheckProbesWithLabels(ctx context.Context, lbls map[string]string, namespace string) error { - probes := &kuadrantdnsv1alpha1.DNSHealthCheckProbeList{} - listOptions := &client.ListOptions{LabelSelector: labels.SelectorFromSet(lbls), Namespace: namespace} - if err := r.Client().List(ctx, probes, listOptions); client.IgnoreNotFound(err) != nil { - return err - } - for i := range probes.Items { - if err := r.Client().Delete(ctx, &probes.Items[i]); err != nil { - return err - } - } - return nil -} - -func (r *DNSPolicyReconciler) deleteUnexpectedGatewayHealthCheckProbes(ctx context.Context, expectedProbes []*kuadrantdnsv1alpha1.DNSHealthCheckProbe, gateway *gatewayapiv1.Gateway, dnsPolicy *v1alpha1.DNSPolicy) error { - // remove any probes for this gateway and DNS Policy that are no longer expected - existingProbes := &kuadrantdnsv1alpha1.DNSHealthCheckProbeList{} - dnsLabels := commonDNSRecordLabels(client.ObjectKeyFromObject(gateway), dnsPolicy) - listOptions := &client.ListOptions{LabelSelector: labels.SelectorFromSet(dnsLabels)} - if err := r.Client().List(ctx, existingProbes, listOptions); client.IgnoreNotFound(err) != nil { - return err - } - for i, p := range existingProbes.Items { - if !slices.ContainsFunc(expectedProbes, func(expectedProbe *kuadrantdnsv1alpha1.DNSHealthCheckProbe) bool { - return expectedProbe.Name == p.Name && expectedProbe.Namespace == p.Namespace - }) { - if err := r.Client().Delete(ctx, &existingProbes.Items[i]); err != nil { - return err - } - } - } - return nil -} - -func (r *DNSPolicyReconciler) expectedHealthCheckProbesForGateway(ctx context.Context, gw kuadrant.GatewayWrapper, dnsPolicy *v1alpha1.DNSPolicy) []*kuadrantdnsv1alpha1.DNSHealthCheckProbe { - log := crlog.FromContext(ctx) - var healthChecks []*kuadrantdnsv1alpha1.DNSHealthCheckProbe - if dnsPolicy.Spec.HealthCheck == nil { - log.V(3).Info("DNS Policy has no defined health check") - return healthChecks - } - - interval := metav1.Duration{Duration: 60 * time.Second} - if dnsPolicy.Spec.HealthCheck.Interval != nil { - interval = *dnsPolicy.Spec.HealthCheck.Interval - } - - gatewayWrapper := multicluster.NewGatewayWrapper(gw.Gateway) - if err := gatewayWrapper.Validate(); err != nil { - return nil - } - - clusterGatewayAddresses := gatewayWrapper.GetClusterGatewayAddresses() - - for _, listener := range gw.Spec.Listeners { - //skip wildcard listeners - if strings.Contains(string(*listener.Hostname), "*") { - continue - } - - port := dnsPolicy.Spec.HealthCheck.Port - if port == nil { - listenerPort := int(listener.Port) - port = &listenerPort - } - - var protocol string - // handle protocol being nil - if dnsPolicy.Spec.HealthCheck.Protocol == nil { - protocol = string(listener.Protocol) - } else { - protocol = string(*dnsPolicy.Spec.HealthCheck.Protocol) - } - - for _, addresses := range clusterGatewayAddresses { - for _, address := range addresses { - log.V(1).Info("reconcileHealthCheckProbes: adding health check for target", "target", address.Value) - healthCheck := &kuadrantdnsv1alpha1.DNSHealthCheckProbe{ - ObjectMeta: metav1.ObjectMeta{ - Name: dnsHealthCheckProbeName(address.Value, gw.Name, string(listener.Name)), - Namespace: gw.Namespace, - Labels: commonDNSRecordLabels(client.ObjectKeyFromObject(gw), dnsPolicy), - }, - Spec: kuadrantdnsv1alpha1.DNSHealthCheckProbeSpec{ - Port: *port, - Host: string(*listener.Hostname), - Address: address.Value, - Path: dnsPolicy.Spec.HealthCheck.Endpoint, - Protocol: kuadrantdnsv1alpha1.HealthProtocol(protocol), - Interval: interval, - AdditionalHeadersRef: dnsPolicy.Spec.HealthCheck.AdditionalHeadersRef, - FailureThreshold: dnsPolicy.Spec.HealthCheck.FailureThreshold, - ExpectedResponses: dnsPolicy.Spec.HealthCheck.ExpectedResponses, - AllowInsecureCertificate: dnsPolicy.Spec.HealthCheck.AllowInsecureCertificates, - }, - } - healthChecks = append(healthChecks, withGatewayListener(gw, listener, healthCheck)) - } - } - } - - return healthChecks -} - -func dnsHealthCheckProbeName(address, gatewayName, listenerName string) string { - return fmt.Sprintf("%s-%s", address, dnsRecordName(gatewayName, listenerName)) -} diff --git a/examples/dnspolicy/application.yaml b/examples/dnspolicy/application.yaml new file mode 100644 index 000000000..b5d2924b7 --- /dev/null +++ b/examples/dnspolicy/application.yaml @@ -0,0 +1,50 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: my-route +spec: + parentRefs: + - kind: Gateway + name: prod-web-istio + namespace: gateway + hostnames: + - "app.${KUADRANT_ZONE_ROOT_DOMAIN}" + rules: + - backendRefs: + - name: echo + port: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: echo +spec: + ports: + - name: http-port + port: 8080 + targetPort: http-port + protocol: TCP + selector: + app: echo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: echo +spec: + replicas: 1 + selector: + matchLabels: + app: echo + template: + metadata: + labels: + app: echo + spec: + containers: + - name: echo + image: docker.io/jmalloc/echo-server + ports: + - name: http-port + containerPort: 8080 + protocol: TCP diff --git a/examples/dnspolicy/dnspolicy.yaml b/examples/dnspolicy/dnspolicy.yaml new file mode 100644 index 000000000..5e2fcf3a9 --- /dev/null +++ b/examples/dnspolicy/dnspolicy.yaml @@ -0,0 +1,16 @@ +apiVersion: kuadrant.io/v1alpha1 +kind: DNSPolicy +metadata: + name: prod-web + namespace: gateway +spec: + targetRef: + name: prod-web-istio + group: gateway.networking.k8s.io + kind: Gateway + routingStrategy: loadbalanced + healthCheck: + endpoint: "/" + port: 443 + protocol: "HTTPS" + failureThreshold: 5 diff --git a/examples/dnspolicy/gateway.yaml b/examples/dnspolicy/gateway.yaml new file mode 100644 index 000000000..5748ccf63 --- /dev/null +++ b/examples/dnspolicy/gateway.yaml @@ -0,0 +1,20 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: prod-web-istio + namespace: gateway +spec: + gatewayClassName: istio + listeners: + - allowedRoutes: + namespaces: + from: All + name: api + hostname: app.${KUADRANT_ZONE_ROOT_DOMAIN} + port: 443 + protocol: HTTPS + tls: + mode: Terminate + certificateRefs: + - name: example-app-tls + kind: Secret diff --git a/examples/dnspolicy/managedzone.yaml b/examples/dnspolicy/managedzone.yaml new file mode 100644 index 000000000..abb8a1877 --- /dev/null +++ b/examples/dnspolicy/managedzone.yaml @@ -0,0 +1,22 @@ +apiVersion: kuadrant.io/v1alpha1 +kind: ManagedZone +metadata: + name: ${KUADRANT_ZONE_ROOT_DOMAIN} + namespace: gateway +spec: + id: ${KUADRANT_AWS_DNS_PUBLIC_ZONE_ID} + domainName: ${KUADRANT_ZONE_ROOT_DOMAIN} + description: "${KUADRANT_ZONE_ROOT_DOMAIN} managed domain" + dnsProviderSecretRef: + name: aws-credentials +--- +apiVersion: v1 +kind: Secret +metadata: + name: aws-credentials + namespace: gateway +type: "kuadrant.io/aws" +stringData: + AWS_ACCESS_KEY_ID: ${KUADRANT_AWS_ACCESS_KEY_ID} + AWS_SECRET_ACCESS_KEY: ${KUADRANT_AWS_SECRET_ACCESS_KEY} + AWS_REGION: ${KUADRANT_AWS_REGION} diff --git a/examples/dnspolicy/script.sh b/examples/dnspolicy/script.sh new file mode 100755 index 000000000..4362e98a0 --- /dev/null +++ b/examples/dnspolicy/script.sh @@ -0,0 +1,5 @@ +kubectl create ns gateway +envsubst < examples/dnspolicy/managedzone.yaml | kubectl apply -f - +envsubst < examples/dnspolicy/gateway.yaml | kubectl apply -f - +envsubst < examples/dnspolicy/dnspolicy.yaml | kubectl apply -f - +envsubst < examples/dnspolicy/application.yaml | kubectl apply -f - diff --git a/go.mod b/go.mod index 3ec8bfd4f..2a4adfd2e 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/uuid v1.4.0 github.com/kuadrant/authorino v0.15.0 github.com/kuadrant/authorino-operator v0.9.0 - github.com/kuadrant/dns-operator v0.1.0 + github.com/kuadrant/dns-operator v0.0.0-20240405095001-9e88ad4a7303 github.com/kuadrant/limitador-operator v0.7.0 github.com/martinlindhe/base36 v1.1.1 github.com/onsi/ginkgo/v2 v2.13.2 @@ -31,6 +31,7 @@ require ( k8s.io/utils v0.0.0-20231127182322-b307cd553661 maistra.io/istio-operator v0.0.0-20231214211859-76e404c8df41 sigs.k8s.io/controller-runtime v0.16.3 + sigs.k8s.io/external-dns v0.14.0 sigs.k8s.io/gateway-api v1.0.1-0.20231204134048-c7da42e6eafc ) @@ -45,6 +46,7 @@ require ( github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/aws/aws-sdk-go v1.44.311 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect @@ -92,6 +94,7 @@ require ( github.com/huandu/xstrings v1.4.0 // indirect github.com/imdario/mergo v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect diff --git a/go.sum b/go.sum index e37845328..4e4316aac 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.44.311 h1:60i8hyVMOXqabKJQPCq4qKRBQ6hRafI/WOcDxGM+J7Q= +github.com/aws/aws-sdk-go v1.44.311/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -221,6 +223,10 @@ github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -250,8 +256,8 @@ github.com/kuadrant/authorino v0.15.0 h1:Xw/buh/wTINdL+IpLSxhlpet4hpleMxZzfx39c4 github.com/kuadrant/authorino v0.15.0/go.mod h1:vXkHKrntn8DR7kt8a8Ohxq+2lgAD0jWivThoP+7ASew= github.com/kuadrant/authorino-operator v0.9.0 h1:EV7zrYBNcd53HPQMivvTwe/+DIATTK7O4znJzh4xON8= github.com/kuadrant/authorino-operator v0.9.0/go.mod h1:VkUqS4CHNiaHMrjSFQ5V71DN829kPnqT3FQxqlOntEI= -github.com/kuadrant/dns-operator v0.1.0 h1:MlSKdzNejuxDFhIjn6/OFcdYnLyMo95SRMlFs5WZZ+A= -github.com/kuadrant/dns-operator v0.1.0/go.mod h1:qmqqpvIRFewuTWd4kox/udz32hW7TQsE7Wvd45Eea18= +github.com/kuadrant/dns-operator v0.0.0-20240405095001-9e88ad4a7303 h1:3PFrKndF/xDHXbCCVX4W7Y6ir5oNw+hxuyBmwRb2hKM= +github.com/kuadrant/dns-operator v0.0.0-20240405095001-9e88ad4a7303/go.mod h1:xT10T4H3uCXkB+xpW0KP9yb/k3zNAA2OXW9WR9j38kA= github.com/kuadrant/limitador-operator v0.7.0 h1:pLIpM6vUxAY/Jn6ny61IGpqS7Oti786duBzJ67DJOuA= github.com/kuadrant/limitador-operator v0.7.0/go.mod h1:tg+G+3eTzUUfvUmdbiqH3FnScEPSWZ3DmorD1ZAx1bo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -386,8 +392,8 @@ github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzF github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -502,6 +508,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= @@ -531,12 +538,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= @@ -633,6 +642,8 @@ oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY= oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324= sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +sigs.k8s.io/external-dns v0.14.0 h1:pgY3DdyoBei+ej1nyZUzRt9ECm9RRwb9s6/CPWe51tc= +sigs.k8s.io/external-dns v0.14.0/go.mod h1:d4Knr/BFz8U1Lc6yLhCzTRP6nJOz6fqR/MnqqJPcIlU= sigs.k8s.io/gateway-api v1.0.1-0.20231204134048-c7da42e6eafc h1:Ls/BrmdKJVBi4LVYhK4a4xA+5TO0mt66f6UpgTHk2Lc= sigs.k8s.io/gateway-api v1.0.1-0.20231204134048-c7da42e6eafc/go.mod h1:i4fiyKUGk0zC7PIaoykdwjfOePLpLIGGX9iab7uhl0o= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/pkg/common/common.go b/pkg/common/common.go index 77d519519..68312ce2c 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -17,9 +17,11 @@ limitations under the License. package common import ( + "crypto/sha256" "fmt" "strings" + "github.com/martinlindhe/base36" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -80,3 +82,13 @@ func UnMarshallObjectKey(keyStr string) (client.ObjectKey, error) { return client.ObjectKey{Namespace: keyStr[:namespaceEndIndex], Name: keyStr[namespaceEndIndex+1:]}, nil } + +func ToBase36Hash(s string) string { + hash := sha256.Sum224([]byte(s)) + // convert the hash to base36 (alphanumeric) to decrease collision probabilities + return strings.ToLower(base36.EncodeBytes(hash[:])) +} + +func ToBase36HashLen(s string, l int) string { + return ToBase36Hash(s)[:l] +} diff --git a/pkg/library/utils/k8s_utils.go b/pkg/library/utils/k8s_utils.go index 5e86a7c0c..6c42e85ff 100644 --- a/pkg/library/utils/k8s_utils.go +++ b/pkg/library/utils/k8s_utils.go @@ -17,11 +17,13 @@ limitations under the License. package utils import ( + "context" "encoding/json" "fmt" "sort" appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" @@ -29,8 +31,12 @@ import ( const ( DeleteTagAnnotation = "kuadrant.io/delete" + ClusterIDLength = 6 + clusterIDNamespace = "kube-system" ) +var clusterUID string + // ObjectInfo generates a string representation of the provided Kubernetes object, including its kind and name. // The generated string follows the format: "kind/name". func ObjectInfo(obj client.Object) string { @@ -147,3 +153,18 @@ func GetLabel(obj metav1.Object, key string) string { } return obj.GetLabels()[key] } + +func GetClusterUID(ctx context.Context, c client.Client) (string, error) { + //Already calculated? return it + if clusterUID != "" { + return clusterUID, nil + } + + ns := &corev1.Namespace{} + err := c.Get(ctx, client.ObjectKey{Name: clusterIDNamespace}, ns) + if err != nil { + return "", err + } + clusterUID = string(ns.UID) + return clusterUID, nil +} diff --git a/pkg/library/utils/k8s_utils_test.go b/pkg/library/utils/k8s_utils_test.go index 1ed983553..3c1c0b131 100644 --- a/pkg/library/utils/k8s_utils_test.go +++ b/pkg/library/utils/k8s_utils_test.go @@ -11,6 +11,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -847,3 +848,49 @@ func TestGetLabel(t *testing.T) { }) } } + +func TestGetClusterUID(t *testing.T) { + var testCases = []struct { + Name string + Objects []client.Object + Validation func(t *testing.T, e error, id string) + }{ + { + Name: "an absent namespace generates an error", + Objects: []client.Object{}, + Validation: func(t *testing.T, e error, id string) { + if !errors.IsNotFound(e) { + t.Errorf("expected not found error, got '%v'", e) + } + }, + }, + { + Name: "a UID generates a valid deterministic cluster ID", + Objects: []client.Object{ + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterIDNamespace, + UID: "random-uid", + }, + }, + }, + Validation: func(t *testing.T, e error, id string) { + if e != nil { + t.Errorf("unexpected error, got '%v', expected nil", e) + } + + if id != "random-uid" { + t.Errorf("unexpected cluster ID got '%s', expected 'random-uid'", id) + } + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + fc := fake.NewClientBuilder().WithObjects(testCase.Objects...).Build() + id, err := GetClusterUID(context.Background(), fc) + testCase.Validation(t, err, id) + }) + } +} diff --git a/pkg/multicluster/gateway_wrapper.go b/pkg/multicluster/gateway_wrapper.go index 2ad4cf26b..91326611f 100644 --- a/pkg/multicluster/gateway_wrapper.go +++ b/pkg/multicluster/gateway_wrapper.go @@ -17,10 +17,11 @@ const ( type GatewayWrapper struct { *gatewayapiv1.Gateway + ClusterID string } -func NewGatewayWrapper(g *gatewayapiv1.Gateway) *GatewayWrapper { - return &GatewayWrapper{Gateway: g} +func NewGatewayWrapper(g *gatewayapiv1.Gateway, clusterID string) *GatewayWrapper { + return &GatewayWrapper{Gateway: g, ClusterID: clusterID} } func isMultiClusterAddressType(addressType gatewayapiv1.AddressType) bool { @@ -150,7 +151,7 @@ func (g *GatewayWrapper) GetClusterGateways() []ClusterGateway { return []ClusterGateway{ { Gateway: *g.Gateway, - ClusterName: g.GetName(), + ClusterName: g.ClusterID, }, } } diff --git a/pkg/multicluster/target.go b/pkg/multicluster/target.go index 03b52f4d9..b496ca981 100644 --- a/pkg/multicluster/target.go +++ b/pkg/multicluster/target.go @@ -1,19 +1,15 @@ package multicluster import ( - "crypto/sha256" "fmt" - "strings" - - "github.com/martinlindhe/base36" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/api/v1alpha1" + "github.com/kuadrant/kuadrant-operator/pkg/common" + "github.com/kuadrant/kuadrant-operator/pkg/library/utils" ) const ( @@ -38,7 +34,7 @@ func (t *GatewayTarget) GetName() string { } func (t *GatewayTarget) GetShortCode() string { - return ToBase36hash(t.GetName()) + return common.ToBase36HashLen(t.GetName(), utils.ClusterIDLength) } // GroupTargetsByGeo groups targets based on Geo Code. @@ -113,7 +109,7 @@ func (t *ClusterGatewayTarget) GetName() string { } func (t *ClusterGatewayTarget) GetShortCode() string { - return ToBase36hash(t.GetName()) + return common.ToBase36HashLen(t.GetName(), utils.ClusterIDLength) } func (t *ClusterGatewayTarget) setGeo(defaultGeo v1alpha1.GeoCode) { @@ -128,61 +124,6 @@ func (t *ClusterGatewayTarget) setGeo(defaultGeo v1alpha1.GeoCode) { t.Geo = &geoCode } -func (t *GatewayTarget) RemoveUnhealthyGatewayAddresses(probes []*kuadrantdnsv1alpha1.DNSHealthCheckProbe, listener gatewayapiv1.Listener) { - //If we have no probes we can't determine health so return unmodified - if len(probes) == 0 { - return - } - - //Build a map of gateway addresses and their health status - gwAddressHealth := map[string]bool{} - allunhealthy := true - for _, cgt := range t.ClusterGatewayTargets { - for _, gwa := range cgt.Status.Addresses { - probe := getProbeForGatewayAddress(probes, gatewayapiv1.GatewayAddress(gwa), t.Gateway.Name, string(listener.Name)) - if probe == nil { - continue - } - probeHealthy := true - if probe.Status.Healthy != nil { - probeHealthy = *probe.Status.Healthy - } - if probeHealthy && probe.Spec.FailureThreshold != nil && probe.Status.ConsecutiveFailures < *probe.Spec.FailureThreshold { - allunhealthy = false - } - gwAddressHealth[gwa.Value] = probeHealthy - } - } - //If we have no matching probes for our current addresses, or we have no healthy probes, return unmodified - if len(gwAddressHealth) == 0 || allunhealthy { - return - } - - // Remove all unhealthy addresses, we know by this point at least one of our addresses is healthy - for _, cgt := range t.ClusterGatewayTargets { - healthyAddresses := []gatewayapiv1.GatewayStatusAddress{} - for _, gwa := range cgt.Status.Addresses { - if healthy, exists := gwAddressHealth[gwa.Value]; exists && healthy { - healthyAddresses = append(healthyAddresses, gwa) - } - } - cgt.Status.Addresses = healthyAddresses - } -} - -func getProbeForGatewayAddress(probes []*kuadrantdnsv1alpha1.DNSHealthCheckProbe, gwa gatewayapiv1.GatewayAddress, gatewayName, listenerName string) *kuadrantdnsv1alpha1.DNSHealthCheckProbe { - for _, probe := range probes { - if dnsHealthCheckProbeName(gwa.Value, gatewayName, listenerName) == probe.Name { - return probe - } - } - return nil -} - -func dnsHealthCheckProbeName(address, gatewayName, listenerName string) string { - return fmt.Sprintf("%s-%s-%s", address, gatewayName, listenerName) -} - func (t *ClusterGatewayTarget) setWeight(defaultWeight int, customWeights []*v1alpha1.CustomWeight) error { weight := defaultWeight for k := range customWeights { @@ -200,11 +141,3 @@ func (t *ClusterGatewayTarget) setWeight(defaultWeight int, customWeights []*v1a t.Weight = &weight return nil } - -func ToBase36hash(s string) string { - hash := sha256.Sum224([]byte(s)) - // convert the hash to base36 (alphanumeric) to decrease collision probabilities - base36hash := strings.ToLower(base36.EncodeBytes(hash[:])) - // use 6 chars of the base36hash, should be enough to avoid collisions and keep the code short enough - return base36hash[:6] -}