@@ -32,6 +32,7 @@ import (
3232 extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2"
3333 gatewayv1 "github.com/apoxy-dev/apoxy/api/gateway/v1"
3434 gatewayv1alpha2 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha2"
35+ vpcv1alpha1 "github.com/apoxy-dev/apoxy/api/vpc/v1alpha1"
3536)
3637
3738func Install (scheme * runtime.Scheme ) {
@@ -54,6 +55,11 @@ const (
5455 serviceTLSRouteIndex = "serviceTLSRouteIndex"
5556 gatewayInfraRefIndex = "gatewayInfraRefIndex"
5657 edgeFunctionLiveIndex = "edgeFunctionLiveIndex"
58+
59+ vpcServiceHTTPRouteIndex = "vpcServiceHTTPRouteIndex"
60+ vpcServiceTCPRouteIndex = "vpcServiceTCPRouteIndex"
61+ vpcServiceUDPRouteIndex = "vpcServiceUDPRouteIndex"
62+ vpcServiceTLSRouteIndex = "vpcServiceTLSRouteIndex"
5763)
5864
5965var (
@@ -173,6 +179,9 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, request reconcile.Req
173179 if err := r .reconcileBackends (clog .IntoContext (ctx , log ), res ); err != nil {
174180 log .Error (err , "Failed to reconcile BackendRefs for GatewayClass" , "name" , gwc .Name )
175181 }
182+ if err := r .reconcileVPCServices (clog .IntoContext (ctx , log ), res ); err != nil {
183+ log .Error (err , "Failed to reconcile VPCServices for GatewayClass" , "name" , gwc .Name )
184+ }
176185 if r .watchK8s {
177186 if err := r .reconcileServices (clog .IntoContext (ctx , log ), res ); err != nil {
178187 log .Error (err , "Failed to reconcile Services for GatewayClass" , "name" , gwc .Name )
@@ -616,6 +625,66 @@ func (r *GatewayReconciler) reconcileBackends(
616625 return nil
617626}
618627
628+ // reconcileVPCServices collects the VPCServices referenced by at least one
629+ // route into the translation snapshot. The translator only reads the spec
630+ // (hostname, networkRef, appProtocol) to mint the vpc-zone FQDN; membership
631+ // changes flow through the endpoint plane and do not pass through here.
632+ func (r * GatewayReconciler ) reconcileVPCServices (
633+ ctx context.Context ,
634+ res * gatewayapi.Resources ,
635+ ) error {
636+ log := clog .FromContext (ctx )
637+
638+ var vsl vpcv1alpha1.VPCServiceList
639+ if err := r .List (ctx , & vsl ); err != nil {
640+ return fmt .Errorf ("failed to list VPCServices: %w" , err )
641+ }
642+
643+ for _ , s := range vsl .Items {
644+ if ! s .DeletionTimestamp .IsZero () {
645+ log .Info ("VPCService is being deleted" , "name" , s .Name )
646+ continue
647+ }
648+
649+ var hasRouteRef bool
650+
651+ var hrsl gatewayv1.HTTPRouteList
652+ if err := r .List (ctx , & hrsl , client.MatchingFields {vpcServiceHTTPRouteIndex : string (s .Name )}); err != nil {
653+ return fmt .Errorf ("failed to list HTTPRoutes for VPCService %s: %w" , s .Name , err )
654+ }
655+ hasRouteRef = hasRouteRef || len (hrsl .Items ) > 0
656+
657+ var trsl gatewayv1alpha2.TCPRouteList
658+ if err := r .List (ctx , & trsl , client.MatchingFields {vpcServiceTCPRouteIndex : string (s .Name )}); err != nil {
659+ return fmt .Errorf ("failed to list TCPRoutes for VPCService %s: %w" , s .Name , err )
660+ }
661+ hasRouteRef = hasRouteRef || len (trsl .Items ) > 0
662+
663+ var ursl gatewayv1alpha2.UDPRouteList
664+ if err := r .List (ctx , & ursl , client.MatchingFields {vpcServiceUDPRouteIndex : string (s .Name )}); err != nil {
665+ return fmt .Errorf ("failed to list UDPRoutes for VPCService %s: %w" , s .Name , err )
666+ }
667+ hasRouteRef = hasRouteRef || len (ursl .Items ) > 0
668+
669+ var tlsrsl gatewayv1alpha2.TLSRouteList
670+ if err := r .List (ctx , & tlsrsl , client.MatchingFields {vpcServiceTLSRouteIndex : string (s .Name )}); err != nil {
671+ return fmt .Errorf ("failed to list TLSRoutes for VPCService %s: %w" , s .Name , err )
672+ }
673+ hasRouteRef = hasRouteRef || len (tlsrsl .Items ) > 0
674+
675+ if ! hasRouteRef {
676+ log .V (1 ).Info ("No matching Route objects found for VPCService" , "name" , s .Name )
677+ continue
678+ }
679+
680+ log .V (1 ).Info ("Reconciling VPCService" , "name" , s .Name )
681+
682+ res .VPCServices = append (res .VPCServices , & s )
683+ }
684+
685+ return nil
686+ }
687+
619688func (r * GatewayReconciler ) reconcileServices (
620689 ctx context.Context ,
621690 res * gatewayapi.Resources ,
@@ -845,6 +914,64 @@ func (r *GatewayReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manag
845914 return fmt .Errorf ("failed to setup field indexer: %w" , err )
846915 }
847916 }
917+ // Indexes each route type by the name of the referenced VPCService
918+ // object, mirroring the Backend indexes above.
919+ if err := mgr .GetFieldIndexer ().IndexField (ctx , & gatewayv1.HTTPRoute {}, vpcServiceHTTPRouteIndex , func (obj client.Object ) []string {
920+ route := obj .(* gatewayv1.HTTPRoute )
921+ var services []string
922+ for _ , rule := range route .Spec .Rules {
923+ for _ , backend := range rule .BackendRefs {
924+ if backend .Kind != nil && * backend .Kind == "VPCService" {
925+ services = append (services , string (backend .Name ))
926+ }
927+ }
928+ }
929+ return services
930+ }); err != nil {
931+ return fmt .Errorf ("failed to setup field indexer: %w" , err )
932+ }
933+ if err := mgr .GetFieldIndexer ().IndexField (ctx , & gatewayv1alpha2.TCPRoute {}, vpcServiceTCPRouteIndex , func (obj client.Object ) []string {
934+ route := obj .(* gatewayv1alpha2.TCPRoute )
935+ var services []string
936+ for _ , rule := range route .Spec .Rules {
937+ for _ , backend := range rule .BackendRefs {
938+ if backend .Kind != nil && * backend .Kind == "VPCService" {
939+ services = append (services , string (backend .Name ))
940+ }
941+ }
942+ }
943+ return services
944+ }); err != nil {
945+ return fmt .Errorf ("failed to setup field indexer: %w" , err )
946+ }
947+ if err := mgr .GetFieldIndexer ().IndexField (ctx , & gatewayv1alpha2.UDPRoute {}, vpcServiceUDPRouteIndex , func (obj client.Object ) []string {
948+ route := obj .(* gatewayv1alpha2.UDPRoute )
949+ var services []string
950+ for _ , rule := range route .Spec .Rules {
951+ for _ , backend := range rule .BackendRefs {
952+ if backend .Kind != nil && * backend .Kind == "VPCService" {
953+ services = append (services , string (backend .Name ))
954+ }
955+ }
956+ }
957+ return services
958+ }); err != nil {
959+ return fmt .Errorf ("failed to setup field indexer: %w" , err )
960+ }
961+ if err := mgr .GetFieldIndexer ().IndexField (ctx , & gatewayv1alpha2.TLSRoute {}, vpcServiceTLSRouteIndex , func (obj client.Object ) []string {
962+ route := obj .(* gatewayv1alpha2.TLSRoute )
963+ var services []string
964+ for _ , rule := range route .Spec .Rules {
965+ for _ , backend := range rule .BackendRefs {
966+ if backend .Kind != nil && * backend .Kind == "VPCService" {
967+ services = append (services , string (backend .Name ))
968+ }
969+ }
970+ }
971+ return services
972+ }); err != nil {
973+ return fmt .Errorf ("failed to setup field indexer: %w" , err )
974+ }
848975 // Index EdgeFunction objects that are ready.
849976 if err := mgr .GetFieldIndexer ().IndexField (ctx , & extensionsv1alpha2.EdgeFunction {}, edgeFunctionLiveIndex , func (obj client.Object ) []string {
850977 if obj .(* extensionsv1alpha2.EdgeFunction ).Status .LiveRevision != "" {
@@ -905,6 +1032,11 @@ func (r *GatewayReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manag
9051032 handler .EnqueueRequestsFromMapFunc (r .enqueueClass ),
9061033 builder .WithPredicates (generationOrDeletion ),
9071034 ).
1035+ Watches (
1036+ & vpcv1alpha1.VPCService {},
1037+ handler .EnqueueRequestsFromMapFunc (r .enqueueClass ),
1038+ builder .WithPredicates (generationOrDeletion ),
1039+ ).
9081040 Watches (
9091041 & extensionsv1alpha2.EdgeFunction {},
9101042 handler .EnqueueRequestsFromMapFunc (r .enqueueClass ),
0 commit comments