diff --git a/pkg/provider/cloud.go b/pkg/provider/cloud.go index fab7da0ba..23400c2d7 100644 --- a/pkg/provider/cloud.go +++ b/pkg/provider/cloud.go @@ -58,6 +58,10 @@ type LoadBalancerConfig struct { // CreationPollTimeout determines how many seconds to wait for the load balancer creation CreationPollTimeout *int `yaml:"creationPollTimeout,omitempty"` + + // Selectorless delegate endpointslices creation on third party by + // skipping service selector creation + Selectorless *bool `yaml:"selectorless,omitempty"` } type InstancesV2Config struct { diff --git a/pkg/provider/loadbalancer.go b/pkg/provider/loadbalancer.go index 702bb3845..56cc5587b 100644 --- a/pkg/provider/loadbalancer.go +++ b/pkg/provider/loadbalancer.go @@ -198,11 +198,13 @@ func (lb *loadbalancer) createLoadBalancerService(ctx context.Context, lbName st }, Spec: corev1.ServiceSpec{ Ports: ports, - Selector: vmiLabels, Type: corev1.ServiceTypeLoadBalancer, ExternalTrafficPolicy: service.Spec.ExternalTrafficPolicy, }, } + if lb.config.Selectorless == nil || !*lb.config.Selectorless { + lbService.Spec.Selector = vmiLabels + } if len(service.Spec.ExternalIPs) > 0 { lbService.Spec.ExternalIPs = service.Spec.ExternalIPs } diff --git a/pkg/provider/loadbalancer_test.go b/pkg/provider/loadbalancer_test.go index ccb73e3bc..c7297b9f0 100644 --- a/pkg/provider/loadbalancer_test.go +++ b/pkg/provider/loadbalancer_test.go @@ -245,7 +245,7 @@ var _ = Describe("LoadBalancer", func() { loadBalancerIP string ) - BeforeAll(func() { + BeforeEach(func() { ctrl, ctx = gomock.WithContext(context.Background(), GinkgoT()) c = mockclient.NewMockClient(ctrl) lb = &loadbalancer{ @@ -402,6 +402,68 @@ var _ = Describe("LoadBalancer", func() { }) + It("Should create new Service without selector if selectorless flag is true", func() { + checkSvcExistErr := notFoundErr + getCount := 1 + port := 30001 + infraServiceExist := generateInfraService( + tenantService, + []corev1.ServicePort{ + {Name: "port1", Protocol: corev1.ProtocolTCP, Port: 80, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: int32(port)}}, + }, + ) + infraServiceExist.Status = corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + IP: loadBalancerIP, + }, + }, + }, + } + + c.EXPECT(). + Get(ctx, client.ObjectKey{Name: "af6ebf1722bb111e9b210d663bd873d9", Namespace: "test"}, gomock.AssignableToTypeOf(&corev1.Service{})). + Return(checkSvcExistErr) + + infraService1 := generateInfraService( + tenantService, + []corev1.ServicePort{ + {Name: "port1", Protocol: corev1.ProtocolTCP, Port: 80, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: 30001}}, + }, + ) + infraService1.Spec.Selector = nil + + c.EXPECT().Create(ctx, infraService1) + + for i := 0; i < getCount; i++ { + infraService2 := infraService1.DeepCopy() + if i == getCount-1 { + infraService2.Status = corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + IP: loadBalancerIP, + }, + }, + }, + } + } + c.EXPECT().Get( + ctx, + client.ObjectKey{Name: "af6ebf1722bb111e9b210d663bd873d9", Namespace: "test"}, + gomock.AssignableToTypeOf(&corev1.Service{}), + ).Do(func(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) { + infraService2.DeepCopyInto(obj.(*corev1.Service)) + }) + } + lb.config.Selectorless = pointer.Bool(true) + lbStatus, err := lb.EnsureLoadBalancer(ctx, clusterName, tenantService, nodes) + Expect(err).To(BeNil()) + Expect(len(lbStatus.Ingress)).Should(Equal(1)) + Expect(lbStatus.Ingress[0].IP).Should(Equal(loadBalancerIP)) + + }) It("Should return an error if service already exist", func() { expectedError := errors.New("Test error - check if service already exist") port := 30001