@@ -28,6 +28,7 @@ import (
2828
2929 egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
3030 "github.com/envoyproxy/gateway/internal/gatewayapi"
31+ "github.com/envoyproxy/gateway/internal/gatewayapi/resource"
3132 "github.com/envoyproxy/gateway/internal/utils"
3233)
3334
@@ -592,7 +593,7 @@ func (r *gatewayAPIReconciler) validateEndpointSliceForReconcile(obj client.Obje
592593 nsName .Name = multiClusterSvcName
593594 }
594595
595- if r .isRouteReferencingBackend (& nsName ) {
596+ if r .hasRouteWithEndpointRouting (& nsName ) {
596597 return true
597598 }
598599
@@ -620,6 +621,142 @@ func (r *gatewayAPIReconciler) validateEndpointSliceForReconcile(obj client.Obje
620621 return false
621622}
622623
624+ // hasRouteWithEndpointRouting returns true if the backend(service and serviceImport) is referenced by any of the xRoutes
625+ // in the system and that route has a parent reference with EndpointRouting.
626+ func (r * gatewayAPIReconciler ) hasRouteWithEndpointRouting (nsName * types.NamespacedName ) bool {
627+ ctx := context .Background ()
628+ httpRouteList := & gwapiv1.HTTPRouteList {}
629+ if err := r .client .List (ctx , httpRouteList , & client.ListOptions {
630+ FieldSelector : fields .OneTermEqualSelector (backendHTTPRouteIndex , nsName .String ()),
631+ }); err != nil && ! kerrors .IsNotFound (err ) {
632+ r .log .Error (err , "failed to find associated HTTPRoutes" )
633+ return false
634+ }
635+ for _ , route := range httpRouteList .Items {
636+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
637+ return true
638+ }
639+ }
640+
641+ if r .grpcRouteCRDExists {
642+ grpcRouteList := & gwapiv1.GRPCRouteList {}
643+ if err := r .client .List (ctx , grpcRouteList , & client.ListOptions {
644+ FieldSelector : fields .OneTermEqualSelector (backendGRPCRouteIndex , nsName .String ()),
645+ }); err != nil && ! kerrors .IsNotFound (err ) {
646+ r .log .Error (err , "failed to find associated GRPCRoutes" )
647+ return false
648+ }
649+ for _ , route := range grpcRouteList .Items {
650+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
651+ return true
652+ }
653+ }
654+ }
655+
656+ if r .tlsRouteCRDExists {
657+ tlsRouteList := & gwapiv1a2.TLSRouteList {}
658+ if err := r .client .List (ctx , tlsRouteList , & client.ListOptions {
659+ FieldSelector : fields .OneTermEqualSelector (backendTLSRouteIndex , nsName .String ()),
660+ }); err != nil && ! kerrors .IsNotFound (err ) {
661+ r .log .Error (err , "failed to find associated TLSRoutes" )
662+ return false
663+ }
664+ for _ , route := range tlsRouteList .Items {
665+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
666+ return true
667+ }
668+ }
669+ }
670+
671+ if r .tcpRouteCRDExists {
672+ tcpRouteList := & gwapiv1a2.TCPRouteList {}
673+ if err := r .client .List (ctx , tcpRouteList , & client.ListOptions {
674+ FieldSelector : fields .OneTermEqualSelector (backendTCPRouteIndex , nsName .String ()),
675+ }); err != nil && ! kerrors .IsNotFound (err ) {
676+ r .log .Error (err , "failed to find associated TCPRoutes" )
677+ return false
678+ }
679+ for _ , route := range tcpRouteList .Items {
680+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
681+ return true
682+ }
683+ }
684+ }
685+
686+ if r .udpRouteCRDExists {
687+ udpRouteList := & gwapiv1a2.UDPRouteList {}
688+ if err := r .client .List (ctx , udpRouteList , & client.ListOptions {
689+ FieldSelector : fields .OneTermEqualSelector (backendUDPRouteIndex , nsName .String ()),
690+ }); err != nil && ! kerrors .IsNotFound (err ) {
691+ r .log .Error (err , "failed to find associated UDPRoutes" )
692+ return false
693+ }
694+ for _ , route := range udpRouteList .Items {
695+ if r .hasEndpointRouting (route .Namespace , route .Spec .CommonRouteSpec ) {
696+ return true
697+ }
698+ }
699+ }
700+
701+ return false
702+ }
703+
704+ // hasEndpointRouting checks that the associated egv1a1.EnvoyProxy has endpoint routing.
705+ func (r * gatewayAPIReconciler ) hasEndpointRouting (namespace string , spec gwapiv1.CommonRouteSpec ) bool {
706+ ctx := context .Background ()
707+ for _ , ref := range spec .ParentRefs {
708+ if ref .Kind != nil && * ref .Kind != resource .KindGateway {
709+ return false
710+ }
711+ if ref .Namespace != nil {
712+ namespace = string (* ref .Namespace )
713+ }
714+
715+ gw := gwapiv1.Gateway {
716+ ObjectMeta : metav1.ObjectMeta {
717+ Name : string (ref .Name ),
718+ Namespace : namespace ,
719+ },
720+ }
721+ err := r .client .Get (ctx , client .ObjectKeyFromObject (& gw ), & gw )
722+ if err != nil {
723+ r .log .Error (err , "unable to find associated gateway" )
724+ return false
725+ }
726+
727+ gwc := gwapiv1.GatewayClass {
728+ ObjectMeta : metav1.ObjectMeta {
729+ Name : string (gw .Spec .GatewayClassName ),
730+ },
731+ }
732+ err = r .client .Get (ctx , client .ObjectKeyFromObject (& gwc ), & gwc )
733+ if err != nil {
734+ r .log .Error (err , "unable to find associated gateway class" )
735+ return false
736+ }
737+
738+ var epNs string
739+ if gwc .Spec .ParametersRef .Namespace != nil {
740+ epNs = string (* gwc .Spec .ParametersRef .Namespace )
741+ }
742+ ep := egv1a1.EnvoyProxy {
743+ ObjectMeta : metav1.ObjectMeta {
744+ Name : gwc .Spec .ParametersRef .Name ,
745+ Namespace : epNs ,
746+ },
747+ }
748+ if err := r .client .Get (ctx , client .ObjectKeyFromObject (& ep ), & ep ); err != nil {
749+ r .log .Error (err , "unable to find associated EnvoyProxy" )
750+ return false
751+ }
752+ rt := ep .Spec .RoutingType
753+ if rt == nil || * rt == egv1a1 .EndpointRoutingType {
754+ return true
755+ }
756+ }
757+ return false
758+ }
759+
623760// validateObjectForReconcile tries finding the owning Gateway of the Deployment or DaemonSet
624761// if it exists, finds the Gateway's Service, and further updates the Gateway
625762// status Ready condition. No Deployments or DaemonSets are pushed for reconciliation.
0 commit comments