Skip to content

Commit f0ede37

Browse files
committed
feat(load-balancer): support http timeout-idle annotation
Add the `load-balancer.hetzner.cloud/http-timeout-idle` annotation to configure the idle timeout for the client and server side of an HTTP/HTTPS Load Balancer service. It is documented as the new `duration` type (a Go duration string, e.g. `30s`). Closes #1233
1 parent 7e1f686 commit f0ede37

5 files changed

Lines changed: 27 additions & 0 deletions

File tree

docs/reference/load_balancer_annotations.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This page contains all annotations, which can be specified at a Service of type
44

55
- Read-only annotations are set by the Cloud Controller Manager.
66
- Enums are depicted in the `Type` column and possible options are separated via the pipe symbol `|`.
7+
- The `duration` type is a Go duration string, i.e. a sequence of decimal numbers each with a unit suffix such as `300ms`, `30s`, `5m` or `1h` (see [`time.ParseDuration`](https://pkg.go.dev/time#ParseDuration)).
78

89
| Name | Type | Default | Read-only | Description |
910
| --- | --- | --- | --- | --- |
@@ -28,6 +29,7 @@ This page contains all annotations, which can be specified at a Service of type
2829
| `load-balancer.hetzner.cloud/uses-proxyprotocol` | `bool` | `false` | `No` | Specifies if the Load Balancer services should use the proxy protocol. |
2930
| `load-balancer.hetzner.cloud/http-cookie-name` | `string` | `-` | `No` | Specifies the cookie name when using HTTP or HTTPS as protocol. |
3031
| `load-balancer.hetzner.cloud/http-cookie-lifetime` | `int` | `-` | `No` | Specifies the lifetime of the HTTP cookie. |
32+
| `load-balancer.hetzner.cloud/http-timeout-idle` | `duration` | `-` | `No` | Specifies the idle timeout for the client and server side. |
3133
| `load-balancer.hetzner.cloud/certificate-type` | `uploaded \| managed` | `uploaded` | `No` | Defines the type of certificate the Load Balancer should use. |
3234
| `load-balancer.hetzner.cloud/http-certificates` | `string` | `-` | `No` | A comma separated list of IDs or Names of Certificates assigned to the service. |
3335
| `load-balancer.hetzner.cloud/http-managed-certificate-name` | `string` | `-` | `No` | Contains the name of the managed certificate to create by the Cloud Controller manager. Ignored if `load-balancer.hetzner.cloud/certificate-type` is missing or set to "uploaded". |

internal/annotation/load_balancer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ const (
160160
// Type: int
161161
LBSvcHTTPCookieLifetime Name = "load-balancer.hetzner.cloud/http-cookie-lifetime"
162162

163+
// LBSvcHTTPTimeoutIdle specifies the idle timeout for the client and
164+
// server side.
165+
//
166+
// Type: duration
167+
LBSvcHTTPTimeoutIdle Name = "load-balancer.hetzner.cloud/http-timeout-idle"
168+
163169
// LBSvcHTTPCertificateType defines the type of certificate the Load
164170
// Balancer should use.
165171
//

internal/hcops/load_balancer.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ type hclbServiceOptsBuilder struct {
10421042
Certificates []*hcloud.Certificate
10431043
RedirectHTTP *bool
10441044
StickySessions *bool
1045+
TimeoutIdle *time.Duration
10451046
}
10461047
addHTTP bool
10471048
healthCheckOpts struct {
@@ -1115,6 +1116,18 @@ func (b *hclbServiceOptsBuilder) extract() {
11151116
return nil
11161117
})
11171118

1119+
b.do(func() error {
1120+
timeout, err := annotation.LBSvcHTTPTimeoutIdle.DurationFromService(b.Service)
1121+
if errors.Is(err, annotation.ErrNotSet) {
1122+
return nil
1123+
}
1124+
if err != nil {
1125+
return fmt.Errorf("%s: %w", op, err)
1126+
}
1127+
b.httpOpts.TimeoutIdle = &timeout
1128+
return nil
1129+
})
1130+
11181131
b.do(func() error {
11191132
certtyp, ok := annotation.LBSvcHTTPCertificateType.StringFromService(b.Service)
11201133
if ok && certtyp == string(hcloud.CertificateTypeManaged) {
@@ -1367,6 +1380,7 @@ func (b *hclbServiceOptsBuilder) buildAddServiceOpts() (hcloud.LoadBalancerAddSe
13671380
Certificates: b.httpOpts.Certificates,
13681381
RedirectHTTP: b.httpOpts.RedirectHTTP,
13691382
StickySessions: b.httpOpts.StickySessions,
1383+
TimeoutIdle: b.httpOpts.TimeoutIdle,
13701384
}
13711385
}
13721386
if b.addHealthCheck {
@@ -1421,6 +1435,7 @@ func (b *hclbServiceOptsBuilder) buildUpdateServiceOpts() (hcloud.LoadBalancerUp
14211435
RedirectHTTP: b.httpOpts.RedirectHTTP,
14221436
Certificates: b.httpOpts.Certificates,
14231437
StickySessions: b.httpOpts.StickySessions,
1438+
TimeoutIdle: b.httpOpts.TimeoutIdle,
14241439
}
14251440
}
14261441
if b.addHealthCheck {

internal/hcops/load_balancer_internal_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func TestHCLBServiceOptsBuilder(t *testing.T) {
120120
annotation.LBSvcHTTPCertificates: "1,3",
121121
annotation.LBSvcRedirectHTTP: "true",
122122
annotation.LBSvcHTTPStickySessions: "true",
123+
annotation.LBSvcHTTPTimeoutIdle: "30s",
123124
},
124125
expectedAddOpts: hcloud.LoadBalancerAddServiceOpts{
125126
ListenPort: new(82),
@@ -131,6 +132,7 @@ func TestHCLBServiceOptsBuilder(t *testing.T) {
131132
Certificates: []*hcloud.Certificate{{ID: 1}, {ID: 3}},
132133
RedirectHTTP: new(true),
133134
StickySessions: new(true),
135+
TimeoutIdle: hcloud.Ptr(30 * time.Second),
134136
},
135137
HealthCheck: &hcloud.LoadBalancerAddServiceOptsHealthCheck{
136138
Protocol: hcloud.LoadBalancerServiceProtocolTCP,
@@ -146,6 +148,7 @@ func TestHCLBServiceOptsBuilder(t *testing.T) {
146148
Certificates: []*hcloud.Certificate{{ID: 1}, {ID: 3}},
147149
RedirectHTTP: new(true),
148150
StickySessions: new(true),
151+
TimeoutIdle: hcloud.Ptr(30 * time.Second),
149152
},
150153
HealthCheck: &hcloud.LoadBalancerUpdateServiceOptsHealthCheck{
151154
Protocol: hcloud.LoadBalancerServiceProtocolTCP,

tools/load_balancer_annotations.md.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ This page contains all annotations, which can be specified at a Service of type
44

55
- Read-only annotations are set by the Cloud Controller Manager.
66
- Enums are depicted in the `Type` column and possible options are separated via the pipe symbol `|`.
7+
- The `duration` type is a Go duration string, i.e. a sequence of decimal numbers each with a unit suffix such as `300ms`, `30s`, `5m` or `1h` (see [`time.ParseDuration`](https://pkg.go.dev/time#ParseDuration)).
78

89
{{.ConstTable}}

0 commit comments

Comments
 (0)