From 3d70836e5c394961fd23573ff386ebf8f0fec421 Mon Sep 17 00:00:00 2001 From: pavel <36902936+pavel-github@users.noreply.github.com> Date: Tue, 22 Oct 2024 03:10:42 +0200 Subject: [PATCH] wip --- internal/xelon/load_balancers.go | 95 +++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/internal/xelon/load_balancers.go b/internal/xelon/load_balancers.go index 6bc5c8e..88bf5a1 100644 --- a/internal/xelon/load_balancers.go +++ b/internal/xelon/load_balancers.go @@ -415,45 +415,78 @@ func (l *loadBalancers) updateLoadBalancer(ctx context.Context, xlb *xelonLoadBa patcher := newServicePatcher(l.client.k8s, service) defer func() { _ = patcher.Patch(ctx) }() - // clean up old rules + var definedForwardingRuleIDs []string if forwardingRuleIDs, ok := service.Annotations[serviceAnnotationLoadBalancerClusterForwardingRuleIDs]; ok && forwardingRuleIDs != "" { - logger.Info("Deleting previously specified forwarding rules", "forwarding_rule_ids", forwardingRuleIDs) - definedForwardingRuleIDs := strings.Split(forwardingRuleIDs, ",") - - for _, definedForwardingRuleID := range definedForwardingRuleIDs { - resp, err := l.client.xelon.LoadBalancerClusters.DeleteForwardingRule(ctx, xlb.clusterID, xlb.virtualIPID, definedForwardingRuleID) - if err != nil { - if resp != nil && resp.StatusCode == http.StatusNotFound { - logger.Info("Skipping not existing forwarding rule", "forwarding_rule_id", definedForwardingRuleID) - } else { - return err - } - } - } - updateServiceAnnotation(service, serviceAnnotationLoadBalancerClusterForwardingRuleIDs, "") + definedForwardingRuleIDs = strings.Split(forwardingRuleIDs, ",") } - // build forwarding rules - logger.Info("Building forwarding rules request") - var forwardingRules []xelon.LoadBalancerClusterForwardingRule - for _, port := range service.Spec.Ports { - forwardingRule := xelon.LoadBalancerClusterForwardingRule{ - Backend: &xelon.LoadBalancerClusterForwardingRuleConfiguration{Port: int(port.NodePort)}, - Frontend: &xelon.LoadBalancerClusterForwardingRuleConfiguration{Port: int(port.Port)}, - } - forwardingRules = append(forwardingRules, forwardingRule) - } - - rules, _, err := l.client.xelon.LoadBalancerClusters.CreateForwardingRules(ctx, xlb.clusterID, xlb.virtualIPID, forwardingRules) + existingForwardingRules, _, err := l.client.xelon.LoadBalancerClusters.ListForwardingRules(ctx, xlb.clusterID, xlb.virtualIPID) if err != nil { return err } - logger.Info("Created forwarding rules", "rules", rules) + xlbUsedPorts := make(map[int]bool, len(existingForwardingRules)) + for _, existingForwardingRule := range existingForwardingRules { + xlbUsedPorts[existingForwardingRule.Frontend.Port] = true + } var frontendRules []string - for _, rule := range rules { - if rule.Frontend != nil { - frontendRules = append(frontendRules, rule.Frontend.ID) + for _, port := range service.Spec.Ports { + portNo := int(port.Port) + portExists := xlbUsedPorts[portNo] + delete(xlbUsedPorts, portNo) + + if portExists { + logger.Info("Update existing forwarding rule", "port", portNo) + + forwardingRuleID := "" + for _, existingForwardingRule := range existingForwardingRules { + if slices.Contains(definedForwardingRuleIDs, existingForwardingRule.Frontend.ID) { + forwardingRuleID = existingForwardingRule.Frontend.ID + } + } + updateRequest := &xelon.LoadBalancerClusterForwardingRuleConfiguration{ + ID: forwardingRuleID, + Port: portNo, + } + _, _, err := l.client.xelon.LoadBalancerClusters.UpdateForwardingRule(ctx, xlb.clusterID, xlb.virtualIPID, forwardingRuleID, updateRequest) + if err != nil { + return err + } + frontendRules = append(frontendRules, forwardingRuleID) + } else { + logger.Info("Create new forwarding rule", "port", portNo) + + forwardingRule := []xelon.LoadBalancerClusterForwardingRule{{ + Backend: &xelon.LoadBalancerClusterForwardingRuleConfiguration{Port: int(port.NodePort)}, + Frontend: &xelon.LoadBalancerClusterForwardingRuleConfiguration{Port: portNo}, + }} + + rules, _, err := l.client.xelon.LoadBalancerClusters.CreateForwardingRules(ctx, xlb.clusterID, xlb.virtualIPID, forwardingRule) + if err != nil { + return err + } + for _, rule := range rules { + if rule.Frontend != nil { + frontendRules = append(frontendRules, rule.Frontend.ID) + } + } + } + } + + // remove any leftovers ports + for port := range xlbUsedPorts { + for _, existingForwardingRule := range existingForwardingRules { + if existingForwardingRule.Frontend.Port == port { + logger.Info("Deleting leftover forwarding rule", "port", port, "frontend_id", existingForwardingRule.Frontend.ID) + resp, err := l.client.xelon.LoadBalancerClusters.DeleteForwardingRule(ctx, xlb.clusterID, xlb.virtualIPID, existingForwardingRule.Frontend.ID) + if err != nil { + if resp != nil && resp.StatusCode == http.StatusNotFound { + logger.Info("Skipping not existing forwarding rule", "forwarding_rule_id", existingForwardingRule.Frontend.ID) + } else { + return err + } + } + } } }