@@ -964,10 +964,11 @@ func ProcessGatewayProxy(r client.Client, log logr.Logger, tctx *provider.Transl
964
964
}
965
965
966
966
if cp .Service != nil {
967
- if err := addProviderEndpointsToTranslateContext ( tctx , r , k8stypes.NamespacedName {
967
+ serviceNN := k8stypes.NamespacedName {
968
968
Namespace : gatewayProxy .GetNamespace (),
969
969
Name : cp .Service .Name ,
970
- }); err != nil {
970
+ }
971
+ if err := addProviderEndpointsToTranslateContext (tctx , r , serviceNN ); err != nil {
971
972
return err
972
973
}
973
974
}
@@ -1377,10 +1378,11 @@ func ProcessIngressClassParameters(tctx *provider.TranslateContext, c client.Cli
1377
1378
1378
1379
// process control plane provider service
1379
1380
if cp .Service != nil {
1380
- if err := addProviderEndpointsToTranslateContext ( tctx , c , client. ObjectKey {
1381
+ serviceNN := k8stypes. NamespacedName {
1381
1382
Namespace : gatewayProxy .GetNamespace (),
1382
1383
Name : cp .Service .Name ,
1383
- }); err != nil {
1384
+ }
1385
+ if err := addProviderEndpointsToTranslateContext (tctx , c , serviceNN ); err != nil {
1384
1386
return err
1385
1387
}
1386
1388
}
@@ -1486,10 +1488,6 @@ func distinctRequests(requests []reconcile.Request) []reconcile.Request {
1486
1488
}
1487
1489
1488
1490
func addProviderEndpointsToTranslateContext (tctx * provider.TranslateContext , c client.Client , serviceNN k8stypes.NamespacedName ) error {
1489
- return addProviderEndpointsToTranslateContextWithEndpointSliceSupport (tctx , c , serviceNN , true )
1490
- }
1491
-
1492
- func addProviderEndpointsToTranslateContextWithEndpointSliceSupport (tctx * provider.TranslateContext , c client.Client , serviceNN k8stypes.NamespacedName , supportsEndpointSlice bool ) error {
1493
1491
log .Debugw ("to process provider endpoints by provider.service" , zap .Any ("service" , serviceNN ))
1494
1492
var (
1495
1493
service corev1.Service
@@ -1500,39 +1498,7 @@ func addProviderEndpointsToTranslateContextWithEndpointSliceSupport(tctx *provid
1500
1498
}
1501
1499
tctx .Services [serviceNN ] = & service
1502
1500
1503
- // Conditionally get EndpointSlice or Endpoints based on cluster API support
1504
- if supportsEndpointSlice {
1505
- // get es
1506
- var (
1507
- esList discoveryv1.EndpointSliceList
1508
- )
1509
- if err := c .List (tctx , & esList ,
1510
- client .InNamespace (serviceNN .Namespace ),
1511
- client.MatchingLabels {
1512
- discoveryv1 .LabelServiceName : serviceNN .Name ,
1513
- }); err != nil {
1514
- log .Errorw ("failed to get endpoints for GatewayProxy provider" , zap .Error (err ), zap .Any ("endpoints" , serviceNN ))
1515
- return err
1516
- }
1517
- tctx .EndpointSlices [serviceNN ] = esList .Items
1518
- } else {
1519
- // Fallback to Endpoints API for Kubernetes 1.18 compatibility
1520
- var endpoints corev1.Endpoints
1521
- if err := c .Get (tctx , serviceNN , & endpoints ); err != nil {
1522
- if client .IgnoreNotFound (err ) != nil {
1523
- log .Errorw ("failed to get endpoints for GatewayProxy provider" , zap .Error (err ), zap .Any ("endpoints" , serviceNN ))
1524
- return err
1525
- }
1526
- // If endpoints not found, create empty EndpointSlice list
1527
- tctx .EndpointSlices [serviceNN ] = []discoveryv1.EndpointSlice {}
1528
- } else {
1529
- // Convert Endpoints to EndpointSlice format for internal consistency
1530
- convertedEndpointSlices := pkgutils .ConvertEndpointsToEndpointSlice (& endpoints )
1531
- tctx .EndpointSlices [serviceNN ] = convertedEndpointSlices
1532
- }
1533
- }
1534
-
1535
- return nil
1501
+ return resolveServiceEndpoints (tctx , c , tctx , serviceNN , true , nil )
1536
1502
}
1537
1503
1538
1504
func TypePredicate [T client.Object ]() func (obj client.Object ) bool {
@@ -1585,3 +1551,94 @@ func watchEndpointSliceOrEndpoints(bdr *ctrl.Builder, supportsEndpointSlice bool
1585
1551
return bdr .Watches (& corev1.Endpoints {}, handler .EnqueueRequestsFromMapFunc (endpointsMapFunc ))
1586
1552
}
1587
1553
}
1554
+
1555
+ // resolveServiceEndpoints collects endpoints and adds them to the translate context
1556
+ // It handles both EndpointSlice (K8s 1.19+) and Endpoints (K8s 1.18) APIs with automatic fallback
1557
+ func resolveServiceEndpoints (
1558
+ ctx context.Context ,
1559
+ c client.Client ,
1560
+ tctx * provider.TranslateContext ,
1561
+ serviceNN k8stypes.NamespacedName ,
1562
+ supportsEndpointSlice bool ,
1563
+ subsetLabels map [string ]string ,
1564
+ ) error {
1565
+ if supportsEndpointSlice {
1566
+ var endpoints discoveryv1.EndpointSliceList
1567
+ if err := c .List (ctx , & endpoints ,
1568
+ client .InNamespace (serviceNN .Namespace ),
1569
+ client.MatchingLabels {
1570
+ discoveryv1 .LabelServiceName : serviceNN .Name ,
1571
+ },
1572
+ ); err != nil {
1573
+ return fmt .Errorf ("failed to list endpoint slices: %v" , err )
1574
+ }
1575
+
1576
+ if len (subsetLabels ) == 0 {
1577
+ tctx .EndpointSlices [serviceNN ] = endpoints .Items
1578
+ } else {
1579
+ // Apply subset filtering
1580
+ tctx .EndpointSlices [serviceNN ] = filterEndpointSlicesBySubsetLabels (ctx , c , endpoints .Items , subsetLabels )
1581
+ }
1582
+ } else {
1583
+ // Fallback to Endpoints API for Kubernetes 1.18 compatibility
1584
+ var ep corev1.Endpoints
1585
+ if err := c .Get (ctx , serviceNN , & ep ); err != nil {
1586
+ if client .IgnoreNotFound (err ) != nil {
1587
+ return fmt .Errorf ("failed to get endpoints: %v" , err )
1588
+ }
1589
+ // If endpoints not found, create empty EndpointSlice list
1590
+ tctx .EndpointSlices [serviceNN ] = []discoveryv1.EndpointSlice {}
1591
+ } else {
1592
+ // Convert Endpoints to EndpointSlice format for internal consistency
1593
+ convertedEndpointSlices := pkgutils .ConvertEndpointsToEndpointSlice (& ep )
1594
+
1595
+ if len (subsetLabels ) == 0 {
1596
+ tctx .EndpointSlices [serviceNN ] = convertedEndpointSlices
1597
+ } else {
1598
+ // Apply subset filtering to converted EndpointSlices
1599
+ tctx .EndpointSlices [serviceNN ] = filterEndpointSlicesBySubsetLabels (ctx , c , convertedEndpointSlices , subsetLabels )
1600
+ }
1601
+ }
1602
+ }
1603
+
1604
+ return nil
1605
+ }
1606
+
1607
+ // filterEndpointSlicesBySubsetLabels filters EndpointSlices by subset labels
1608
+ func filterEndpointSlicesBySubsetLabels (ctx context.Context , c client.Client , endpointSlices []discoveryv1.EndpointSlice , labels map [string ]string ) []discoveryv1.EndpointSlice {
1609
+ if len (labels ) == 0 {
1610
+ return endpointSlices
1611
+ }
1612
+
1613
+ for i := range endpointSlices {
1614
+ endpointSlices [i ] = filterEndpointSliceByTargetPod (ctx , c , endpointSlices [i ], labels )
1615
+ }
1616
+
1617
+ return utils .Filter (endpointSlices , func (v discoveryv1.EndpointSlice ) bool {
1618
+ return len (v .Endpoints ) > 0
1619
+ })
1620
+ }
1621
+
1622
+ // filterEndpointSliceByTargetPod filters item.Endpoints which is not a subset of labels
1623
+ func filterEndpointSliceByTargetPod (ctx context.Context , c client.Client , item discoveryv1.EndpointSlice , labels map [string ]string ) discoveryv1.EndpointSlice {
1624
+ item .Endpoints = utils .Filter (item .Endpoints , func (v discoveryv1.Endpoint ) bool {
1625
+ if v .TargetRef == nil || v .TargetRef .Kind != KindPod {
1626
+ return true
1627
+ }
1628
+
1629
+ var (
1630
+ pod corev1.Pod
1631
+ podNN = k8stypes.NamespacedName {
1632
+ Namespace : v .TargetRef .Namespace ,
1633
+ Name : v .TargetRef .Name ,
1634
+ }
1635
+ )
1636
+ if err := c .Get (ctx , podNN , & pod ); err != nil {
1637
+ return false
1638
+ }
1639
+
1640
+ return utils .IsSubsetOf (labels , pod .GetLabels ())
1641
+ })
1642
+
1643
+ return item
1644
+ }
0 commit comments