Skip to content

Commit 572e458

Browse files
authored
Release v0.15.1 #minor
1 parent 239b7a3 commit 572e458

File tree

1 file changed

+65
-3
lines changed

1 file changed

+65
-3
lines changed

vultr/loadbalancers.go

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net"
1010
"strconv"
1111
"strings"
12+
"time"
1213

1314
"github.com/asaskevich/govalidator"
1415
"github.com/vultr/govultr/v3"
@@ -186,7 +187,7 @@ func (l *loadbalancers) EnsureLoadBalancer(ctx context.Context, clusterName stri
186187
// Check if creation is disabled
187188
if create, ok := service.Annotations[annoVultrLoadBalancerCreate]; ok {
188189
if strings.EqualFold(create, "false") {
189-
return nil, fmt.Errorf("%s set to %s - load balancer will not be created", annoVultrLoadBalancerCreate, create)
190+
return nil, cloudprovider.ImplementedElsewhere
190191
}
191192
}
192193

@@ -216,12 +217,18 @@ func (l *loadbalancers) EnsureLoadBalancer(ctx context.Context, clusterName stri
216217
return nil, fmt.Errorf("load-balancer is not yet active - current status: %s", lb.Status)
217218
}
218219

219-
// Update load balancer configuration (pass the lb to avoid another API call)
220220
if updateErr := l.updateLoadBalancerWithLB(ctx, clusterName, service, nodes, lb); updateErr != nil {
221+
if isLBActivating(updateErr) {
222+
ingress := l.buildLoadBalancerIngress(service, lb)
223+
if len(ingress) > 0 {
224+
klog.V(2).Infof("LB %s update deferred: nodes still activating; returning current ingress and retrying in background", lb.ID)
225+
l.retryLBUpdateAsync(ctx, lb.ID, clusterName, service, nodes)
226+
return &v1.LoadBalancerStatus{Ingress: ingress}, nil
227+
}
228+
}
221229
return nil, updateErr
222230
}
223231

224-
// Build and return status from the lb we already have
225232
ingress := l.buildLoadBalancerIngress(service, lb)
226233
return &v1.LoadBalancerStatus{
227234
Ingress: ingress,
@@ -1250,3 +1257,58 @@ func checkEnabledIPv6(service *v1.Service) bool {
12501257

12511258
return false
12521259
}
1260+
1261+
func isLBActivating(err error) bool {
1262+
if err == nil {
1263+
return false
1264+
}
1265+
msg := strings.ToLower(err.Error())
1266+
return strings.Contains(msg, "still activating") ||
1267+
strings.Contains(msg, "activation in progress") ||
1268+
strings.Contains(msg, "activating")
1269+
}
1270+
1271+
func (l *loadbalancers) retryLBUpdateAsync(ctx context.Context, lbID, clusterName string, service *v1.Service, nodes []*v1.Node) {
1272+
bgCtx, cancel := context.WithTimeout(ctx, 10*time.Minute)
1273+
1274+
go func() {
1275+
defer cancel()
1276+
1277+
backoffs := []time.Duration{
1278+
2 * time.Second,
1279+
3 * time.Second,
1280+
5 * time.Second,
1281+
8 * time.Second,
1282+
13 * time.Second,
1283+
21 * time.Second,
1284+
34 * time.Second,
1285+
}
1286+
1287+
for _, d := range backoffs {
1288+
select {
1289+
case <-bgCtx.Done():
1290+
klog.V(3).Infof("Background LB %s update canceled/expired: %v", lbID, bgCtx.Err())
1291+
return
1292+
case <-time.After(d):
1293+
}
1294+
1295+
lb, getErr := l.getVultrLB(bgCtx, service)
1296+
if getErr != nil {
1297+
klog.V(4).Infof("Background LB %s: getVultrLB failed, will retry: %v", lbID, getErr)
1298+
continue
1299+
}
1300+
1301+
if err := l.updateLoadBalancerWithLB(bgCtx, clusterName, service, nodes, lb); err != nil {
1302+
if isLBActivating(err) {
1303+
klog.V(4).Infof("Background LB %s update still activating, will retry: %v", lbID, err)
1304+
continue
1305+
}
1306+
klog.V(3).Infof("Background LB %s update stopped (non-activating error): %v", lbID, err)
1307+
return
1308+
}
1309+
1310+
klog.V(2).Infof("Background LB %s update finalized after activation", lbID)
1311+
return
1312+
}
1313+
}()
1314+
}

0 commit comments

Comments
 (0)