diff --git a/controller/main.go b/controller/main.go index 93950b08ea1..ba50fc94c6d 100644 --- a/controller/main.go +++ b/controller/main.go @@ -86,16 +86,24 @@ func (c *controller) SetBalancer(l log.Logger, name string, svcRo *v1.Service, _ return successRes } + toWrite := svcRo.DeepCopy() if !reflect.DeepEqual(svcRo.Status, svc.Status) { - var st v1.ServiceStatus - st, svc = svc.Status, svcRo.DeepCopy() - svc.Status = st + toWrite.Status = svc.Status + } + + if !reflect.DeepEqual(svcRo.Annotations, svc.Annotations) { + toWrite.Annotations = svc.Annotations + } + + if !reflect.DeepEqual(toWrite, svcRo) { if err := c.client.UpdateStatus(svc); err != nil { - level.Error(l).Log("op", "updateServiceStatus", "error", err, "msg", "failed to update service status") + 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") } - level.Info(l).Log("event", "serviceUpdated", "msg", "updated service object") + + level.Info(l).Log("event", "serviceUpdated", "msg", "service is not updated") return successRes } diff --git a/controller/service.go b/controller/service.go index fae834a735c..e00fbdede8b 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{} } 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])