@@ -37,7 +37,7 @@ index 74166b5d9..4e744f8de 100644
3737 klog.Infof("Initializing kubevirtEPSController")
3838
3939diff --git a/pkg/controller/kubevirteps/kubevirteps_controller.go b/pkg/controller/kubevirteps/kubevirteps_controller.go
40- index 6f6e3d322 ..b56882c12 100644
40+ index 53388eb8e ..b56882c12 100644
4141--- a/pkg/controller/kubevirteps/kubevirteps_controller.go
4242+++ b/pkg/controller/kubevirteps/kubevirteps_controller.go
4343@@ -54,10 +54,10 @@ type Controller struct {
@@ -286,22 +286,6 @@ index 6f6e3d322..b56882c12 100644
286286 for _, eps := range slicesToDelete {
287287 err := c.infraClient.DiscoveryV1().EndpointSlices(eps.Namespace).Delete(context.TODO(), eps.Name, metav1.DeleteOptions{})
288288 if err != nil {
289- @@ -474,11 +538,11 @@ func (c *Controller) reconcileByAddressType(service *v1.Service, tenantSlices []
290- // Create the desired port configuration
291- var desiredPorts []discovery.EndpointPort
292-
293- - for _, port := range service.Spec.Ports {
294- + for i := range service.Spec.Ports {
295- desiredPorts = append(desiredPorts, discovery.EndpointPort{
296- - Port: &port.TargetPort.IntVal,
297- - Protocol: &port.Protocol,
298- - Name: &port.Name,
299- + Port: &service.Spec.Ports[i].TargetPort.IntVal,
300- + Protocol: &service.Spec.Ports[i].Protocol,
301- + Name: &service.Spec.Ports[i].Name,
302- })
303- }
304-
305289@@ -588,55 +652,114 @@ func ownedBy(endpointSlice *discovery.EndpointSlice, svc *v1.Service) bool {
306290 return false
307291 }
@@ -437,18 +421,10 @@ index 6f6e3d322..b56882c12 100644
437421
438422 return nil
439423diff --git a/pkg/controller/kubevirteps/kubevirteps_controller_test.go b/pkg/controller/kubevirteps/kubevirteps_controller_test.go
440- index 1fb86e25f ..14d92d340 100644
424+ index 1c97035b4 ..14d92d340 100644
441425--- a/pkg/controller/kubevirteps/kubevirteps_controller_test.go
442426+++ b/pkg/controller/kubevirteps/kubevirteps_controller_test.go
443- @@ -13,6 +13,7 @@ import (
444- "k8s.io/apimachinery/pkg/runtime"
445- "k8s.io/apimachinery/pkg/runtime/schema"
446- "k8s.io/apimachinery/pkg/util/intstr"
447- + "k8s.io/apimachinery/pkg/util/sets"
448- dfake "k8s.io/client-go/dynamic/fake"
449- "k8s.io/client-go/kubernetes/fake"
450- "k8s.io/client-go/testing"
451- @@ -189,7 +190,7 @@ func setupTestKubevirtEPSController() *testKubevirtEPSController {
427+ @@ -190,7 +190,7 @@ func setupTestKubevirtEPSController() *testKubevirtEPSController {
452428 }: "VirtualMachineInstanceList",
453429 })
454430
@@ -457,83 +433,87 @@ index 1fb86e25f..14d92d340 100644
457433
458434 err := controller.Init()
459435 if err != nil {
460- @@ -686,5 +687,229 @@ var _ = g.Describe("KubevirtEPSController", g.Ordered, func() {
461- return false, err
462- }).Should(BeTrue(), "EndpointSlice in infra cluster should be recreated by the controller after deletion")
463- })
464- +
465- + g.It("Should correctly handle multiple unique ports in EndpointSlice", func() {
466- + // Create a VMI in the infra cluster
467- + createAndAssertVMI("worker-0-test", "ip-10-32-5-13", "123.45.67.89")
468- +
469- + // Create an EndpointSlice in the tenant cluster
470- + createAndAssertTenantSlice("test-epslice", "tenant-service-name", discoveryv1.AddressTypeIPv4,
471- + *createPort("http", 80, v1.ProtocolTCP),
472- + []discoveryv1.Endpoint{*createEndpoint("123.45.67.89", "worker-0-test", true, true, false)})
473- +
436+ @@ -697,51 +697,43 @@ var _ = g.Describe("KubevirtEPSController", g.Ordered, func() {
437+ *createPort("http", 80, v1.ProtocolTCP),
438+ []discoveryv1.Endpoint{*createEndpoint("123.45.67.89", "worker-0-test", true, true, false)})
439+
440+ - // Define several unique ports for the Service
474441+ // Define multiple ports for the Service
475- + servicePorts := []v1.ServicePort{
476- + {
442+ servicePorts := []v1.ServicePort{
443+ {
444+ - Name: "client",
445+ - Protocol: v1.ProtocolTCP,
446+ - Port: 10001,
447+ - TargetPort: intstr.FromInt(30396),
448+ - NodePort: 30396,
449+ - AppProtocol: nil,
477450+ Name: "client",
478451+ Protocol: v1.ProtocolTCP,
479452+ Port: 10001,
480453+ TargetPort: intstr.FromInt(30396),
481454+ NodePort: 30396,
482- + },
483- + {
455+ },
456+ {
457+ - Name: "dashboard",
458+ - Protocol: v1.ProtocolTCP,
459+ - Port: 8265,
460+ - TargetPort: intstr.FromInt(31003),
461+ - NodePort: 31003,
462+ - AppProtocol: nil,
484463+ Name: "dashboard",
485464+ Protocol: v1.ProtocolTCP,
486465+ Port: 8265,
487466+ TargetPort: intstr.FromInt(31003),
488467+ NodePort: 31003,
489- + },
490- + {
468+ },
469+ {
470+ - Name: "metrics",
471+ - Protocol: v1.ProtocolTCP,
472+ - Port: 8080,
473+ - TargetPort: intstr.FromInt(30452),
474+ - NodePort: 30452,
475+ - AppProtocol: nil,
491476+ Name: "metrics",
492477+ Protocol: v1.ProtocolTCP,
493478+ Port: 8080,
494479+ TargetPort: intstr.FromInt(30452),
495480+ NodePort: 30452,
496- + },
497- + }
498- +
499- + createAndAssertInfraServiceLB("infra-multiport-service", "tenant-service-name", "test-cluster",
481+ },
482+ }
483+
484+ - // Create a Service with the first port
485+ createAndAssertInfraServiceLB("infra-multiport-service", "tenant-service-name", "test-cluster",
486+ - servicePorts[0],
487+ - v1.ServiceExternalTrafficPolicyLocal)
500488+ servicePorts[0], v1.ServiceExternalTrafficPolicyLocal)
501- +
502- + svc, err := testVals.infraClient.CoreV1().Services(infraNamespace).Get(context.TODO(), "infra-multiport-service", metav1.GetOptions{})
503- + Expect(err).To(BeNil())
504- +
505- + svc.Spec.Ports = servicePorts
506- + _, err = testVals.infraClient.CoreV1().Services(infraNamespace).Update(context.TODO(), svc, metav1.UpdateOptions{})
507- + Expect(err).To(BeNil())
508- +
509- + var epsListMultiPort *discoveryv1.EndpointSliceList
510- +
511- + Eventually(func() (bool, error) {
512- + epsListMultiPort, err = testVals.infraClient.DiscoveryV1().EndpointSlices(infraNamespace).List(context.TODO(), metav1.ListOptions{})
513- + if len(epsListMultiPort.Items) != 1 {
514- + return false, err
515- + }
516- +
517- + createdSlice := epsListMultiPort.Items[0]
518- + expectedPortNames := []string{"client", "dashboard", "metrics"}
519- + foundPortNames := []string{}
520- +
521- + for _, port := range createdSlice.Ports {
522- + if port.Name != nil {
523- + foundPortNames = append(foundPortNames, *port.Name)
524- + }
525- + }
526- +
527- + if len(foundPortNames) != len(expectedPortNames) {
528- + return false, err
529- + }
530- +
531- + portSet := sets.NewString(foundPortNames...)
532- + expectedPortSet := sets.NewString(expectedPortNames...)
533- + return portSet.Equal(expectedPortSet), err
534- + }).Should(BeTrue(), "EndpointSlice should contain all unique ports from the Service without duplicates")
535- + })
536- +
489+
490+ - // Update the Service by adding the remaining ports
491+ svc, err := testVals.infraClient.CoreV1().Services(infraNamespace).Get(context.TODO(), "infra-multiport-service", metav1.GetOptions{})
492+ Expect(err).To(BeNil())
493+
494+ svc.Spec.Ports = servicePorts
495+ -
496+ _, err = testVals.infraClient.CoreV1().Services(infraNamespace).Update(context.TODO(), svc, metav1.UpdateOptions{})
497+ Expect(err).To(BeNil())
498+
499+ var epsListMultiPort *discoveryv1.EndpointSliceList
500+
501+ - // Verify that the EndpointSlice is created with correct unique ports
502+ Eventually(func() (bool, error) {
503+ epsListMultiPort, err = testVals.infraClient.DiscoveryV1().EndpointSlices(infraNamespace).List(context.TODO(), metav1.ListOptions{})
504+ if len(epsListMultiPort.Items) != 1 {
505+ @@ -758,7 +750,6 @@ var _ = g.Describe("KubevirtEPSController", g.Ordered, func() {
506+ }
507+ }
508+
509+ - // Verify that all expected ports are present and without duplicates
510+ if len(foundPortNames) != len(expectedPortNames) {
511+ return false, err
512+ }
513+ @@ -769,5 +760,156 @@ var _ = g.Describe("KubevirtEPSController", g.Ordered, func() {
514+ }).Should(BeTrue(), "EndpointSlice should contain all unique ports from the Service without duplicates")
515+ })
516+
537517+ g.It("Should not panic when Service changes to have a non-nil selector, causing EndpointSlice deletion with no new slices to create", func() {
538518+ createAndAssertVMI("worker-0-test", "ip-10-32-5-13", "123.45.67.89")
539519+ createAndAssertTenantSlice("test-epslice", "tenant-service-name", discoveryv1.AddressTypeIPv4,
0 commit comments