From 3402c09a779a0b46ef3dc2d76a00bb8c2aa1123b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D0=B5=D0=B3=20=D0=91=D0=BE=D1=80=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Mon, 13 Apr 2026 17:07:18 +0200 Subject: [PATCH] controller: added finalizer processing --- app/control/svccont.go | 75 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/app/control/svccont.go b/app/control/svccont.go index 9b9b087..60fa4ed 100644 --- a/app/control/svccont.go +++ b/app/control/svccont.go @@ -127,7 +127,11 @@ func (cont *Controller) addService(obj any) { } } cont.log.Debugf("Service %s/%s forwarded", service.Namespace, service.Name) - err := cont.patchService(service) + err := cont.addStatus(service) + if err != nil { + cont.log.Debugf("Error patch service %s/%s: %v", service.Namespace, service.Name, err) + } + err = cont.addFinalizer(service) if err != nil { cont.log.Debugf("Error patch service %s/%s: %v", service.Namespace, service.Name, err) } @@ -151,7 +155,7 @@ func (cont *Controller) updateService(oldObj, newObj any) { return } } - err := cont.patchService(newService) + err := cont.addStatus(newService) if err != nil { cont.log.Errorf("Error patch service %s/%s: %v", newService.Namespace, newService.Name, err) } @@ -171,6 +175,10 @@ func (cont *Controller) deleteService(obj any) { cont.log.Errorf("Error unforwarding service %s/%s: %v", service.Namespace, service.Name, err) } } + err := cont.deleteFinalizer(service) + if err != nil { + cont.log.Debugf("Error patch service %s/%s: %v", service.Namespace, service.Name, err) + } cont.log.Debugf("Service %s/%s unforwarded", service.Namespace, service.Name) } } @@ -197,12 +205,50 @@ func makeForwardings(service *kubecore.Service) []*Forwarding { return forwardings } -func (cont *Controller) patchService(svc *kubecore.Service) error { +const LoadBalancerFinalizer = "service.kubernetes.io/load-balancer" + +func (cont *Controller) addFinalizer(oldSvc *kubecore.Service) error { var err error - oldData, err := json.Marshal(svc) + for _, finalizer := range oldSvc.ObjectMeta.Finalizers { + if finalizer == LoadBalancerFinalizer { + return err + } + } + newSvc := oldSvc.DeepCopy() + newSvc.ObjectMeta.Finalizers = append(newSvc.ObjectMeta.Finalizers, LoadBalancerFinalizer) + err = cont.patchService(oldSvc, newSvc) if err != nil { return err } + return err +} + +func (cont *Controller) deleteFinalizer(oldSvc *kubecore.Service) error { + var err error + haveFinalizer := false + newFinalizers := make([]string, 0) + for _, finalizer := range oldSvc.ObjectMeta.Finalizers { + if finalizer == LoadBalancerFinalizer { + haveFinalizer = true + } else { + newFinalizers = append(newFinalizers, finalizer) + } + } + if !haveFinalizer { + return err + } + newSvc := oldSvc.DeepCopy() + newSvc.ObjectMeta.Finalizers = newFinalizers + err = cont.patchService(oldSvc, newSvc) + if err != nil { + return err + } + return err +} + +func (cont *Controller) addStatus(oldSvc *kubecore.Service) error { + var err error + newSvc := oldSvc.DeepCopy() ingressMode := kubecore.LoadBalancerIPModeProxy ingresses := make([]kubecore.LoadBalancerIngress, 0) ingresses = append(ingresses, kubecore.LoadBalancerIngress{ @@ -212,13 +258,24 @@ func (cont *Controller) patchService(svc *kubecore.Service) error { status := kubecore.LoadBalancerStatus{ Ingress: ingresses, } - svc.Status.LoadBalancer = status - - newData, err := json.Marshal(svc) + newSvc.Status.LoadBalancer = status + err = cont.patchService(oldSvc, newSvc) if err != nil { return err } + return err +} +func (cont *Controller) patchService(oldSvc, newSvc *kubecore.Service) error { + var err error + oldData, err := json.Marshal(oldSvc) + if err != nil { + return err + } + newData, err := json.Marshal(newSvc) + if err != nil { + return err + } patchBytes, err := k8patch.CreateTwoWayMergePatch(oldData, newData, kubecore.Service{}) if err != nil { return err @@ -228,8 +285,8 @@ func (cont *Controller) patchService(svc *kubecore.Service) error { ctx, _ := context.WithTimeout(cont.ctx, 5*time.Second) patchServiceOpts := k8meta.PatchOptions{} strategy := k8types.StrategicMergePatchType - _, err = cont.clientset.CoreV1().Services(svc.Namespace). - Patch(ctx, svc.Name, strategy, patchBytes, patchServiceOpts, "status") + _, err = cont.clientset.CoreV1().Services(oldSvc.Namespace). + Patch(ctx, oldSvc.Name, strategy, patchBytes, patchServiceOpts, "status") if err != nil { return err }