@@ -26,6 +26,7 @@ import (
2626
2727 egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
2828 "github.com/envoyproxy/gateway/internal/gatewayapi"
29+ "github.com/envoyproxy/gateway/internal/gatewayapi/resource"
2930 "github.com/envoyproxy/gateway/internal/utils"
3031)
3132
@@ -491,7 +492,7 @@ func (r *gatewayAPIReconciler) validateEndpointSliceForReconcile(obj client.Obje
491492 nsName .Name = multiClusterSvcName
492493 }
493494
494- if r .isRouteReferencingBackend (& nsName ) {
495+ if r .hasRouteWithEndpointRouting (& nsName ) {
495496 return true
496497 }
497498
@@ -516,6 +517,142 @@ func (r *gatewayAPIReconciler) validateEndpointSliceForReconcile(obj client.Obje
516517 return false
517518}
518519
520+ // hasRouteWithEndpointRouting returns true if the backend(service and serviceImport) is referenced by any of the xRoutes
521+ // in the system and that route has a parent reference with EndpointRouting.
522+ func (r * gatewayAPIReconciler ) hasRouteWithEndpointRouting (nsName * types.NamespacedName ) bool {
523+ ctx := context .Background ()
524+ httpRouteList := & gwapiv1.HTTPRouteList {}
525+ if err := r .client .List (ctx , httpRouteList , & client.ListOptions {
526+ FieldSelector : fields .OneTermEqualSelector (backendHTTPRouteIndex , nsName .String ()),
527+ }); err != nil && ! kerrors .IsNotFound (err ) {
528+ r .log .Error (err , "failed to find associated HTTPRoutes" )
529+ return false
530+ }
531+ for _ , route := range httpRouteList .Items {
532+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
533+ return true
534+ }
535+ }
536+
537+ if r .grpcRouteCRDExists {
538+ grpcRouteList := & gwapiv1.GRPCRouteList {}
539+ if err := r .client .List (ctx , grpcRouteList , & client.ListOptions {
540+ FieldSelector : fields .OneTermEqualSelector (backendGRPCRouteIndex , nsName .String ()),
541+ }); err != nil && ! kerrors .IsNotFound (err ) {
542+ r .log .Error (err , "failed to find associated GRPCRoutes" )
543+ return false
544+ }
545+ for _ , route := range grpcRouteList .Items {
546+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
547+ return true
548+ }
549+ }
550+ }
551+
552+ if r .tlsRouteCRDExists {
553+ tlsRouteList := & gwapiv1a2.TLSRouteList {}
554+ if err := r .client .List (ctx , tlsRouteList , & client.ListOptions {
555+ FieldSelector : fields .OneTermEqualSelector (backendTLSRouteIndex , nsName .String ()),
556+ }); err != nil && ! kerrors .IsNotFound (err ) {
557+ r .log .Error (err , "failed to find associated TLSRoutes" )
558+ return false
559+ }
560+ for _ , route := range tlsRouteList .Items {
561+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
562+ return true
563+ }
564+ }
565+ }
566+
567+ if r .tcpRouteCRDExists {
568+ tcpRouteList := & gwapiv1a2.TCPRouteList {}
569+ if err := r .client .List (ctx , tcpRouteList , & client.ListOptions {
570+ FieldSelector : fields .OneTermEqualSelector (backendTCPRouteIndex , nsName .String ()),
571+ }); err != nil && ! kerrors .IsNotFound (err ) {
572+ r .log .Error (err , "failed to find associated TCPRoutes" )
573+ return false
574+ }
575+ for _ , route := range tcpRouteList .Items {
576+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
577+ return true
578+ }
579+ }
580+ }
581+
582+ if r .udpRouteCRDExists {
583+ udpRouteList := & gwapiv1a2.UDPRouteList {}
584+ if err := r .client .List (ctx , udpRouteList , & client.ListOptions {
585+ FieldSelector : fields .OneTermEqualSelector (backendUDPRouteIndex , nsName .String ()),
586+ }); err != nil && ! kerrors .IsNotFound (err ) {
587+ r .log .Error (err , "failed to find associated UDPRoutes" )
588+ return false
589+ }
590+ for _ , route := range udpRouteList .Items {
591+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
592+ return true
593+ }
594+ }
595+ }
596+
597+ return false
598+ }
599+
600+ // hasEndpointRouting checks that the associated egv1a1.EnvoyProxy has endpoint routing.
601+ func (r * gatewayAPIReconciler ) hasEndpointRouting (namespace string , spec gwapiv1.CommonRouteSpec ) bool {
602+ ctx := context .Background ()
603+ for _ , ref := range spec .ParentRefs {
604+ if ref .Kind != nil && * ref .Kind != resource .KindGateway {
605+ return false
606+ }
607+ if ref .Namespace != nil {
608+ namespace = string (* ref .Namespace )
609+ }
610+
611+ gw := gwapiv1.Gateway {
612+ ObjectMeta : metav1.ObjectMeta {
613+ Name : string (ref .Name ),
614+ Namespace : namespace ,
615+ },
616+ }
617+ err := r .client .Get (ctx , client .ObjectKeyFromObject (& gw ), & gw )
618+ if err != nil {
619+ r .log .Error (err , "unable to find associated gateway" )
620+ return false
621+ }
622+
623+ gwc := gwapiv1.GatewayClass {
624+ ObjectMeta : metav1.ObjectMeta {
625+ Name : string (gw .Spec .GatewayClassName ),
626+ },
627+ }
628+ err = r .client .Get (ctx , client .ObjectKeyFromObject (& gwc ), & gwc )
629+ if err != nil {
630+ r .log .Error (err , "unable to find associated gateway class" )
631+ return false
632+ }
633+
634+ var epNs string
635+ if gwc .Spec .ParametersRef .Namespace != nil {
636+ epNs = string (* gwc .Spec .ParametersRef .Namespace )
637+ }
638+ ep := egv1a1.EnvoyProxy {
639+ ObjectMeta : metav1.ObjectMeta {
640+ Name : gwc .Spec .ParametersRef .Name ,
641+ Namespace : epNs ,
642+ },
643+ }
644+ if err := r .client .Get (ctx , client .ObjectKeyFromObject (& ep ), & ep ); err != nil {
645+ r .log .Error (err , "unable to find associated EnvoyProxy" )
646+ return false
647+ }
648+ rt := ep .Spec .RoutingType
649+ if rt == nil || * rt == egv1a1 .EndpointRoutingType {
650+ return true
651+ }
652+ }
653+ return false
654+ }
655+
519656// validateObjectForReconcile tries finding the owning Gateway of the Deployment or DaemonSet
520657// if it exists, finds the Gateway's Service, and further updates the Gateway
521658// status Ready condition. No Deployments or DaemonSets are pushed for reconciliation.
0 commit comments