From b877baca98bc9b28086bd80a8109aa25bca96247 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Mon, 28 Oct 2024 17:23:47 -0700 Subject: [PATCH] make watching alpha CRDs optional (#4519) * make watching alpha CRDs optional * The ownership of CRD installation is not tied to a single entity https://gateway-api.sigs.k8s.io/guides/crd-management/#who-should-manage-crds This results in multiple entities taking ownership of CRD installation * infra users * implementations * cloud providers This complicates things for implementations who may not know which version and release of CRDs are installed, so this PR makes watching alpha versioned CRDs optional * Even Envoy Gateway specific CRDs have been made optional to solve the use case where users want to only configure Gateway API resources * GRPCRoute is the only exception, which is v1, but has been made optional because it just graduated to v1 in v1.2 but a lot of cloud providers or service mesh implementations have not moved to v1.2 Fixes: https://github.com/envoyproxy/gateway/issues/3387 Signed-off-by: Arko Dasgupta --- internal/provider/kubernetes/controller.go | 623 ++++++++++-------- internal/provider/kubernetes/predicates.go | 244 ++++--- .../provider/kubernetes/predicates_test.go | 16 +- internal/provider/kubernetes/routes.go | 19 +- 4 files changed, 536 insertions(+), 366 deletions(-) diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 66b8b883c01..28a0eafaa77 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -65,6 +65,21 @@ type gatewayAPIReconciler struct { resources *message.ProviderResources extGVKs []schema.GroupVersionKind extServerPolicies []schema.GroupVersionKind + + backendCRDExists bool + bTLSPolicyCRDExists bool + btpCRDExists bool + ctpCRDExists bool + eepCRDExists bool + epCRDExists bool + eppCRDExists bool + hrfCRDExists bool + grpcRouteCRDExists bool + serviceImportCRDExists bool + spCRDExists bool + tcpRouteCRDExists bool + tlsRouteCRDExists bool + udpRouteCRDExists bool } // newGatewayAPIController @@ -197,42 +212,55 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques return reconcile.Result{}, err } - // Add all EnvoyPatchPolicies to the resourceTree - if err = r.processEnvoyPatchPolicies(ctx, gwcResource, resourceMappings); err != nil { - return reconcile.Result{}, err + if r.eppCRDExists { + // Add all EnvoyPatchPolicies to the resourceTree + if err = r.processEnvoyPatchPolicies(ctx, gwcResource, resourceMappings); err != nil { + return reconcile.Result{}, err + } } - - // Add all ClientTrafficPolicies and their referenced resources to the resourceTree - if err = r.processClientTrafficPolicies(ctx, gwcResource, resourceMappings); err != nil { - return reconcile.Result{}, err + if r.ctpCRDExists { + // Add all ClientTrafficPolicies and their referenced resources to the resourceTree + if err = r.processClientTrafficPolicies(ctx, gwcResource, resourceMappings); err != nil { + return reconcile.Result{}, err + } } - // Add all BackendTrafficPolicies to the resourceTree - if err = r.processBackendTrafficPolicies(ctx, gwcResource, resourceMappings); err != nil { - return reconcile.Result{}, err + if r.btpCRDExists { + // Add all BackendTrafficPolicies to the resourceTree + if err = r.processBackendTrafficPolicies(ctx, gwcResource, resourceMappings); err != nil { + return reconcile.Result{}, err + } } - // Add all SecurityPolicies and their referenced resources to the resourceTree - if err = r.processSecurityPolicies(ctx, gwcResource, resourceMappings); err != nil { - return reconcile.Result{}, err + if r.spCRDExists { + // Add all SecurityPolicies and their referenced resources to the resourceTree + if err = r.processSecurityPolicies(ctx, gwcResource, resourceMappings); err != nil { + return reconcile.Result{}, err + } } - // Add all BackendTLSPolies to the resourceTree - if err = r.processBackendTLSPolicies(ctx, gwcResource, resourceMappings); err != nil { - return reconcile.Result{}, err + if r.bTLSPolicyCRDExists { + // Add all BackendTLSPolies to the resourceTree + if err = r.processBackendTLSPolicies(ctx, gwcResource, resourceMappings); err != nil { + return reconcile.Result{}, err + } } - // Add all EnvoyExtensionPolicies and their referenced resources to the resourceTree - if err = r.processEnvoyExtensionPolicies(ctx, gwcResource, resourceMappings); err != nil { - return reconcile.Result{}, err + if r.eepCRDExists { + // Add all EnvoyExtensionPolicies and their referenced resources to the resourceTree + if err = r.processEnvoyExtensionPolicies(ctx, gwcResource, resourceMappings); err != nil { + return reconcile.Result{}, err + } } if err = r.processExtensionServerPolicies(ctx, gwcResource); err != nil { return reconcile.Result{}, err } - if err = r.processBackends(ctx, gwcResource); err != nil { - return reconcile.Result{}, err + if r.backendCRDExists { + if err = r.processBackends(ctx, gwcResource); err != nil { + return reconcile.Result{}, err + } } // Add the referenced services, ServiceImports, and EndpointSlices in @@ -905,9 +933,12 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g gtwNamespacedName := utils.NamespacedName(>w).String() // Route Processing - // Get TLSRoute objects and check if it exists. - if err := r.processTLSRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { - return err + + if r.tlsRouteCRDExists { + // Get TLSRoute objects and check if it exists. + if err := r.processTLSRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { + return err + } } // Get HTTPRoute objects and check if it exists. @@ -915,21 +946,26 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g return err } - // Get GRPCRoute objects and check if it exists. - if err := r.processGRPCRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { - return err + if r.grpcRouteCRDExists { + // Get GRPCRoute objects and check if it exists. + if err := r.processGRPCRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { + return err + } } - // Get TCPRoute objects and check if it exists. - if err := r.processTCPRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { - return err + if r.tcpRouteCRDExists { + // Get TCPRoute objects and check if it exists. + if err := r.processTCPRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { + return err + } } - // Get UDPRoute objects and check if it exists. - if err := r.processUDPRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { - return err + if r.udpRouteCRDExists { + // Get UDPRoute objects and check if it exists. + if err := r.processUDPRoutes(ctx, gtwNamespacedName, resourceMap, resourceTree); err != nil { + return err + } } - // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer gtw.Status = gwapiv1.GatewayStatus{} @@ -1122,24 +1158,30 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return fmt.Errorf("failed to watch GatewayClass: %w", err) } - epPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyProxy]{ - &predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyProxy]{}, - } - if r.namespaceLabel != nil { - epPredicates = append(epPredicates, predicate.NewTypedPredicateFuncs(func(ep *egv1a1.EnvoyProxy) bool { - return r.hasMatchingNamespaceLabels(ep) - })) - } - if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, t *egv1a1.EnvoyProxy) []reconcile.Request { - return r.enqueueClass(ctx, t) - }), - epPredicates...)); err != nil { - return err - } - if err := addEnvoyProxyIndexers(ctx, mgr); err != nil { - return err + r.epCRDExists = r.crdExists(mgr, resource.KindEnvoyProxy, egv1a1.GroupVersion.String()) + if !r.epCRDExists { + r.log.Info("EnvoyProxy CRD not found, skipping EnvoyProxy watch") + } else { + epPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyProxy]{ + &predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyProxy]{}, + } + if r.namespaceLabel != nil { + epPredicates = append(epPredicates, predicate.NewTypedPredicateFuncs(func(ep *egv1a1.EnvoyProxy) bool { + return r.hasMatchingNamespaceLabels(ep) + })) + } + + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, t *egv1a1.EnvoyProxy) []reconcile.Request { + return r.enqueueClass(ctx, t) + }), + epPredicates...)); err != nil { + return err + } + if err := addEnvoyProxyIndexers(ctx, mgr); err != nil { + return err + } } // Watch Gateway CRUDs and reconcile affected GatewayClass. @@ -1189,92 +1231,113 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } - // Watch GRPCRoute CRUDs and process affected Gateways. - grpcrPredicates := []predicate.TypedPredicate[*gwapiv1.GRPCRoute]{ - predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1.GRPCRoute]{}, - predicate.TypedLabelChangedPredicate[*gwapiv1.GRPCRoute]{}), - } - if r.namespaceLabel != nil { - grpcrPredicates = append(grpcrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1.GRPCRoute](func(grpc *gwapiv1.GRPCRoute) bool { - return r.hasMatchingNamespaceLabels(grpc) - })) - } - if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1.GRPCRoute{}, - handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1.GRPCRoute](func(ctx context.Context, route *gwapiv1.GRPCRoute) []reconcile.Request { - return r.enqueueClass(ctx, route) - }), - grpcrPredicates...)); err != nil { - return err - } - if err := addGRPCRouteIndexers(ctx, mgr); err != nil { - return err + // TODO: Remove this optional check once most cloud providers and service meshes support GRPCRoute v1 + r.grpcRouteCRDExists = r.crdExists(mgr, resource.KindGRPCRoute, gwapiv1.GroupVersion.String()) + if !r.grpcRouteCRDExists { + r.log.Info("GRPCRoute CRD not found, skipping GRPCRoute watch") + } else { + // Watch GRPCRoute CRUDs and process affected Gateways. + grpcrPredicates := []predicate.TypedPredicate[*gwapiv1.GRPCRoute]{ + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1.GRPCRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1.GRPCRoute]{}), + } + if r.namespaceLabel != nil { + grpcrPredicates = append(grpcrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1.GRPCRoute](func(grpc *gwapiv1.GRPCRoute) bool { + return r.hasMatchingNamespaceLabels(grpc) + })) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &gwapiv1.GRPCRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1.GRPCRoute](func(ctx context.Context, route *gwapiv1.GRPCRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + grpcrPredicates...)); err != nil { + return err + } + if err := addGRPCRouteIndexers(ctx, mgr); err != nil { + return err + } } - // Watch TLSRoute CRUDs and process affected Gateways. - tlsrPredicates := []predicate.TypedPredicate[*gwapiv1a2.TLSRoute]{ - predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TLSRoute]{}, - predicate.TypedLabelChangedPredicate[*gwapiv1a2.TLSRoute]{}), - } - if r.namespaceLabel != nil { - tlsrPredicates = append(tlsrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TLSRoute](func(route *gwapiv1a2.TLSRoute) bool { - return r.hasMatchingNamespaceLabels(route) - })) - } - if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.TLSRoute{}, - handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TLSRoute](func(ctx context.Context, route *gwapiv1a2.TLSRoute) []reconcile.Request { - return r.enqueueClass(ctx, route) - }), - tlsrPredicates...)); err != nil { - return err - } - if err := addTLSRouteIndexers(ctx, mgr); err != nil { - return err + r.tlsRouteCRDExists = r.crdExists(mgr, resource.KindTLSRoute, gwapiv1a2.GroupVersion.String()) + if !r.tlsRouteCRDExists { + r.log.Info("TLSRoute CRD not found, skipping TLSRoute watch") + } else { + // Watch TLSRoute CRUDs and process affected Gateways. + tlsrPredicates := []predicate.TypedPredicate[*gwapiv1a2.TLSRoute]{ + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TLSRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1a2.TLSRoute]{}), + } + if r.namespaceLabel != nil { + tlsrPredicates = append(tlsrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TLSRoute](func(route *gwapiv1a2.TLSRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &gwapiv1a2.TLSRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TLSRoute](func(ctx context.Context, route *gwapiv1a2.TLSRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + tlsrPredicates...)); err != nil { + return err + } + if err := addTLSRouteIndexers(ctx, mgr); err != nil { + return err + } } - // Watch UDPRoute CRUDs and process affected Gateways. - udprPredicates := []predicate.TypedPredicate[*gwapiv1a2.UDPRoute]{ - predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.UDPRoute]{}, - predicate.TypedLabelChangedPredicate[*gwapiv1a2.UDPRoute]{}), - } - if r.namespaceLabel != nil { - udprPredicates = append(udprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.UDPRoute](func(route *gwapiv1a2.UDPRoute) bool { - return r.hasMatchingNamespaceLabels(route) - })) - } - if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.UDPRoute{}, - handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.UDPRoute](func(ctx context.Context, route *gwapiv1a2.UDPRoute) []reconcile.Request { - return r.enqueueClass(ctx, route) - }), - udprPredicates...)); err != nil { - return err - } - if err := addUDPRouteIndexers(ctx, mgr); err != nil { - return err + r.udpRouteCRDExists = r.crdExists(mgr, resource.KindUDPRoute, gwapiv1a2.GroupVersion.String()) + if !r.udpRouteCRDExists { + r.log.Info("UDPRoute CRD not found, skipping UDPRoute watch") + } else { + // Watch UDPRoute CRUDs and process affected Gateways. + udprPredicates := []predicate.TypedPredicate[*gwapiv1a2.UDPRoute]{ + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.UDPRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1a2.UDPRoute]{}), + } + if r.namespaceLabel != nil { + udprPredicates = append(udprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.UDPRoute](func(route *gwapiv1a2.UDPRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &gwapiv1a2.UDPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.UDPRoute](func(ctx context.Context, route *gwapiv1a2.UDPRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + udprPredicates...)); err != nil { + return err + } + if err := addUDPRouteIndexers(ctx, mgr); err != nil { + return err + } } - // Watch TCPRoute CRUDs and process affected Gateways. - tcprPredicates := []predicate.TypedPredicate[*gwapiv1a2.TCPRoute]{ - predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TCPRoute]{}, - predicate.TypedLabelChangedPredicate[*gwapiv1a2.TCPRoute]{}), - } - if r.namespaceLabel != nil { - tcprPredicates = append(tcprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TCPRoute](func(route *gwapiv1a2.TCPRoute) bool { - return r.hasMatchingNamespaceLabels(route) - })) - } - if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.TCPRoute{}, - handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TCPRoute](func(ctx context.Context, route *gwapiv1a2.TCPRoute) []reconcile.Request { - return r.enqueueClass(ctx, route) - }), - tcprPredicates...)); err != nil { - return err - } - if err := addTCPRouteIndexers(ctx, mgr); err != nil { - return err + r.tcpRouteCRDExists = r.crdExists(mgr, resource.KindTCPRoute, gwapiv1a2.GroupVersion.String()) + if !r.tcpRouteCRDExists { + r.log.Info("TCPRoute CRD not found, skipping TCPRoute watch") + } else { + // Watch TCPRoute CRUDs and process affected Gateways. + tcprPredicates := []predicate.TypedPredicate[*gwapiv1a2.TCPRoute]{ + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TCPRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1a2.TCPRoute]{}), + } + if r.namespaceLabel != nil { + tcprPredicates = append(tcprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TCPRoute](func(route *gwapiv1a2.TCPRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &gwapiv1a2.TCPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TCPRoute](func(ctx context.Context, route *gwapiv1a2.TCPRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + tcprPredicates...)); err != nil { + return err + } + if err := addTCPRouteIndexers(ctx, mgr); err != nil { + return err + } } // Watch Service CRUDs and process affected *Route objects. @@ -1298,11 +1361,10 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch ServiceImport CRUDs and process affected *Route objects. - serviceImportCRDExists := r.serviceImportCRDExists(mgr) - if !serviceImportCRDExists { + r.serviceImportCRDExists = r.crdExists(mgr, resource.KindServiceImport, mcsapiv1a1.GroupVersion.String()) + if !r.serviceImportCRDExists { r.log.Info("ServiceImport CRD not found, skipping ServiceImport watch") - } - if serviceImportCRDExists { + } else { if err := c.Watch( source.Kind(mgr.GetCache(), &mcsapiv1a1.ServiceImport{}, handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *mcsapiv1a1.ServiceImport) []reconcile.Request { @@ -1338,8 +1400,11 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } - // Watch Backend CRUDs and process affected *Route objects. - if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableBackend { + r.backendCRDExists = r.crdExists(mgr, resource.KindBackend, egv1a1.GroupVersion.String()) + if !r.backendCRDExists { + r.log.Info("Backend CRD not found, skipping Backend watch") + } else if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableBackend { + // Watch Backend CRUDs and process affected *Route objects. backendPredicates := []predicate.TypedPredicate[*egv1a1.Backend]{ predicate.TypedGenerationChangedPredicate[*egv1a1.Backend]{}, predicate.NewTypedPredicateFuncs[*egv1a1.Backend](func(be *egv1a1.Backend) bool { @@ -1485,7 +1550,10 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } - if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { + r.eppCRDExists = r.crdExists(mgr, resource.KindEnvoyPatchPolicy, egv1a1.GroupVersion.String()) + if !r.eppCRDExists { + r.log.Info("EnvoyPatchPolicy CRD not found, skipping EnvoyPatchPolicy watch") + } else if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { // Watch EnvoyPatchPolicy if enabled in config eppPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyPatchPolicy]{ predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyPatchPolicy]{}, @@ -1506,118 +1574,143 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } } - // Watch ClientTrafficPolicy - ctpPredicates := []predicate.TypedPredicate[*egv1a1.ClientTrafficPolicy]{ - predicate.TypedGenerationChangedPredicate[*egv1a1.ClientTrafficPolicy]{}, - } - if r.namespaceLabel != nil { - ctpPredicates = append(ctpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.ClientTrafficPolicy](func(ctp *egv1a1.ClientTrafficPolicy) bool { - return r.hasMatchingNamespaceLabels(ctp) - })) - } + r.ctpCRDExists = r.crdExists(mgr, resource.KindClientTrafficPolicy, egv1a1.GroupVersion.String()) + if !r.ctpCRDExists { + r.log.Info("ClientTrafficPolicy CRD not found, skipping ClientTrafficPolicy watch") + } else { + // Watch ClientTrafficPolicy + ctpPredicates := []predicate.TypedPredicate[*egv1a1.ClientTrafficPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.ClientTrafficPolicy]{}, + } + if r.namespaceLabel != nil { + ctpPredicates = append(ctpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.ClientTrafficPolicy](func(ctp *egv1a1.ClientTrafficPolicy) bool { + return r.hasMatchingNamespaceLabels(ctp) + })) + } - if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, ctp *egv1a1.ClientTrafficPolicy) []reconcile.Request { - return r.enqueueClass(ctx, ctp) - }), - ctpPredicates...)); err != nil { - return err - } + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, ctp *egv1a1.ClientTrafficPolicy) []reconcile.Request { + return r.enqueueClass(ctx, ctp) + }), + ctpPredicates...)); err != nil { + return err + } - if err := addCtpIndexers(ctx, mgr); err != nil { - return err + if err := addCtpIndexers(ctx, mgr); err != nil { + return err + } } - // Watch BackendTrafficPolicy - btpPredicates := []predicate.TypedPredicate[*egv1a1.BackendTrafficPolicy]{ - predicate.TypedGenerationChangedPredicate[*egv1a1.BackendTrafficPolicy]{}, - } - if r.namespaceLabel != nil { - btpPredicates = append(btpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.BackendTrafficPolicy](func(btp *egv1a1.BackendTrafficPolicy) bool { - return r.hasMatchingNamespaceLabels(btp) - })) - } + r.btpCRDExists = r.crdExists(mgr, resource.KindBackendTrafficPolicy, egv1a1.GroupVersion.String()) + if !r.btpCRDExists { + r.log.Info("BackendTrafficPolicy CRD not found, skipping BackendTrafficPolicy watch") + } else { + // Watch BackendTrafficPolicy + btpPredicates := []predicate.TypedPredicate[*egv1a1.BackendTrafficPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.BackendTrafficPolicy]{}, + } + if r.namespaceLabel != nil { + btpPredicates = append(btpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.BackendTrafficPolicy](func(btp *egv1a1.BackendTrafficPolicy) bool { + return r.hasMatchingNamespaceLabels(btp) + })) + } - if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *egv1a1.BackendTrafficPolicy) []reconcile.Request { - return r.enqueueClass(ctx, btp) - }), - btpPredicates...)); err != nil { - return err - } + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *egv1a1.BackendTrafficPolicy) []reconcile.Request { + return r.enqueueClass(ctx, btp) + }), + btpPredicates...)); err != nil { + return err + } - if err := addBtpIndexers(ctx, mgr); err != nil { - return err + if err := addBtpIndexers(ctx, mgr); err != nil { + return err + } } - // Watch SecurityPolicy - spPredicates := []predicate.TypedPredicate[*egv1a1.SecurityPolicy]{ - predicate.TypedGenerationChangedPredicate[*egv1a1.SecurityPolicy]{}, - } - if r.namespaceLabel != nil { - spPredicates = append(spPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.SecurityPolicy](func(sp *egv1a1.SecurityPolicy) bool { - return r.hasMatchingNamespaceLabels(sp) - })) - } + r.spCRDExists = r.crdExists(mgr, resource.KindSecurityPolicy, egv1a1.GroupVersion.String()) + if !r.spCRDExists { + r.log.Info("SecurityPolicy CRD not found, skipping SecurityPolicy watch") + } else { + // Watch SecurityPolicy + spPredicates := []predicate.TypedPredicate[*egv1a1.SecurityPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.SecurityPolicy]{}, + } + if r.namespaceLabel != nil { + spPredicates = append(spPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.SecurityPolicy](func(sp *egv1a1.SecurityPolicy) bool { + return r.hasMatchingNamespaceLabels(sp) + })) + } - if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.SecurityPolicy{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, sp *egv1a1.SecurityPolicy) []reconcile.Request { - return r.enqueueClass(ctx, sp) - }), - spPredicates...)); err != nil { - return err - } - if err := addSecurityPolicyIndexers(ctx, mgr); err != nil { - return err + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.SecurityPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, sp *egv1a1.SecurityPolicy) []reconcile.Request { + return r.enqueueClass(ctx, sp) + }), + spPredicates...)); err != nil { + return err + } + if err := addSecurityPolicyIndexers(ctx, mgr); err != nil { + return err + } } - // Watch BackendTLSPolicy - btlsPredicates := []predicate.TypedPredicate[*gwapiv1a3.BackendTLSPolicy]{ - predicate.TypedGenerationChangedPredicate[*gwapiv1a3.BackendTLSPolicy]{}, - } - if r.namespaceLabel != nil { - btlsPredicates = append(btlsPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a3.BackendTLSPolicy](func(btp *gwapiv1a3.BackendTLSPolicy) bool { - return r.hasMatchingNamespaceLabels(btp) - })) - } + r.bTLSPolicyCRDExists = r.crdExists(mgr, resource.KindBackendTLSPolicy, gwapiv1a3.GroupVersion.String()) + if !r.bTLSPolicyCRDExists { + r.log.Info("BackendTLSPolicy CRD not found, skipping BackendTLSPolicy watch") + } else { + // Watch BackendTLSPolicy + btlsPredicates := []predicate.TypedPredicate[*gwapiv1a3.BackendTLSPolicy]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a3.BackendTLSPolicy]{}, + } + if r.namespaceLabel != nil { + btlsPredicates = append(btlsPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a3.BackendTLSPolicy](func(btp *gwapiv1a3.BackendTLSPolicy) bool { + return r.hasMatchingNamespaceLabels(btp) + })) + } - if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a3.BackendTLSPolicy{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *gwapiv1a3.BackendTLSPolicy) []reconcile.Request { - return r.enqueueClass(ctx, btp) - }), - btlsPredicates...)); err != nil { - return err - } + if err := c.Watch( + source.Kind(mgr.GetCache(), &gwapiv1a3.BackendTLSPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *gwapiv1a3.BackendTLSPolicy) []reconcile.Request { + return r.enqueueClass(ctx, btp) + }), + btlsPredicates...)); err != nil { + return err + } - if err := addBtlsIndexers(ctx, mgr); err != nil { - return err + if err := addBtlsIndexers(ctx, mgr); err != nil { + return err + } } - // Watch EnvoyExtensionPolicy - eepPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyExtensionPolicy]{ - predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyExtensionPolicy]{}, - } - if r.namespaceLabel != nil { - eepPredicates = append(eepPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyExtensionPolicy](func(eep *egv1a1.EnvoyExtensionPolicy) bool { - return r.hasMatchingNamespaceLabels(eep) - })) - } + r.eepCRDExists = r.crdExists(mgr, resource.KindEnvoyExtensionPolicy, egv1a1.GroupVersion.String()) + if !r.eepCRDExists { + r.log.Info("EnvoyExtensionPolicy CRD not found, skipping EnvoyExtensionPolicy watch") + } else { + // Watch EnvoyExtensionPolicy + eepPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyExtensionPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyExtensionPolicy]{}, + } + if r.namespaceLabel != nil { + eepPredicates = append(eepPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyExtensionPolicy](func(eep *egv1a1.EnvoyExtensionPolicy) bool { + return r.hasMatchingNamespaceLabels(eep) + })) + } - // Watch EnvoyExtensionPolicy CRUDs - if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyExtensionPolicy{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, eep *egv1a1.EnvoyExtensionPolicy) []reconcile.Request { - return r.enqueueClass(ctx, eep) - }), - eepPredicates...)); err != nil { - return err - } - if err := addEnvoyExtensionPolicyIndexers(ctx, mgr); err != nil { - return err + // Watch EnvoyExtensionPolicy CRUDs + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.EnvoyExtensionPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, eep *egv1a1.EnvoyExtensionPolicy) []reconcile.Request { + return r.enqueueClass(ctx, eep) + }), + eepPredicates...)); err != nil { + return err + } + if err := addEnvoyExtensionPolicyIndexers(ctx, mgr); err != nil { + return err + } } r.log.Info("Watching gatewayAPI related objects") @@ -1656,31 +1749,35 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M r.log.Info("Watching additional policy resource", "resource", gvk.String()) } - // Watch HTTPRouteFilter CRUDs and process affected HTTPRoute objects. - httpRouteFilter := []predicate.TypedPredicate[*egv1a1.HTTPRouteFilter]{ - predicate.TypedGenerationChangedPredicate[*egv1a1.HTTPRouteFilter]{}, - predicate.NewTypedPredicateFuncs[*egv1a1.HTTPRouteFilter](func(be *egv1a1.HTTPRouteFilter) bool { - return r.validateHTTPRouteFilterForReconcile(be) - }), - } - if r.namespaceLabel != nil { - httpRouteFilter = append(httpRouteFilter, predicate.NewTypedPredicateFuncs[*egv1a1.HTTPRouteFilter](func(be *egv1a1.HTTPRouteFilter) bool { - return r.hasMatchingNamespaceLabels(be) - })) - } - if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.HTTPRouteFilter{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, be *egv1a1.HTTPRouteFilter) []reconcile.Request { - return r.enqueueClass(ctx, be) + r.hrfCRDExists = r.crdExists(mgr, resource.KindHTTPRouteFilter, egv1a1.GroupVersion.String()) + if !r.hrfCRDExists { + r.log.Info("HTTPRouteFilter CRD not found, skipping HTTPRouteFilter watch") + } else { + // Watch HTTPRouteFilter CRUDs and process affected HTTPRoute objects. + httpRouteFilter := []predicate.TypedPredicate[*egv1a1.HTTPRouteFilter]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.HTTPRouteFilter]{}, + predicate.NewTypedPredicateFuncs[*egv1a1.HTTPRouteFilter](func(be *egv1a1.HTTPRouteFilter) bool { + return r.validateHTTPRouteFilterForReconcile(be) }), - httpRouteFilter...)); err != nil { - return err - } + } + if r.namespaceLabel != nil { + httpRouteFilter = append(httpRouteFilter, predicate.NewTypedPredicateFuncs[*egv1a1.HTTPRouteFilter](func(be *egv1a1.HTTPRouteFilter) bool { + return r.hasMatchingNamespaceLabels(be) + })) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.HTTPRouteFilter{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, be *egv1a1.HTTPRouteFilter) []reconcile.Request { + return r.enqueueClass(ctx, be) + }), + httpRouteFilter...)); err != nil { + return err + } - if err := addRouteFilterIndexers(ctx, mgr); err != nil { - return err + if err := addRouteFilterIndexers(ctx, mgr); err != nil { + return err + } } - return nil } @@ -1820,8 +1917,8 @@ func (r *gatewayAPIReconciler) processEnvoyProxy(ep *egv1a1.EnvoyProxy, resource return nil } -// serviceImportCRDExists checks for the existence of the ServiceImport CRD in k8s APIServer before watching it -func (r *gatewayAPIReconciler) serviceImportCRDExists(mgr manager.Manager) bool { +// crdExists checks for the existence of the CRD in k8s APIServer before watching it +func (r *gatewayAPIReconciler) crdExists(mgr manager.Manager, kind string, groupVersion string) bool { discoveryClient, err := discovery.NewDiscoveryClientForConfig(mgr.GetConfig()) if err != nil { r.log.Error(err, "failed to create discovery client") @@ -1830,17 +1927,17 @@ func (r *gatewayAPIReconciler) serviceImportCRDExists(mgr manager.Manager) bool if err != nil { r.log.Error(err, "failed to get API resource list") } - serviceImportFound := false + found := false for _, list := range apiResourceList { for _, res := range list.APIResources { - if list.GroupVersion == mcsapiv1a1.GroupVersion.String() && res.Kind == resource.KindServiceImport { - serviceImportFound = true + if list.GroupVersion == groupVersion && res.Kind == kind { + found = true break } } } - return serviceImportFound + return found } func (r *gatewayAPIReconciler) processBackendTLSPolicyRefs( diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index ae4f63ef3e9..916a58b2f77 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -144,24 +144,32 @@ func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) boo return true } - if r.isSecurityPolicyReferencingSecret(&nsName) { - return true + if r.spCRDExists { + if r.isSecurityPolicyReferencingSecret(&nsName) { + return true + } } - if r.isCtpReferencingSecret(&nsName) { - return true + if r.ctpCRDExists { + if r.isCtpReferencingSecret(&nsName) { + return true + } } if r.isOIDCHMACSecret(&nsName) { return true } - if r.isEnvoyProxyReferencingSecret(&nsName) { - return true + if r.epCRDExists { + if r.isEnvoyProxyReferencingSecret(&nsName) { + return true + } } - if r.isExtensionPolicyReferencingSecret(&nsName) { - return true + if r.eepCRDExists { + if r.isExtensionPolicyReferencingSecret(&nsName) { + return true + } } return false @@ -283,15 +291,25 @@ func (r *gatewayAPIReconciler) validateServiceForReconcile(obj client.Object) bo return true } - if r.isSecurityPolicyReferencingBackend(&nsName) { - return true + if r.spCRDExists { + if r.isSecurityPolicyReferencingBackend(&nsName) { + return true + } } - if r.isEnvoyProxyReferencingBackend(&nsName) { - return true + if r.epCRDExists { + if r.isEnvoyProxyReferencingBackend(&nsName) { + return true + } + } + + if r.eepCRDExists { + if r.isEnvoyExtensionPolicyReferencingBackend(&nsName) { + return true + } } - return r.isEnvoyExtensionPolicyReferencingBackend(&nsName) + return false } // validateBackendForReconcile tries finding the owning Gateway of the Backend @@ -309,15 +327,25 @@ func (r *gatewayAPIReconciler) validateBackendForReconcile(obj client.Object) bo return true } - if r.isSecurityPolicyReferencingBackend(&nsName) { - return true + if r.spCRDExists { + if r.isSecurityPolicyReferencingBackend(&nsName) { + return true + } } - if r.isEnvoyProxyReferencingBackend(&nsName) { - return true + if r.epCRDExists { + if r.isEnvoyProxyReferencingBackend(&nsName) { + return true + } } - return r.isEnvoyExtensionPolicyReferencingBackend(&nsName) + if r.eepCRDExists { + if r.isEnvoyExtensionPolicyReferencingBackend(&nsName) { + return true + } + } + + return false } func (r *gatewayAPIReconciler) isSecurityPolicyReferencingBackend(nsName *types.NamespacedName) bool { @@ -357,47 +385,63 @@ func (r *gatewayAPIReconciler) isRouteReferencingBackend(nsName *types.Namespace r.log.Error(err, "failed to find associated HTTPRoutes") return false } - - grpcRouteList := &gwapiv1.GRPCRouteList{} - if err := r.client.List(ctx, grpcRouteList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(backendGRPCRouteIndex, nsName.String()), - }); err != nil && !kerrors.IsNotFound(err) { - r.log.Error(err, "failed to find associated GRPCRoutes") - return false + if len(httpRouteList.Items) > 0 { + return true } - tlsRouteList := &gwapiv1a2.TLSRouteList{} - if err := r.client.List(ctx, tlsRouteList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(backendTLSRouteIndex, nsName.String()), - }); err != nil && !kerrors.IsNotFound(err) { - r.log.Error(err, "failed to find associated TLSRoutes") - return false + if r.grpcRouteCRDExists { + grpcRouteList := &gwapiv1.GRPCRouteList{} + if err := r.client.List(ctx, grpcRouteList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(backendGRPCRouteIndex, nsName.String()), + }); err != nil && !kerrors.IsNotFound(err) { + r.log.Error(err, "failed to find associated GRPCRoutes") + return false + } + if len(grpcRouteList.Items) > 0 { + return true + } } - tcpRouteList := &gwapiv1a2.TCPRouteList{} - if err := r.client.List(ctx, tcpRouteList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(backendTCPRouteIndex, nsName.String()), - }); err != nil && !kerrors.IsNotFound(err) { - r.log.Error(err, "failed to find associated TCPRoutes") - return false + if r.tlsRouteCRDExists { + tlsRouteList := &gwapiv1a2.TLSRouteList{} + if err := r.client.List(ctx, tlsRouteList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(backendTLSRouteIndex, nsName.String()), + }); err != nil && !kerrors.IsNotFound(err) { + r.log.Error(err, "failed to find associated TLSRoutes") + return false + } + if len(tlsRouteList.Items) > 0 { + return true + } } - udpRouteList := &gwapiv1a2.UDPRouteList{} - if err := r.client.List(ctx, udpRouteList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(backendUDPRouteIndex, nsName.String()), - }); err != nil && !kerrors.IsNotFound(err) { - r.log.Error(err, "failed to find associated UDPRoutes") - return false + if r.tcpRouteCRDExists { + tcpRouteList := &gwapiv1a2.TCPRouteList{} + if err := r.client.List(ctx, tcpRouteList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(backendTCPRouteIndex, nsName.String()), + }); err != nil && !kerrors.IsNotFound(err) { + r.log.Error(err, "failed to find associated TCPRoutes") + return false + } + if len(tcpRouteList.Items) > 0 { + return true + } } - // Check how many Route objects refer this Backend - allAssociatedRoutes := len(httpRouteList.Items) + - len(grpcRouteList.Items) + - len(tlsRouteList.Items) + - len(tcpRouteList.Items) + - len(udpRouteList.Items) + if r.udpRouteCRDExists { + udpRouteList := &gwapiv1a2.UDPRouteList{} + if err := r.client.List(ctx, udpRouteList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(backendUDPRouteIndex, nsName.String()), + }); err != nil && !kerrors.IsNotFound(err) { + r.log.Error(err, "failed to find associated UDPRoutes") + return false + } + if len(udpRouteList.Items) > 0 { + return true + } + } - return allAssociatedRoutes != 0 + return false } // validateEndpointSliceForReconcile returns true if the endpointSlice references @@ -429,15 +473,25 @@ func (r *gatewayAPIReconciler) validateEndpointSliceForReconcile(obj client.Obje return true } - if r.isSecurityPolicyReferencingBackend(&nsName) { - return true + if r.spCRDExists { + if r.isSecurityPolicyReferencingBackend(&nsName) { + return true + } } - if r.isEnvoyProxyReferencingBackend(&nsName) { - return true + if r.epCRDExists { + if r.isEnvoyProxyReferencingBackend(&nsName) { + return true + } + } + + if r.eepCRDExists { + if r.isEnvoyExtensionPolicyReferencingBackend(&nsName) { + return true + } } - return r.isEnvoyExtensionPolicyReferencingBackend(&nsName) + return false } // validateObjectForReconcile tries finding the owning Gateway of the Deployment or DaemonSet @@ -596,52 +650,60 @@ func (r *gatewayAPIReconciler) validateConfigMapForReconcile(obj client.Object) return false } - ctpList := &egv1a1.ClientTrafficPolicyList{} - if err := r.client.List(context.Background(), ctpList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(configMapCtpIndex, utils.NamespacedName(configMap).String()), - }); err != nil { - r.log.Error(err, "unable to find associated ClientTrafficPolicy") - return false - } + if r.ctpCRDExists { + ctpList := &egv1a1.ClientTrafficPolicyList{} + if err := r.client.List(context.Background(), ctpList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(configMapCtpIndex, utils.NamespacedName(configMap).String()), + }); err != nil { + r.log.Error(err, "unable to find associated ClientTrafficPolicy") + return false + } - if len(ctpList.Items) > 0 { - return true + if len(ctpList.Items) > 0 { + return true + } } - btlsList := &gwapiv1a3.BackendTLSPolicyList{} - if err := r.client.List(context.Background(), btlsList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(configMapBtlsIndex, utils.NamespacedName(configMap).String()), - }); err != nil { - r.log.Error(err, "unable to find associated BackendTLSPolicy") - return false - } + if r.bTLSPolicyCRDExists { + btlsList := &gwapiv1a3.BackendTLSPolicyList{} + if err := r.client.List(context.Background(), btlsList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(configMapBtlsIndex, utils.NamespacedName(configMap).String()), + }); err != nil { + r.log.Error(err, "unable to find associated BackendTLSPolicy") + return false + } - if len(btlsList.Items) > 0 { - return true + if len(btlsList.Items) > 0 { + return true + } } - btpList := &egv1a1.BackendTrafficPolicyList{} - if err := r.client.List(context.Background(), btpList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(configMapBtpIndex, utils.NamespacedName(configMap).String()), - }); err != nil { - r.log.Error(err, "unable to find associated BackendTrafficPolicy") - return false - } + if r.btpCRDExists { + btpList := &egv1a1.BackendTrafficPolicyList{} + if err := r.client.List(context.Background(), btpList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(configMapBtpIndex, utils.NamespacedName(configMap).String()), + }); err != nil { + r.log.Error(err, "unable to find associated BackendTrafficPolicy") + return false + } - if len(btpList.Items) > 0 { - return true + if len(btpList.Items) > 0 { + return true + } } - routeFilterList := &egv1a1.HTTPRouteFilterList{} - if err := r.client.List(context.Background(), routeFilterList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(configMapHTTPRouteFilterIndex, utils.NamespacedName(configMap).String()), - }); err != nil { - r.log.Error(err, "unable to find associated HTTPRouteFilter") - return false - } + if r.hrfCRDExists { + routeFilterList := &egv1a1.HTTPRouteFilterList{} + if err := r.client.List(context.Background(), routeFilterList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(configMapHTTPRouteFilterIndex, utils.NamespacedName(configMap).String()), + }); err != nil { + r.log.Error(err, "unable to find associated HTTPRouteFilter") + return false + } - if len(routeFilterList.Items) > 0 { - return true + if len(routeFilterList.Items) > 0 { + return true + } } return false diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index 5954e94675e..d8abf845f4d 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -356,6 +356,9 @@ func TestValidateSecretForReconcile(t *testing.T) { r := gatewayAPIReconciler{ classController: egv1a1.GatewayControllerName, log: logger, + spCRDExists: true, + epCRDExists: true, + eepCRDExists: true, } for _, tc := range testCases { @@ -848,9 +851,16 @@ func TestValidateServiceForReconcile(t *testing.T) { logger := logging.DefaultLogger(egv1a1.LogLevelInfo) r := gatewayAPIReconciler{ - classController: egv1a1.GatewayControllerName, - log: logger, - mergeGateways: sets.New[string]("test-mg"), + classController: egv1a1.GatewayControllerName, + log: logger, + mergeGateways: sets.New[string]("test-mg"), + grpcRouteCRDExists: true, + tcpRouteCRDExists: true, + udpRouteCRDExists: true, + tlsRouteCRDExists: true, + spCRDExists: true, + eepCRDExists: true, + epCRDExists: true, } for _, tc := range testCases { diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index dcc01631f3b..fa148ffd441 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -238,16 +238,17 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam resourceMap *resourceMappings, resourceTree *resource.Resources, ) error { httpRouteList := &gwapiv1.HTTPRouteList{} + if r.hrfCRDExists { + httpFilters, err := r.getHTTPRouteFilters(ctx) + if err != nil { + return err + } - httpFilters, err := r.getHTTPRouteFilters(ctx) - if err != nil { - return err - } - - for i := range httpFilters { - filter := httpFilters[i] - resourceMap.httpRouteFilters[utils.GetNamespacedNameWithGroupKind(&filter)] = &filter - r.processRouteFilterConfigMapRef(ctx, &filter, resourceMap, resourceTree) + for i := range httpFilters { + filter := httpFilters[i] + resourceMap.httpRouteFilters[utils.GetNamespacedNameWithGroupKind(&filter)] = &filter + r.processRouteFilterConfigMapRef(ctx, &filter, resourceMap, resourceTree) + } } extensionRefFilters, err := r.getExtensionRefFilters(ctx)