Skip to content

Commit 944bc4a

Browse files
authored
Merge pull request #228 from nox-404/fix-unsupported-udp
fix: duplicate backends for service with unsuported udp ports
2 parents 0fc984a + 3786a46 commit 944bc4a

2 files changed

Lines changed: 96 additions & 50 deletions

File tree

scaleway/loadbalancers.go

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ func servicePortToFrontend(service *v1.Service, loadbalancer *scwlb.LB, port v1.
11121112
}
11131113

11141114
return &scwlb.Frontend{
1115-
Name: fmt.Sprintf("%s_tcp_%d", string(service.UID), port.Port),
1115+
Name: fmt.Sprintf("%s_%s_%d", string(service.UID), strings.ToLower(string(port.Protocol)), port.Port),
11161116
InboundPort: port.Port,
11171117
TimeoutClient: &timeoutClient,
11181118
ConnectionRateLimit: connectionRateLimit,
@@ -1294,7 +1294,7 @@ func servicePortToBackend(service *v1.Service, loadbalancer *scwlb.LB, port v1.S
12941294
healthCheck.TransientCheckDelay = healthCheckTransientCheckDelay
12951295

12961296
backend := &scwlb.Backend{
1297-
Name: fmt.Sprintf("%s_tcp_%d", string(service.UID), port.NodePort),
1297+
Name: fmt.Sprintf("%s_%s_%d", string(service.UID), strings.ToLower(string(port.Protocol)), port.NodePort),
12981298
Pool: nodeIPs,
12991299
ForwardProtocol: protocol,
13001300
SslBridging: &sslBridging,
@@ -1332,25 +1332,30 @@ func servicePortToBackend(service *v1.Service, loadbalancer *scwlb.LB, port v1.S
13321332

13331333
// serviceToLB converts a service definition to a list of load balancer frontends and backends
13341334
func serviceToLB(service *v1.Service, loadbalancer *scwlb.LB, nodeIPs []string) (map[int32]*scwlb.Frontend, map[int32]*scwlb.Backend, error) {
1335-
frontends := map[int32]*scwlb.Frontend{}
1336-
backends := map[int32]*scwlb.Backend{}
1335+
tcpFrontends := map[int32]*scwlb.Frontend{}
1336+
tcpBackends := map[int32]*scwlb.Backend{}
13371337

13381338
for _, port := range service.Spec.Ports {
1339-
frontend, err := servicePortToFrontend(service, loadbalancer, port)
1339+
if port.Protocol != v1.ProtocolTCP {
1340+
klog.V(3).Infof("skipping unsupported protocol %s for port %d in service %s/%s", port.Protocol, port.Port, service.Namespace, service.Name)
1341+
continue
1342+
}
1343+
1344+
tcpFrontend, err := servicePortToFrontend(service, loadbalancer, port)
13401345
if err != nil {
13411346
return nil, nil, fmt.Errorf("failed to prepare frontend for port %d: %v", port.Port, err)
13421347
}
13431348

1344-
backend, err := servicePortToBackend(service, loadbalancer, port, nodeIPs)
1349+
tcpBackend, err := servicePortToBackend(service, loadbalancer, port, nodeIPs)
13451350
if err != nil {
13461351
return nil, nil, fmt.Errorf("failed to prepare backend for port %d: %v", port.Port, err)
13471352
}
13481353

1349-
frontends[port.Port] = frontend
1350-
backends[port.NodePort] = backend
1354+
tcpFrontends[port.Port] = tcpFrontend
1355+
tcpBackends[port.NodePort] = tcpBackend
13511356
}
13521357

1353-
return frontends, backends, nil
1358+
return tcpFrontends, tcpBackends, nil
13541359
}
13551360

13561361
// frontendEquals returns true if the two frontends configuration are equal
@@ -1484,7 +1489,7 @@ func backendEquals(got, want *scwlb.Backend) bool {
14841489
}
14851490

14861491
type frontendOps struct {
1487-
remove map[int32]*scwlb.Frontend
1492+
remove []*scwlb.Frontend
14881493
update map[int32]*scwlb.Frontend
14891494
create map[int32]*scwlb.Frontend
14901495
keep map[int32]*scwlb.Frontend
@@ -1493,42 +1498,42 @@ type frontendOps struct {
14931498
// compareFrontends returns the frontends operation to do to achieve the wanted configuration
14941499
// will ignore frontends with names not starting with the filterPrefix if provided
14951500
func compareFrontends(got []*scwlb.Frontend, want map[int32]*scwlb.Frontend, filterPrefix string) frontendOps {
1496-
remove := make(map[int32]*scwlb.Frontend)
1501+
remove := make([]*scwlb.Frontend, 0)
14971502
update := make(map[int32]*scwlb.Frontend)
14981503
create := make(map[int32]*scwlb.Frontend)
14991504
keep := make(map[int32]*scwlb.Frontend)
15001505

1501-
filteredGot := make([]*scwlb.Frontend, 0, len(got))
1506+
lbEvaluatedFrontendMap := make(map[int32]*scwlb.Frontend)
1507+
1508+
// Check for deletions and updates
15021509
for _, current := range got {
1503-
if strings.HasPrefix(current.Name, filterPrefix) {
1504-
filteredGot = append(filteredGot, current)
1510+
if !strings.HasPrefix(current.Name, filterPrefix) {
1511+
continue
1512+
}
1513+
1514+
// Will remove duplicated frontends with the same InboundPort.
1515+
if _, ok := lbEvaluatedFrontendMap[current.InboundPort]; ok {
1516+
remove = append(remove, current)
1517+
continue
1518+
} else {
1519+
lbEvaluatedFrontendMap[current.InboundPort] = current
15051520
}
1506-
}
15071521

1508-
// Check for deletions and updates
1509-
for _, current := range filteredGot {
15101522
if target, ok := want[current.InboundPort]; ok {
1511-
if !frontendEquals(current, target) {
1523+
if frontendEquals(current, target) {
1524+
keep[target.InboundPort] = current
1525+
} else {
15121526
target.ID = current.ID
15131527
update[target.InboundPort] = target
1514-
} else {
1515-
keep[target.InboundPort] = current
15161528
}
15171529
} else {
1518-
remove[current.InboundPort] = current
1530+
remove = append(remove, current)
15191531
}
15201532
}
15211533

15221534
// Check for additions
15231535
for _, target := range want {
1524-
found := false
1525-
for _, current := range filteredGot {
1526-
if current.InboundPort == target.InboundPort {
1527-
found = true
1528-
break
1529-
}
1530-
}
1531-
if !found {
1536+
if _, ok := lbEvaluatedFrontendMap[target.InboundPort]; !ok {
15321537
create[target.InboundPort] = target
15331538
}
15341539
}
@@ -1542,50 +1547,50 @@ func compareFrontends(got []*scwlb.Frontend, want map[int32]*scwlb.Frontend, fil
15421547
}
15431548

15441549
type backendOps struct {
1545-
remove map[int32]*scwlb.Backend
1550+
remove []*scwlb.Backend
15461551
update map[int32]*scwlb.Backend
15471552
create map[int32]*scwlb.Backend
15481553
keep map[int32]*scwlb.Backend
15491554
}
15501555

15511556
// compareBackends returns the backends operation to do to achieve the wanted configuration
15521557
func compareBackends(got []*scwlb.Backend, want map[int32]*scwlb.Backend, filterPrefix string) backendOps {
1553-
remove := make(map[int32]*scwlb.Backend)
1558+
remove := make([]*scwlb.Backend, 0)
15541559
update := make(map[int32]*scwlb.Backend)
15551560
create := make(map[int32]*scwlb.Backend)
15561561
keep := make(map[int32]*scwlb.Backend)
15571562

1558-
filteredGot := make([]*scwlb.Backend, 0, len(got))
1563+
lbEvaluatedBackendMap := make(map[int32]*scwlb.Backend)
1564+
1565+
// Check for deletions and updates
15591566
for _, current := range got {
1560-
if strings.HasPrefix(current.Name, filterPrefix) {
1561-
filteredGot = append(filteredGot, current)
1567+
if !strings.HasPrefix(current.Name, filterPrefix) {
1568+
continue
1569+
}
1570+
1571+
// Will remove duplicated backends with the same ForwardPort.
1572+
if _, ok := lbEvaluatedBackendMap[current.ForwardPort]; ok {
1573+
remove = append(remove, current)
1574+
continue
1575+
} else {
1576+
lbEvaluatedBackendMap[current.ForwardPort] = current
15621577
}
1563-
}
15641578

1565-
// Check for deletions and updates
1566-
for _, current := range filteredGot {
15671579
if target, ok := want[current.ForwardPort]; ok {
1568-
if !backendEquals(current, target) {
1580+
if backendEquals(current, target) {
1581+
keep[target.ForwardPort] = current
1582+
} else {
15691583
target.ID = current.ID
15701584
update[target.ForwardPort] = target
1571-
} else {
1572-
keep[target.ForwardPort] = current
15731585
}
15741586
} else {
1575-
remove[current.ForwardPort] = current
1587+
remove = append(remove, current)
15761588
}
15771589
}
15781590

15791591
// Check for additions
15801592
for _, target := range want {
1581-
found := false
1582-
for _, current := range filteredGot {
1583-
if current.ForwardPort == target.ForwardPort {
1584-
found = true
1585-
break
1586-
}
1587-
}
1588-
if !found {
1593+
if _, ok := lbEvaluatedBackendMap[target.ForwardPort]; !ok {
15891594
create[target.ForwardPort] = target
15901595
}
15911596
}

scaleway/loadbalancers_test.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ func TestServicePortToFrontend(t *testing.T) {
637637

638638
for _, tt := range matrix {
639639
t.Run(tt.name, func(t *testing.T) {
640-
got, err := servicePortToFrontend(tt.service, &scwlb.LB{ID: "lbid"}, v1.ServicePort{Port: 1234})
640+
got, err := servicePortToFrontend(tt.service, &scwlb.LB{ID: "lbid"}, v1.ServicePort{Port: 1234, Protocol: v1.ProtocolTCP})
641641
if tt.wantErr != (err != nil) {
642642
t.Errorf("got error: %s, expected: %v", err, tt.wantErr)
643643
return
@@ -2607,3 +2607,44 @@ func TestServicePortToBackendWithHealthCheckFromService(t *testing.T) {
26072607
})
26082608
}
26092609
}
2610+
2611+
func TestServiceToLB_UDPPortsIgnored(t *testing.T) {
2612+
service := &v1.Service{
2613+
ObjectMeta: metav1.ObjectMeta{
2614+
UID: "test-uid",
2615+
Annotations: map[string]string{},
2616+
},
2617+
Spec: v1.ServiceSpec{
2618+
Ports: []v1.ServicePort{
2619+
{Port: 80, NodePort: 30080, Protocol: v1.ProtocolTCP},
2620+
{Port: 53, NodePort: 30053, Protocol: v1.ProtocolUDP},
2621+
},
2622+
},
2623+
}
2624+
2625+
frontends, backends, err := serviceToLB(service, &scwlb.LB{ID: "test-lb"}, []string{"10.0.0.1"})
2626+
if err != nil {
2627+
t.Fatalf("serviceToLB() error = %v", err)
2628+
}
2629+
2630+
if _, ok := frontends[80]; !ok {
2631+
t.Error("expected frontend for TCP port 80")
2632+
}
2633+
if _, ok := frontends[53]; ok {
2634+
t.Error("unexpected frontend for UDP port 53")
2635+
}
2636+
2637+
if _, ok := backends[30080]; !ok {
2638+
t.Error("expected backend for TCP nodePort 30080")
2639+
}
2640+
if _, ok := backends[30053]; ok {
2641+
t.Error("unexpected backend for UDP nodePort 30053")
2642+
}
2643+
2644+
if len(frontends) != 1 {
2645+
t.Errorf("expected 1 frontend, got %d", len(frontends))
2646+
}
2647+
if len(backends) != 1 {
2648+
t.Errorf("expected 1 backend, got %d", len(backends))
2649+
}
2650+
}

0 commit comments

Comments
 (0)