Skip to content

Commit ca116c2

Browse files
committed
feat(lb): implement ConnectionRateLimit, EnableAccessLogs and EnableHTTP3
1 parent 495a2bb commit ca116c2

File tree

3 files changed

+444
-20
lines changed

3 files changed

+444
-20
lines changed

scaleway/loadbalancers.go

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -963,11 +963,32 @@ func servicePortToFrontend(service *v1.Service, loadbalancer *scwlb.LB, port v1.
963963
return nil, fmt.Errorf("error getting certificate IDs for loadbalancer %s: %v", loadbalancer.ID, err)
964964
}
965965

966+
connectionRateLimit, err := getConnectionRateLimit(service)
967+
if err != nil {
968+
return nil, fmt.Errorf("error getting %s annotation for loadbalancer %s: %v",
969+
serviceAnnotationLoadBalancerConnectionRateLimit, loadbalancer.ID, err)
970+
}
971+
972+
enableAccessLogs, err := getEnableAccessLogs(service)
973+
if err != nil {
974+
return nil, fmt.Errorf("error getting %s annotation for loadbalancer %s: %v",
975+
serviceAnnotationLoadBalancerEnableAccessLogs, loadbalancer.ID, err)
976+
}
977+
978+
enableHTTP3, err := getEnableHTTP3(service)
979+
if err != nil {
980+
return nil, fmt.Errorf("error getting %s annotation for loadbalancer %s: %v",
981+
serviceAnnotationLoadBalancerEnableHTTP3, loadbalancer.ID, err)
982+
}
983+
966984
return &scwlb.Frontend{
967-
Name: fmt.Sprintf("%s_tcp_%d", string(service.UID), port.Port),
968-
InboundPort: port.Port,
969-
TimeoutClient: &timeoutClient,
970-
CertificateIDs: certificateIDs,
985+
Name: fmt.Sprintf("%s_tcp_%d", string(service.UID), port.Port),
986+
InboundPort: port.Port,
987+
TimeoutClient: &timeoutClient,
988+
ConnectionRateLimit: connectionRateLimit,
989+
CertificateIDs: certificateIDs,
990+
EnableAccessLogs: enableAccessLogs,
991+
EnableHTTP3: enableHTTP3,
971992
}, nil
972993
}
973994

@@ -1219,6 +1240,21 @@ func frontendEquals(got, want *scwlb.Frontend) bool {
12191240
return false
12201241
}
12211242

1243+
if !uint32PtrEqual(got.ConnectionRateLimit, want.ConnectionRateLimit) {
1244+
klog.V(3).Infof("frontend.ConnectionRateLimit: %s - %s", ptrUint32ToString(got.ConnectionRateLimit), ptrUint32ToString(want.ConnectionRateLimit))
1245+
return false
1246+
}
1247+
1248+
if got.EnableAccessLogs != want.EnableAccessLogs {
1249+
klog.V(3).Infof("frontend.EnableAccessLogs: %t - %t", got.EnableAccessLogs, want.EnableAccessLogs)
1250+
return false
1251+
}
1252+
1253+
if got.EnableHTTP3 != want.EnableHTTP3 {
1254+
klog.V(3).Infof("frontend.EnableHTTP3: %t - %t", got.EnableHTTP3, want.EnableHTTP3)
1255+
return false
1256+
}
1257+
12221258
return true
12231259
}
12241260

@@ -1547,14 +1583,16 @@ func (l *loadbalancers) updateBackend(service *v1.Service, loadbalancer *scwlb.L
15471583
// createFrontend creates a frontend on the load balancer
15481584
func (l *loadbalancers) createFrontend(service *v1.Service, loadbalancer *scwlb.LB, frontend *scwlb.Frontend, backend *scwlb.Backend) (*scwlb.Frontend, error) {
15491585
f, err := l.api.CreateFrontend(&scwlb.ZonedAPICreateFrontendRequest{
1550-
Zone: loadbalancer.Zone,
1551-
LBID: loadbalancer.ID,
1552-
Name: frontend.Name,
1553-
InboundPort: frontend.InboundPort,
1554-
BackendID: backend.ID,
1555-
TimeoutClient: frontend.TimeoutClient,
1556-
CertificateIDs: &frontend.CertificateIDs,
1557-
EnableHTTP3: frontend.EnableHTTP3,
1586+
Zone: loadbalancer.Zone,
1587+
LBID: loadbalancer.ID,
1588+
Name: frontend.Name,
1589+
InboundPort: frontend.InboundPort,
1590+
BackendID: backend.ID,
1591+
TimeoutClient: frontend.TimeoutClient,
1592+
CertificateIDs: &frontend.CertificateIDs,
1593+
ConnectionRateLimit: frontend.ConnectionRateLimit,
1594+
EnableAccessLogs: frontend.EnableAccessLogs,
1595+
EnableHTTP3: frontend.EnableHTTP3,
15581596
})
15591597

15601598
return f, err
@@ -1563,14 +1601,16 @@ func (l *loadbalancers) createFrontend(service *v1.Service, loadbalancer *scwlb.
15631601
// updateFrontend updates a frontend on the load balancer
15641602
func (l *loadbalancers) updateFrontend(service *v1.Service, loadbalancer *scwlb.LB, frontend *scwlb.Frontend, backend *scwlb.Backend) (*scwlb.Frontend, error) {
15651603
f, err := l.api.UpdateFrontend(&scwlb.ZonedAPIUpdateFrontendRequest{
1566-
Zone: loadbalancer.Zone,
1567-
FrontendID: frontend.ID,
1568-
Name: frontend.Name,
1569-
InboundPort: frontend.InboundPort,
1570-
BackendID: backend.ID,
1571-
TimeoutClient: frontend.TimeoutClient,
1572-
CertificateIDs: &frontend.CertificateIDs,
1573-
EnableHTTP3: frontend.EnableHTTP3,
1604+
Zone: loadbalancer.Zone,
1605+
FrontendID: frontend.ID,
1606+
Name: frontend.Name,
1607+
InboundPort: frontend.InboundPort,
1608+
BackendID: backend.ID,
1609+
TimeoutClient: frontend.TimeoutClient,
1610+
CertificateIDs: &frontend.CertificateIDs,
1611+
ConnectionRateLimit: frontend.ConnectionRateLimit,
1612+
EnableAccessLogs: &frontend.EnableAccessLogs,
1613+
EnableHTTP3: frontend.EnableHTTP3,
15741614
})
15751615

15761616
return f, err
@@ -1634,6 +1674,17 @@ func int32PtrEqual(got, want *int32) bool {
16341674
return *got == *want
16351675
}
16361676

1677+
// uint32PtrEqual returns true if both integers are equal
1678+
func uint32PtrEqual(got, want *uint32) bool {
1679+
if got == nil && want == nil {
1680+
return true
1681+
}
1682+
if got == nil || want == nil {
1683+
return false
1684+
}
1685+
return *got == *want
1686+
}
1687+
16371688
// chunkArray takes an array and split it in chunks of a given size
16381689
func chunkArray(array []string, maxChunkSize int) [][]string {
16391690
result := [][]string{}
@@ -1717,6 +1768,13 @@ func ptrInt32ToString(i *int32) string {
17171768
return fmt.Sprintf("%d", *i)
17181769
}
17191770

1771+
func ptrUint32ToString(i *uint32) string {
1772+
if i == nil {
1773+
return "<nil>"
1774+
}
1775+
return fmt.Sprintf("%d", *i)
1776+
}
1777+
17201778
func ptrBoolToString(b *bool) string {
17211779
if b == nil {
17221780
return "<nil>"

scaleway/loadbalancers_annotations.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ const (
107107
// serviceAnnotationLoadBalancerZone is the zone to create the load balancer
108108
serviceAnnotationLoadBalancerZone = "service.beta.kubernetes.io/scw-loadbalancer-zone"
109109

110+
// serviceAnnotationLoadBalancerConnectionRateLimit is the annotation to set the incoming connection rate limit per second.
111+
// Set to 0 to disable the rate limit
112+
serviceAnnotationLoadBalancerConnectionRateLimit = "service.beta.kubernetes.io/scw-loadbalancer-connection-rate-limit"
113+
114+
// serviceAnnotationLoadBalancerEnableAccessLogs is the annotation to enable access logs for the load balancer.
115+
// The default value is "false". The possible values are "false" or "true".
116+
serviceAnnotationLoadBalancerEnableAccessLogs = "service.beta.kubernetes.io/scw-loadbalancer-enable-access-logs"
117+
118+
// serviceAnnotationLoadBalancerEnableHTTP3 is the annotation to enable HTTP/3 protocol for the load balancer.
119+
// The default value is "false". The possible values are "false" or "true".
120+
serviceAnnotationLoadBalancerEnableHTTP3 = "service.beta.kubernetes.io/scw-loadbalancer-enable-http3"
121+
110122
// serviceAnnotationLoadBalancerTimeoutClient is the maximum client connection inactivity time
111123
// The default value is "10m". The duration are go's time.Duration (ex: "1s", "2m", "4h", ...)
112124
serviceAnnotationLoadBalancerTimeoutClient = "service.beta.kubernetes.io/scw-loadbalancer-timeout-client"
@@ -957,3 +969,33 @@ func getKeyValueFromAnnotation(annotation string) map[string]string {
957969

958970
return additionalTags
959971
}
972+
973+
func getConnectionRateLimit(service *v1.Service) (*uint32, error) {
974+
connectionRateLimit, ok := service.Annotations[serviceAnnotationLoadBalancerConnectionRateLimit]
975+
if !ok {
976+
return nil, nil
977+
}
978+
connectionRateLimitInt, err := strconv.Atoi(connectionRateLimit)
979+
if err != nil {
980+
klog.Errorf("invalid value for annotation %s", serviceAnnotationLoadBalancerConnectionRateLimit)
981+
return nil, errLoadBalancerInvalidAnnotation
982+
}
983+
connectionRateLimitUint32 := uint32(connectionRateLimitInt)
984+
return &connectionRateLimitUint32, nil
985+
}
986+
987+
func getEnableAccessLogs(service *v1.Service) (bool, error) {
988+
enableAccessLogs, ok := service.Annotations[serviceAnnotationLoadBalancerEnableAccessLogs]
989+
if !ok {
990+
return false, nil
991+
}
992+
return strconv.ParseBool(enableAccessLogs)
993+
}
994+
995+
func getEnableHTTP3(service *v1.Service) (bool, error) {
996+
enableHTTP3, ok := service.Annotations[serviceAnnotationLoadBalancerEnableHTTP3]
997+
if !ok {
998+
return false, nil
999+
}
1000+
return strconv.ParseBool(enableHTTP3)
1001+
}

0 commit comments

Comments
 (0)