From 1ea2ebcc15d61123c0116b2266e6f5ca33a6e7fc Mon Sep 17 00:00:00 2001 From: cyclinder Date: Mon, 14 Nov 2022 10:47:52 +0800 Subject: [PATCH] Annotate a service with the pool used to provide its IP when we have multiple configurations tied to the ipaddresspool, it'd be useful to see which pool was used to assign the ip to a given service. You can see it by looking service's annotation "metallb.universe.tf/ip-allocated-from-pool". Signed-off-by: cyclinder --- controller/main.go | 18 +++++++++++------- controller/service.go | 25 +++++++++++++++++++++++-- e2etest/l2tests/l2.go | 4 ++++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/controller/main.go b/controller/main.go index 93950b08ea1..4b94a452845 100644 --- a/controller/main.go +++ b/controller/main.go @@ -87,14 +87,18 @@ func (c *controller) SetBalancer(l log.Logger, name string, svcRo *v1.Service, _ } if !reflect.DeepEqual(svcRo.Status, svc.Status) { - var st v1.ServiceStatus - st, svc = svc.Status, svcRo.DeepCopy() - svc.Status = st - if err := c.client.UpdateStatus(svc); err != nil { - level.Error(l).Log("op", "updateServiceStatus", "error", err, "msg", "failed to update service status") - return controllers.SyncStateError - } + updateSvcStatus(svc, svcRo) + } + + if !reflect.DeepEqual(svcRo.Annotations, svc.Annotations) { + updateSvcAnnotations(svc, svcRo) } + + if err := c.client.UpdateStatus(svc); err != nil { + level.Error(l).Log("op", "updateServiceStatus", "error", err, "msg", "failed to update service") + return controllers.SyncStateError + } + level.Info(l).Log("event", "serviceUpdated", "msg", "updated service object") return successRes } diff --git a/controller/service.go b/controller/service.go index fae834a735c..20617126bc1 100644 --- a/controller/service.go +++ b/controller/service.go @@ -30,8 +30,9 @@ import ( ) const ( - annotationAddressPool = "metallb.universe.tf/address-pool" - annotationLoadBalancerIPs = "metallb.universe.tf/loadBalancerIPs" + annotationAddressPool = "metallb.universe.tf/address-pool" + annotationLoadBalancerIPs = "metallb.universe.tf/loadBalancerIPs" + annotationIPAllocateFromPool = "metallb.universe.tf/ip-allocated-from-pool" ) func (c *controller) convergeBalancer(l log.Logger, key string, svc *v1.Service) bool { @@ -161,6 +162,10 @@ func (c *controller) convergeBalancer(l log.Logger, key string, svc *v1.Service) lbIngressIPs = append(lbIngressIPs, v1.LoadBalancerIngress{IP: lbIP.String()}) } svc.Status.LoadBalancer.Ingress = lbIngressIPs + if svc.Annotations == nil { + svc.Annotations = make(map[string]string) + } + svc.Annotations[annotationIPAllocateFromPool] = pool return true } @@ -168,6 +173,7 @@ func (c *controller) convergeBalancer(l log.Logger, key string, svc *v1.Service) // this controller. func (c *controller) clearServiceState(key string, svc *v1.Service) { c.ips.Unassign(key) + delete(svc.Annotations, annotationIPAllocateFromPool) svc.Status.LoadBalancer = v1.LoadBalancerStatus{} } @@ -260,3 +266,18 @@ func isEqualIPs(ipsA, ipsB []net.IP) bool { }) return reflect.DeepEqual(ipsA, ipsB) } + +// updateSvcStatus updating svc's status and svcRo's status +func updateSvcStatus(svc, svcRo *v1.Service) { + var st v1.ServiceStatus + st, svc = svc.Status, svcRo.DeepCopy() + // we need be update svcRo's status + svc.Status, svcRo.Status = st, st +} + +// updateSvcAnnotations updating svc's annotations +func updateSvcAnnotations(svc, svcRo *v1.Service) { + var annotations map[string]string + annotations, svc = svc.Annotations, svcRo.DeepCopy() + svc.Annotations = annotations +} diff --git a/e2etest/l2tests/l2.go b/e2etest/l2tests/l2.go index 7e72eb0052f..9df6be7acaf 100644 --- a/e2etest/l2tests/l2.go +++ b/e2etest/l2tests/l2.go @@ -676,10 +676,14 @@ var _ = ginkgo.Describe("L2", func() { err = config.ValidateIPInRange([]metallbv1beta1.IPAddressPool{pool}, ingressIP) framework.ExpectNoError(err) + ginkgo.By("validate annotating a service with the pool used to provide its IP") + framework.ExpectEqual(svc.Annotations["metallb.universe.tf/ip-allocated-from-pool"], pool.Name) + services = append(services, svc) servicesIngressIP = append(servicesIngressIP, ingressIP) for j := 0; j <= i; j++ { + ginkgo.By(fmt.Sprintf("validate service %d IP didn't change", j+1)) ip := e2eservice.GetIngressPoint(&services[j].Status.LoadBalancer.Ingress[0]) framework.ExpectEqual(ip, servicesIngressIP[j])