diff --git a/docs/reference/load_balancer_annotations.md b/docs/reference/load_balancer_annotations.md index 367c5fa09..633543729 100644 --- a/docs/reference/load_balancer_annotations.md +++ b/docs/reference/load_balancer_annotations.md @@ -4,6 +4,7 @@ This page contains all annotations, which can be specified at a Service of type - Read-only annotations are set by the Cloud Controller Manager. - Enums are depicted in the `Type` column and possible options are separated via the pipe symbol `|`. +- 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)). | Name | Type | Default | Read-only | Description | | --- | --- | --- | --- | --- | @@ -28,6 +29,7 @@ This page contains all annotations, which can be specified at a Service of type | `load-balancer.hetzner.cloud/uses-proxyprotocol` | `bool` | `false` | `No` | Specifies if the Load Balancer services should use the proxy protocol. | | `load-balancer.hetzner.cloud/http-cookie-name` | `string` | `-` | `No` | Specifies the cookie name when using HTTP or HTTPS as protocol. | | `load-balancer.hetzner.cloud/http-cookie-lifetime` | `int` | `-` | `No` | Specifies the lifetime of the HTTP cookie. | +| `load-balancer.hetzner.cloud/http-timeout-idle` | `duration` | `-` | `No` | Specifies the idle timeout for the client and server side. | | `load-balancer.hetzner.cloud/certificate-type` | `uploaded \| managed` | `uploaded` | `No` | Defines the type of certificate the Load Balancer should use. | | `load-balancer.hetzner.cloud/http-certificates` | `string` | `-` | `No` | A comma separated list of IDs or Names of Certificates assigned to the service. | | `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". | diff --git a/internal/annotation/load_balancer.go b/internal/annotation/load_balancer.go index df95f53db..63b09a5d5 100644 --- a/internal/annotation/load_balancer.go +++ b/internal/annotation/load_balancer.go @@ -160,6 +160,12 @@ const ( // Type: int LBSvcHTTPCookieLifetime Name = "load-balancer.hetzner.cloud/http-cookie-lifetime" + // LBSvcHTTPTimeoutIdle specifies the idle timeout for the client and + // server side. + // + // Type: duration + LBSvcHTTPTimeoutIdle Name = "load-balancer.hetzner.cloud/http-timeout-idle" + // LBSvcHTTPCertificateType defines the type of certificate the Load // Balancer should use. // diff --git a/internal/hcops/load_balancer.go b/internal/hcops/load_balancer.go index b4012bf1f..83016aff8 100644 --- a/internal/hcops/load_balancer.go +++ b/internal/hcops/load_balancer.go @@ -1042,6 +1042,7 @@ type hclbServiceOptsBuilder struct { Certificates []*hcloud.Certificate RedirectHTTP *bool StickySessions *bool + TimeoutIdle *time.Duration } addHTTP bool healthCheckOpts struct { @@ -1115,6 +1116,19 @@ func (b *hclbServiceOptsBuilder) extract() { return nil }) + b.do(func() error { + timeout, err := annotation.LBSvcHTTPTimeoutIdle.DurationFromService(b.Service) + if errors.Is(err, annotation.ErrNotSet) { + return nil + } + if err != nil { + return fmt.Errorf("%s: %w", op, err) + } + b.httpOpts.TimeoutIdle = &timeout + b.addHTTP = true + return nil + }) + b.do(func() error { certtyp, ok := annotation.LBSvcHTTPCertificateType.StringFromService(b.Service) if ok && certtyp == string(hcloud.CertificateTypeManaged) { @@ -1367,6 +1381,7 @@ func (b *hclbServiceOptsBuilder) buildAddServiceOpts() (hcloud.LoadBalancerAddSe Certificates: b.httpOpts.Certificates, RedirectHTTP: b.httpOpts.RedirectHTTP, StickySessions: b.httpOpts.StickySessions, + TimeoutIdle: b.httpOpts.TimeoutIdle, } } if b.addHealthCheck { @@ -1421,6 +1436,7 @@ func (b *hclbServiceOptsBuilder) buildUpdateServiceOpts() (hcloud.LoadBalancerUp RedirectHTTP: b.httpOpts.RedirectHTTP, Certificates: b.httpOpts.Certificates, StickySessions: b.httpOpts.StickySessions, + TimeoutIdle: b.httpOpts.TimeoutIdle, } } if b.addHealthCheck { diff --git a/internal/hcops/load_balancer_internal_test.go b/internal/hcops/load_balancer_internal_test.go index d7be5ccd2..ebbd75b3b 100644 --- a/internal/hcops/load_balancer_internal_test.go +++ b/internal/hcops/load_balancer_internal_test.go @@ -120,6 +120,7 @@ func TestHCLBServiceOptsBuilder(t *testing.T) { annotation.LBSvcHTTPCertificates: "1,3", annotation.LBSvcRedirectHTTP: "true", annotation.LBSvcHTTPStickySessions: "true", + annotation.LBSvcHTTPTimeoutIdle: "30s", }, expectedAddOpts: hcloud.LoadBalancerAddServiceOpts{ ListenPort: new(82), @@ -131,6 +132,7 @@ func TestHCLBServiceOptsBuilder(t *testing.T) { Certificates: []*hcloud.Certificate{{ID: 1}, {ID: 3}}, RedirectHTTP: new(true), StickySessions: new(true), + TimeoutIdle: hcloud.Ptr(30 * time.Second), }, HealthCheck: &hcloud.LoadBalancerAddServiceOptsHealthCheck{ Protocol: hcloud.LoadBalancerServiceProtocolTCP, @@ -146,6 +148,7 @@ func TestHCLBServiceOptsBuilder(t *testing.T) { Certificates: []*hcloud.Certificate{{ID: 1}, {ID: 3}}, RedirectHTTP: new(true), StickySessions: new(true), + TimeoutIdle: hcloud.Ptr(30 * time.Second), }, HealthCheck: &hcloud.LoadBalancerUpdateServiceOptsHealthCheck{ Protocol: hcloud.LoadBalancerServiceProtocolTCP, diff --git a/tools/load_balancer_annotations.md.tmpl b/tools/load_balancer_annotations.md.tmpl index cc50d3251..5f56df870 100644 --- a/tools/load_balancer_annotations.md.tmpl +++ b/tools/load_balancer_annotations.md.tmpl @@ -4,5 +4,6 @@ This page contains all annotations, which can be specified at a Service of type - Read-only annotations are set by the Cloud Controller Manager. - Enums are depicted in the `Type` column and possible options are separated via the pipe symbol `|`. +- 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)). {{.ConstTable}}