From dff34b4d7d5199ed553cc0222d426574ab778876 Mon Sep 17 00:00:00 2001 From: Martin Schuppert Date: Thu, 20 Jun 2024 17:06:37 +0200 Subject: [PATCH] [svc] return error if no LoadBalancer IP If there is an issue with the LoadBalancer service in the cluster, like the MetalLB instance is down, or the requested IP using the metallb.universe.tf/loadBalancerIPs annotation is outside the configured range of the IPAddressPool, the k8s LoadBalancert service External-IP is stuck in pending. This would not allow dataplane service to connect to the service. This change returns an error in this case to reflect that there is an issue with the k8s service, which needs to be fixed and the consumer of the func can reconcile to wait for a LoadBalancer IP to be available. Signed-off-by: Martin Schuppert --- modules/common/service/service.go | 2 ++ modules/common/test/functional/service_test.go | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/common/service/service.go b/modules/common/service/service.go index b33f4340..ea52e794 100644 --- a/modules/common/service/service.go +++ b/modules/common/service/service.go @@ -338,6 +338,8 @@ func (s *Service) CreateOrPatch( for _, ingr := range service.Status.LoadBalancer.Ingress { s.externalIPs = append(s.externalIPs, ingr.IP) } + } else { + return ctrl.Result{}, fmt.Errorf("%s LoadBalancer IP still pending", s.service.Name) } } diff --git a/modules/common/test/functional/service_test.go b/modules/common/test/functional/service_test.go index 6b847602..cc185001 100644 --- a/modules/common/test/functional/service_test.go +++ b/modules/common/test/functional/service_test.go @@ -221,10 +221,26 @@ var _ = Describe("service package", func() { Expect(err).ShouldNot(HaveOccurred()) _, err = s.CreateOrPatch(ctx, h) - Expect(err).ShouldNot(HaveOccurred()) + // when LoadBalancer service gets created and LB has not assigned an LB IP we exect an error + Expect(err).Should(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("test-svc LoadBalancer IP still pending")) + svc := th.AssertServiceExists(types.NamespacedName{Namespace: namespace, Name: "test-svc"}) Expect(svc.Spec.Type).To(Equal(corev1.ServiceTypeLoadBalancer)) + // simulate LoadBalancer assigned IP and updated the k8s service to have a LB IP + svc.Status.LoadBalancer.Ingress = []corev1.LoadBalancerIngress{ + { + IP: "1.1.1.1", + }, + } + Expect(th.K8sClient.Status().Update(ctx, svc)).Should(Succeed()) + + // No LB IP still pending error should _NOT_ occure + _, err = s.CreateOrPatch(ctx, h) + Expect(err).ShouldNot(HaveOccurred()) + Expect(s.GetExternalIPs()).To(Equal([]string{"1.1.1.1"})) + // NONE endpoint with port endpointURL, err := s.GetAPIEndpoint(nil, ptr.To(service.ProtocolNone), "") Expect(err).ShouldNot(HaveOccurred())